blob: 00114e1f929100d4e10014c8640a0171708046fa [file] [log] [blame]
drhd1bf3512001-04-07 15:24:33 +00001/*
drhb19a2bc2001-09-16 00:13:26 +00002** 2001 September 15
drhd1bf3512001-04-07 15:24:33 +00003**
drhb19a2bc2001-09-16 00:13:26 +00004** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
drhd1bf3512001-04-07 15:24:33 +00006**
drhb19a2bc2001-09-16 00:13:26 +00007** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
drhd1bf3512001-04-07 15:24:33 +000010**
11*************************************************************************
drh05a82982006-03-19 13:00:25 +000012** Code for testing all sorts of SQLite interfaces. This code
drhd1bf3512001-04-07 15:24:33 +000013** is not included in the SQLite library. It is used for automated
14** testing of the SQLite library.
drhd1bf3512001-04-07 15:24:33 +000015*/
16#include "sqliteInt.h"
mistachkinf74b9e02013-11-26 01:00:31 +000017#if SQLITE_OS_WIN
18# include "os_win.h"
19#endif
20
dand9495cd2011-04-27 12:08:04 +000021#include "vdbeInt.h"
drhd1bf3512001-04-07 15:24:33 +000022#include "tcl.h"
23#include <stdlib.h>
24#include <string.h>
25
drhdddca282006-01-03 00:33:50 +000026/*
27** This is a copy of the first part of the SqliteDb structure in
28** tclsqlite.c. We need it here so that the get_sqlite_pointer routine
29** can extract the sqlite3* pointer from an existing Tcl SQLite
30** connection.
31*/
32struct SqliteDb {
33 sqlite3 *db;
34};
35
36/*
drha3152892007-05-05 11:48:52 +000037** Convert text generated by the "%p" conversion format back into
38** a pointer.
39*/
40static int testHexToInt(int h){
41 if( h>='0' && h<='9' ){
42 return h - '0';
43 }else if( h>='a' && h<='f' ){
44 return h - 'a' + 10;
45 }else{
46 assert( h>='A' && h<='F' );
47 return h - 'A' + 10;
48 }
49}
drhe8f52c52008-07-12 14:52:20 +000050void *sqlite3TestTextToPtr(const char *z){
drha3152892007-05-05 11:48:52 +000051 void *p;
52 u64 v;
53 u32 v2;
54 if( z[0]=='0' && z[1]=='x' ){
55 z += 2;
56 }
57 v = 0;
58 while( *z ){
59 v = (v<<4) + testHexToInt(*z);
60 z++;
61 }
62 if( sizeof(p)==sizeof(v) ){
63 memcpy(&p, &v, sizeof(p));
64 }else{
65 assert( sizeof(p)==sizeof(v2) );
66 v2 = (u32)v;
67 memcpy(&p, &v2, sizeof(p));
68 }
69 return p;
70}
71
72
73/*
drhdddca282006-01-03 00:33:50 +000074** A TCL command that returns the address of the sqlite* pointer
75** for an sqlite connection instance. Bad things happen if the
76** input is not an sqlite connection.
77*/
78static int get_sqlite_pointer(
79 void * clientData,
80 Tcl_Interp *interp,
81 int objc,
82 Tcl_Obj *CONST objv[]
83){
84 struct SqliteDb *p;
85 Tcl_CmdInfo cmdInfo;
86 char zBuf[100];
87 if( objc!=2 ){
88 Tcl_WrongNumArgs(interp, 1, objv, "SQLITE-CONNECTION");
89 return TCL_ERROR;
90 }
91 if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
92 Tcl_AppendResult(interp, "command not found: ",
93 Tcl_GetString(objv[1]), (char*)0);
94 return TCL_ERROR;
95 }
96 p = (struct SqliteDb*)cmdInfo.objClientData;
drh65545b52015-01-19 00:35:53 +000097 sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", p->db);
drhdddca282006-01-03 00:33:50 +000098 Tcl_AppendResult(interp, zBuf, 0);
99 return TCL_OK;
100}
101
drhb62c3352006-11-23 09:39:16 +0000102/*
103** Decode a pointer to an sqlite3 object.
104*/
drh24b58dd2008-07-07 14:50:14 +0000105int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
drhb62c3352006-11-23 09:39:16 +0000106 struct SqliteDb *p;
107 Tcl_CmdInfo cmdInfo;
108 if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){
109 p = (struct SqliteDb*)cmdInfo.objClientData;
110 *ppDb = p->db;
111 }else{
drhe8f52c52008-07-12 14:52:20 +0000112 *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA);
drhb62c3352006-11-23 09:39:16 +0000113 }
114 return TCL_OK;
115}
116
mistachkin6b98d672014-05-30 16:42:35 +0000117#if SQLITE_OS_WIN
118/*
119** Decode a Win32 HANDLE object.
120*/
121int getWin32Handle(Tcl_Interp *interp, const char *zA, LPHANDLE phFile){
122 *phFile = (HANDLE)sqlite3TestTextToPtr(zA);
123 return TCL_OK;
124}
125#endif
126
mistachkine84d8d32013-04-29 03:09:10 +0000127extern const char *sqlite3ErrName(int);
128#define t1ErrorName sqlite3ErrName
danielk19776622cce2004-05-20 11:00:52 +0000129
drhd1bf3512001-04-07 15:24:33 +0000130/*
drhc60d0442004-09-30 13:43:13 +0000131** Convert an sqlite3_stmt* into an sqlite3*. This depends on the
132** fact that the sqlite3* is the first field in the Vdbe structure.
133*/
drh51942bc2005-06-12 22:01:42 +0000134#define StmtToDb(X) sqlite3_db_handle(X)
drhc60d0442004-09-30 13:43:13 +0000135
136/*
137** Check a return value to make sure it agrees with the results
138** from sqlite3_errcode.
139*/
140int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
drhb8613ab2009-01-19 17:40:12 +0000141 if( sqlite3_threadsafe()==0 && rc!=SQLITE_MISUSE && rc!=SQLITE_OK
142 && sqlite3_errcode(db)!=rc ){
drhc60d0442004-09-30 13:43:13 +0000143 char zBuf[200];
144 int r2 = sqlite3_errcode(db);
drh65545b52015-01-19 00:35:53 +0000145 sqlite3_snprintf(sizeof(zBuf), zBuf,
146 "error code %s (%d) does not match sqlite3_errcode %s (%d)",
drh4f0c5872007-03-26 22:05:01 +0000147 t1ErrorName(rc), rc, t1ErrorName(r2), r2);
drhc60d0442004-09-30 13:43:13 +0000148 Tcl_ResetResult(interp);
149 Tcl_AppendResult(interp, zBuf, 0);
150 return 1;
151 }
152 return 0;
153}
154
155/*
danielk197751e3d8e2004-05-20 01:12:34 +0000156** Decode a pointer to an sqlite3_stmt object.
157*/
158static int getStmtPointer(
159 Tcl_Interp *interp,
160 const char *zArg,
161 sqlite3_stmt **ppStmt
162){
drhe8f52c52008-07-12 14:52:20 +0000163 *ppStmt = (sqlite3_stmt*)sqlite3TestTextToPtr(zArg);
danielk197751e3d8e2004-05-20 01:12:34 +0000164 return TCL_OK;
165}
166
167/*
drh7d8085a2003-04-26 13:19:38 +0000168** Generate a text representation of a pointer that can be understood
169** by the getDbPointer and getVmPointer routines above.
170**
171** The problem is, on some machines (Solaris) if you do a printf with
172** "%p" you cannot turn around and do a scanf with the same "%p" and
173** get your pointer back. You have to prepend a "0x" before it will
174** work. Or at least that is what is reported to me (drh). But this
175** behavior varies from machine to machine. The solution used her is
176** to test the string right after it is generated to see if it can be
177** understood by scanf, and if not, try prepending an "0x" to see if
178** that helps. If nothing works, a fatal error is generated.
179*/
drh64b1bea2006-01-15 02:30:57 +0000180int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
drhfe63d1c2004-09-08 20:13:04 +0000181 sqlite3_snprintf(100, zPtr, "%p", p);
drh7d8085a2003-04-26 13:19:38 +0000182 return TCL_OK;
183}
184
185/*
danielk19776f8a5032004-05-10 10:34:51 +0000186** The callback routine for sqlite3_exec_printf().
drhd1bf3512001-04-07 15:24:33 +0000187*/
188static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
189 Tcl_DString *str = (Tcl_DString*)pArg;
190 int i;
191
192 if( Tcl_DStringLength(str)==0 ){
193 for(i=0; i<argc; i++){
194 Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
195 }
196 }
197 for(i=0; i<argc; i++){
198 Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
199 }
200 return 0;
201}
202
203/*
drh538f5702007-04-13 02:14:30 +0000204** The I/O tracing callback.
205*/
shaneafdd23a2008-05-29 02:57:47 +0000206#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
drh538f5702007-04-13 02:14:30 +0000207static FILE *iotrace_file = 0;
208static void io_trace_callback(const char *zFormat, ...){
209 va_list ap;
210 va_start(ap, zFormat);
211 vfprintf(iotrace_file, zFormat, ap);
212 va_end(ap);
213 fflush(iotrace_file);
214}
shaneafdd23a2008-05-29 02:57:47 +0000215#endif
drh538f5702007-04-13 02:14:30 +0000216
217/*
218** Usage: io_trace FILENAME
219**
220** Turn I/O tracing on or off. If FILENAME is not an empty string,
221** I/O tracing begins going into FILENAME. If FILENAME is an empty
222** string, I/O tracing is turned off.
223*/
224static int test_io_trace(
225 void *NotUsed,
226 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
227 int argc, /* Number of arguments */
228 char **argv /* Text of each argument */
229){
danielk1977286d2f42008-05-05 11:33:47 +0000230#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
drh538f5702007-04-13 02:14:30 +0000231 if( argc!=2 ){
232 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
233 " FILENAME\"", 0);
234 return TCL_ERROR;
235 }
236 if( iotrace_file ){
237 if( iotrace_file!=stdout && iotrace_file!=stderr ){
238 fclose(iotrace_file);
239 }
240 iotrace_file = 0;
mlcreech3a00f902008-03-04 17:45:01 +0000241 sqlite3IoTrace = 0;
drh538f5702007-04-13 02:14:30 +0000242 }
243 if( argv[1][0] ){
244 if( strcmp(argv[1],"stdout")==0 ){
245 iotrace_file = stdout;
246 }else if( strcmp(argv[1],"stderr")==0 ){
247 iotrace_file = stderr;
248 }else{
249 iotrace_file = fopen(argv[1], "w");
250 }
mlcreech3a00f902008-03-04 17:45:01 +0000251 sqlite3IoTrace = io_trace_callback;
drh538f5702007-04-13 02:14:30 +0000252 }
danielk1977286d2f42008-05-05 11:33:47 +0000253#endif
254 return TCL_OK;
drh538f5702007-04-13 02:14:30 +0000255}
256
danafcf9bd2014-01-23 14:44:08 +0000257/*
258** Usage: clang_sanitize_address
259**
260** Returns true if the program was compiled using clang with the
261** -fsanitize=address switch on the command line. False otherwise.
drh32e1f272015-01-08 16:47:51 +0000262**
263** Also return true if the OMIT_MISUSE environment variable exists.
danafcf9bd2014-01-23 14:44:08 +0000264*/
265static int clang_sanitize_address(
266 void *NotUsed,
267 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
268 int argc, /* Number of arguments */
269 char **argv /* Text of each argument */
270){
271 int res = 0;
272#if defined(__has_feature)
273# if __has_feature(address_sanitizer)
274 res = 1;
275# endif
276#endif
drh32e1f272015-01-08 16:47:51 +0000277 if( res==0 && getenv("OMIT_MISUSE")!=0 ) res = 1;
danafcf9bd2014-01-23 14:44:08 +0000278 Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
279 return TCL_OK;
280}
281
drh538f5702007-04-13 02:14:30 +0000282/*
danielk19776f8a5032004-05-10 10:34:51 +0000283** Usage: sqlite3_exec_printf DB FORMAT STRING
drhd1bf3512001-04-07 15:24:33 +0000284**
danielk19776f8a5032004-05-10 10:34:51 +0000285** Invoke the sqlite3_exec_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000286** DB. The SQL is the string FORMAT. The format string should contain
287** one %s or %q. STRING is the value inserted into %s or %q.
288*/
289static int test_exec_printf(
290 void *NotUsed,
291 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
292 int argc, /* Number of arguments */
293 char **argv /* Text of each argument */
294){
drh9bb575f2004-09-06 17:24:11 +0000295 sqlite3 *db;
drhd1bf3512001-04-07 15:24:33 +0000296 Tcl_DString str;
297 int rc;
298 char *zErr = 0;
drh1211de32004-07-26 12:24:22 +0000299 char *zSql;
drhd1bf3512001-04-07 15:24:33 +0000300 char zBuf[30];
301 if( argc!=4 ){
302 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
303 " DB FORMAT STRING", 0);
304 return TCL_ERROR;
305 }
drhb86ccfb2003-01-28 23:13:10 +0000306 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000307 Tcl_DStringInit(&str);
drh1211de32004-07-26 12:24:22 +0000308 zSql = sqlite3_mprintf(argv[2], argv[3]);
309 rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
310 sqlite3_free(zSql);
drh65545b52015-01-19 00:35:53 +0000311 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
drhd1bf3512001-04-07 15:24:33 +0000312 Tcl_AppendElement(interp, zBuf);
313 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
314 Tcl_DStringFree(&str);
danielk1977926aab22006-06-27 07:34:40 +0000315 if( zErr ) sqlite3_free(zErr);
drhc60d0442004-09-30 13:43:13 +0000316 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000317 return TCL_OK;
318}
319
320/*
drh5bd98ae2009-01-07 18:24:03 +0000321** Usage: sqlite3_exec_hex DB HEX
322**
323** Invoke the sqlite3_exec() on a string that is obtained by translating
324** HEX into ASCII. Most characters are translated as is. %HH becomes
325** a hex character.
326*/
327static int test_exec_hex(
328 void *NotUsed,
329 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
330 int argc, /* Number of arguments */
331 char **argv /* Text of each argument */
332){
333 sqlite3 *db;
334 Tcl_DString str;
335 int rc, i, j;
336 char *zErr = 0;
337 char *zHex;
338 char zSql[500];
339 char zBuf[30];
340 if( argc!=3 ){
341 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
342 " DB HEX", 0);
343 return TCL_ERROR;
344 }
345 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
346 zHex = argv[2];
347 for(i=j=0; i<sizeof(zSql) && zHex[j]; i++, j++){
348 if( zHex[j]=='%' && zHex[j+2] && zHex[j+2] ){
349 zSql[i] = (testHexToInt(zHex[j+1])<<4) + testHexToInt(zHex[j+2]);
350 j += 2;
351 }else{
352 zSql[i] = zHex[j];
353 }
354 }
355 zSql[i] = 0;
356 Tcl_DStringInit(&str);
357 rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
drh65545b52015-01-19 00:35:53 +0000358 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
drh5bd98ae2009-01-07 18:24:03 +0000359 Tcl_AppendElement(interp, zBuf);
360 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
361 Tcl_DStringFree(&str);
362 if( zErr ) sqlite3_free(zErr);
363 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
364 return TCL_OK;
365}
366
367/*
drh27641702007-08-22 02:56:42 +0000368** Usage: db_enter DB
369** db_leave DB
370**
371** Enter or leave the mutex on a database connection.
372*/
373static int db_enter(
374 void *NotUsed,
375 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
376 int argc, /* Number of arguments */
377 char **argv /* Text of each argument */
378){
379 sqlite3 *db;
380 if( argc!=2 ){
381 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
382 " DB", 0);
383 return TCL_ERROR;
384 }
385 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
386 sqlite3_mutex_enter(db->mutex);
387 return TCL_OK;
388}
389static int db_leave(
390 void *NotUsed,
391 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
392 int argc, /* Number of arguments */
393 char **argv /* Text of each argument */
394){
395 sqlite3 *db;
396 if( argc!=2 ){
397 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
398 " DB", 0);
399 return TCL_ERROR;
400 }
401 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
402 sqlite3_mutex_leave(db->mutex);
403 return TCL_OK;
404}
405
406/*
drhb62c3352006-11-23 09:39:16 +0000407** Usage: sqlite3_exec DB SQL
408**
409** Invoke the sqlite3_exec interface using the open database DB
410*/
411static int test_exec(
412 void *NotUsed,
413 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
414 int argc, /* Number of arguments */
415 char **argv /* Text of each argument */
416){
417 sqlite3 *db;
418 Tcl_DString str;
419 int rc;
420 char *zErr = 0;
drh4e5dd852007-05-15 03:56:49 +0000421 char *zSql;
422 int i, j;
drhb62c3352006-11-23 09:39:16 +0000423 char zBuf[30];
424 if( argc!=3 ){
425 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
426 " DB SQL", 0);
427 return TCL_ERROR;
428 }
429 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
430 Tcl_DStringInit(&str);
drh4e5dd852007-05-15 03:56:49 +0000431 zSql = sqlite3_mprintf("%s", argv[2]);
432 for(i=j=0; zSql[i];){
433 if( zSql[i]=='%' ){
434 zSql[j++] = (testHexToInt(zSql[i+1])<<4) + testHexToInt(zSql[i+2]);
435 i += 3;
436 }else{
437 zSql[j++] = zSql[i++];
438 }
439 }
440 zSql[j] = 0;
441 rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
442 sqlite3_free(zSql);
drh65545b52015-01-19 00:35:53 +0000443 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
drhb62c3352006-11-23 09:39:16 +0000444 Tcl_AppendElement(interp, zBuf);
445 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
446 Tcl_DStringFree(&str);
447 if( zErr ) sqlite3_free(zErr);
448 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
449 return TCL_OK;
450}
451
452/*
453** Usage: sqlite3_exec_nr DB SQL
454**
455** Invoke the sqlite3_exec interface using the open database DB. Discard
456** all results
457*/
458static int test_exec_nr(
459 void *NotUsed,
460 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
461 int argc, /* Number of arguments */
462 char **argv /* Text of each argument */
463){
464 sqlite3 *db;
465 int rc;
466 char *zErr = 0;
467 if( argc!=3 ){
468 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
469 " DB SQL", 0);
470 return TCL_ERROR;
471 }
472 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
473 rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
474 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
475 return TCL_OK;
476}
477
478/*
danielk19776f8a5032004-05-10 10:34:51 +0000479** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ...
drhd93d8a82003-06-16 03:08:18 +0000480**
drhbc6160b2009-04-08 15:45:31 +0000481** Test the %z format of sqlite_mprintf(). Use multiple mprintf() calls to
drhd93d8a82003-06-16 03:08:18 +0000482** concatenate arg0 through argn using separator as the separator.
483** Return the result.
484*/
485static int test_mprintf_z(
486 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 char *zResult = 0;
492 int i;
493
danielk1977ca0c8972007-09-01 09:02:53 +0000494 for(i=2; i<argc && (i==2 || zResult); i++){
drhbc6160b2009-04-08 15:45:31 +0000495 zResult = sqlite3_mprintf("%z%s%s", zResult, argv[1], argv[i]);
drhd93d8a82003-06-16 03:08:18 +0000496 }
497 Tcl_AppendResult(interp, zResult, 0);
drh17435752007-08-16 04:30:38 +0000498 sqlite3_free(zResult);
drhd93d8a82003-06-16 03:08:18 +0000499 return TCL_OK;
500}
501
502/*
drh05a82982006-03-19 13:00:25 +0000503** Usage: sqlite3_mprintf_n_test STRING
504**
drhbc6160b2009-04-08 15:45:31 +0000505** Test the %n format of sqlite_mprintf(). Return the length of the
drh05a82982006-03-19 13:00:25 +0000506** input string.
507*/
508static int test_mprintf_n(
509 void *NotUsed,
510 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
511 int argc, /* Number of arguments */
512 char **argv /* Text of each argument */
513){
514 char *zStr;
515 int n = 0;
drhbc6160b2009-04-08 15:45:31 +0000516 zStr = sqlite3_mprintf("%s%n", argv[1], &n);
drh17435752007-08-16 04:30:38 +0000517 sqlite3_free(zStr);
drh05a82982006-03-19 13:00:25 +0000518 Tcl_SetObjResult(interp, Tcl_NewIntObj(n));
519 return TCL_OK;
520}
521
522/*
drh68853902007-05-07 11:24:30 +0000523** Usage: sqlite3_snprintf_int SIZE FORMAT INT
524**
525** Test the of sqlite3_snprintf() routine. SIZE is the size of the
526** output buffer in bytes. The maximum size is 100. FORMAT is the
527** format string. INT is a single integer argument. The FORMAT
528** string must require no more than this one integer argument. If
529** You pass in a format string that requires more than one argument,
530** bad things will happen.
531*/
532static int test_snprintf_int(
533 void *NotUsed,
534 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
535 int argc, /* Number of arguments */
536 char **argv /* Text of each argument */
537){
538 char zStr[100];
539 int n = atoi(argv[1]);
drh68853902007-05-07 11:24:30 +0000540 const char *zFormat = argv[2];
541 int a1 = atoi(argv[3]);
drhdaf276d2007-06-15 18:53:14 +0000542 if( n>sizeof(zStr) ) n = sizeof(zStr);
drh76945742008-02-19 18:29:07 +0000543 sqlite3_snprintf(sizeof(zStr), zStr, "abcdefghijklmnopqrstuvwxyz");
drh68853902007-05-07 11:24:30 +0000544 sqlite3_snprintf(n, zStr, zFormat, a1);
545 Tcl_AppendResult(interp, zStr, 0);
546 return TCL_OK;
547}
548
shane8225f5a2008-07-31 02:05:04 +0000549#ifndef SQLITE_OMIT_GET_TABLE
550
drh68853902007-05-07 11:24:30 +0000551/*
drhd2b3e232008-01-23 14:51:49 +0000552** Usage: sqlite3_get_table_printf DB FORMAT STRING ?--no-counts?
drhd1bf3512001-04-07 15:24:33 +0000553**
danielk19776f8a5032004-05-10 10:34:51 +0000554** Invoke the sqlite3_get_table_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000555** DB. The SQL is the string FORMAT. The format string should contain
556** one %s or %q. STRING is the value inserted into %s or %q.
557*/
558static int test_get_table_printf(
559 void *NotUsed,
560 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
561 int argc, /* Number of arguments */
562 char **argv /* Text of each argument */
563){
drh9bb575f2004-09-06 17:24:11 +0000564 sqlite3 *db;
drhd1bf3512001-04-07 15:24:33 +0000565 Tcl_DString str;
566 int rc;
567 char *zErr = 0;
mistachkin27b2f052015-01-12 19:49:46 +0000568 int nRow = 0, nCol = 0;
drhd1bf3512001-04-07 15:24:33 +0000569 char **aResult;
570 int i;
571 char zBuf[30];
drh1211de32004-07-26 12:24:22 +0000572 char *zSql;
drhd2b3e232008-01-23 14:51:49 +0000573 int resCount = -1;
574 if( argc==5 ){
575 if( Tcl_GetInt(interp, argv[4], &resCount) ) return TCL_ERROR;
576 }
577 if( argc!=4 && argc!=5 ){
drhd1bf3512001-04-07 15:24:33 +0000578 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drhd2b3e232008-01-23 14:51:49 +0000579 " DB FORMAT STRING ?COUNT?", 0);
drhd1bf3512001-04-07 15:24:33 +0000580 return TCL_ERROR;
581 }
drhb86ccfb2003-01-28 23:13:10 +0000582 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000583 Tcl_DStringInit(&str);
drh1211de32004-07-26 12:24:22 +0000584 zSql = sqlite3_mprintf(argv[2],argv[3]);
drhd2b3e232008-01-23 14:51:49 +0000585 if( argc==5 ){
586 rc = sqlite3_get_table(db, zSql, &aResult, 0, 0, &zErr);
587 }else{
588 rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
589 resCount = (nRow+1)*nCol;
590 }
drh1211de32004-07-26 12:24:22 +0000591 sqlite3_free(zSql);
drh65545b52015-01-19 00:35:53 +0000592 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
drhd1bf3512001-04-07 15:24:33 +0000593 Tcl_AppendElement(interp, zBuf);
594 if( rc==SQLITE_OK ){
drhd2b3e232008-01-23 14:51:49 +0000595 if( argc==4 ){
drh65545b52015-01-19 00:35:53 +0000596 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nRow);
drhd2b3e232008-01-23 14:51:49 +0000597 Tcl_AppendElement(interp, zBuf);
drh65545b52015-01-19 00:35:53 +0000598 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nCol);
drhd2b3e232008-01-23 14:51:49 +0000599 Tcl_AppendElement(interp, zBuf);
600 }
601 for(i=0; i<resCount; i++){
drhd1bf3512001-04-07 15:24:33 +0000602 Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
603 }
604 }else{
605 Tcl_AppendElement(interp, zErr);
606 }
danielk19776f8a5032004-05-10 10:34:51 +0000607 sqlite3_free_table(aResult);
danielk1977926aab22006-06-27 07:34:40 +0000608 if( zErr ) sqlite3_free(zErr);
drhc60d0442004-09-30 13:43:13 +0000609 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000610 return TCL_OK;
611}
612
shane8225f5a2008-07-31 02:05:04 +0000613#endif /* SQLITE_OMIT_GET_TABLE */
614
drhaf9ff332002-01-16 21:00:27 +0000615
616/*
danielk19776f8a5032004-05-10 10:34:51 +0000617** Usage: sqlite3_last_insert_rowid DB
drhaf9ff332002-01-16 21:00:27 +0000618**
619** Returns the integer ROWID of the most recent insert.
620*/
621static int test_last_rowid(
622 void *NotUsed,
623 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
624 int argc, /* Number of arguments */
625 char **argv /* Text of each argument */
626){
drh9bb575f2004-09-06 17:24:11 +0000627 sqlite3 *db;
drhaf9ff332002-01-16 21:00:27 +0000628 char zBuf[30];
629
630 if( argc!=2 ){
631 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
632 return TCL_ERROR;
633 }
drhb86ccfb2003-01-28 23:13:10 +0000634 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drh65545b52015-01-19 00:35:53 +0000635 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", sqlite3_last_insert_rowid(db));
drhaf9ff332002-01-16 21:00:27 +0000636 Tcl_AppendResult(interp, zBuf, 0);
637 return SQLITE_OK;
638}
639
drhd1bf3512001-04-07 15:24:33 +0000640/*
drh25d65432004-07-22 15:02:25 +0000641** Usage: sqlite3_key DB KEY
642**
643** Set the codec key.
644*/
645static int test_key(
646 void *NotUsed,
647 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
648 int argc, /* Number of arguments */
649 char **argv /* Text of each argument */
650){
drhcaffb1a2012-01-30 18:00:31 +0000651#ifdef SQLITE_HAS_CODEC
drh9bb575f2004-09-06 17:24:11 +0000652 sqlite3 *db;
drh25d65432004-07-22 15:02:25 +0000653 const char *zKey;
654 int nKey;
655 if( argc!=3 ){
656 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
657 " FILENAME\"", 0);
658 return TCL_ERROR;
659 }
660 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
661 zKey = argv[2];
662 nKey = strlen(zKey);
drh25d65432004-07-22 15:02:25 +0000663 sqlite3_key(db, zKey, nKey);
664#endif
665 return TCL_OK;
666}
667
668/*
669** Usage: sqlite3_rekey DB KEY
670**
671** Change the codec key.
672*/
673static int test_rekey(
674 void *NotUsed,
675 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
676 int argc, /* Number of arguments */
677 char **argv /* Text of each argument */
678){
drhcaffb1a2012-01-30 18:00:31 +0000679#ifdef SQLITE_HAS_CODEC
drh9bb575f2004-09-06 17:24:11 +0000680 sqlite3 *db;
drh25d65432004-07-22 15:02:25 +0000681 const char *zKey;
682 int nKey;
683 if( argc!=3 ){
684 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
685 " FILENAME\"", 0);
686 return TCL_ERROR;
687 }
688 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
689 zKey = argv[2];
690 nKey = strlen(zKey);
drh25d65432004-07-22 15:02:25 +0000691 sqlite3_rekey(db, zKey, nKey);
692#endif
693 return TCL_OK;
694}
695
696/*
danielk19776f8a5032004-05-10 10:34:51 +0000697** Usage: sqlite3_close DB
drhd1bf3512001-04-07 15:24:33 +0000698**
danielk19776f8a5032004-05-10 10:34:51 +0000699** Closes the database opened by sqlite3_open.
drhd1bf3512001-04-07 15:24:33 +0000700*/
701static int sqlite_test_close(
702 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){
drh9bb575f2004-09-06 17:24:11 +0000707 sqlite3 *db;
danielk197796d81f92004-06-19 03:33:57 +0000708 int rc;
drhd1bf3512001-04-07 15:24:33 +0000709 if( argc!=2 ){
710 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
711 " FILENAME\"", 0);
712 return TCL_ERROR;
713 }
drhb86ccfb2003-01-28 23:13:10 +0000714 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk197796d81f92004-06-19 03:33:57 +0000715 rc = sqlite3_close(db);
drh4f0c5872007-03-26 22:05:01 +0000716 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
drhd1bf3512001-04-07 15:24:33 +0000717 return TCL_OK;
718}
719
720/*
dan617dc862013-05-16 11:57:28 +0000721** Usage: sqlite3_close_v2 DB
722**
723** Closes the database opened by sqlite3_open.
724*/
725static int sqlite_test_close_v2(
726 void *NotUsed,
727 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
728 int argc, /* Number of arguments */
729 char **argv /* Text of each argument */
730){
731 sqlite3 *db;
732 int rc;
733 if( argc!=2 ){
734 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
735 " FILENAME\"", 0);
736 return TCL_ERROR;
737 }
738 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
739 rc = sqlite3_close_v2(db);
740 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
741 return TCL_OK;
742}
743
744/*
drhc22bd472002-05-10 13:14:07 +0000745** Implementation of the x_coalesce() function.
746** Return the first argument non-NULL argument.
747*/
drh4f0c5872007-03-26 22:05:01 +0000748static void t1_ifnullFunc(
749 sqlite3_context *context,
750 int argc,
751 sqlite3_value **argv
752){
drhc22bd472002-05-10 13:14:07 +0000753 int i;
754 for(i=0; i<argc; i++){
drh9c054832004-05-31 18:51:57 +0000755 if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
drh9310ef22007-04-27 17:16:20 +0000756 int n = sqlite3_value_bytes(argv[i]);
drh03d847e2005-12-09 20:21:58 +0000757 sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]),
drh9310ef22007-04-27 17:16:20 +0000758 n, SQLITE_TRANSIENT);
drhc22bd472002-05-10 13:14:07 +0000759 break;
760 }
761 }
762}
763
764/*
drhf0313812006-09-04 15:53:53 +0000765** These are test functions. hex8() interprets its argument as
766** UTF8 and returns a hex encoding. hex16le() interprets its argument
767** as UTF16le and returns a hex encoding.
768*/
769static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){
770 const unsigned char *z;
771 int i;
772 char zBuf[200];
773 z = sqlite3_value_text(argv[0]);
774 for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){
drh65545b52015-01-19 00:35:53 +0000775 sqlite3_snprintf(sizeof(zBuf)-i*2, &zBuf[i*2], "%02x", z[i]);
drhf0313812006-09-04 15:53:53 +0000776 }
777 zBuf[i*2] = 0;
778 sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
779}
drhaf304692007-04-23 23:56:31 +0000780#ifndef SQLITE_OMIT_UTF16
drhf0313812006-09-04 15:53:53 +0000781static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){
782 const unsigned short int *z;
783 int i;
784 char zBuf[400];
785 z = sqlite3_value_text16(argv[0]);
786 for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){
drh65545b52015-01-19 00:35:53 +0000787 sqlite3_snprintf(sizeof(zBuf)-i*4, &zBuf[i*4],"%04x", z[i]&0xff);
drhf0313812006-09-04 15:53:53 +0000788 }
789 zBuf[i*4] = 0;
790 sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
791}
drhaf304692007-04-23 23:56:31 +0000792#endif
drhf0313812006-09-04 15:53:53 +0000793
794/*
drhd1d9fc32004-01-07 19:24:48 +0000795** A structure into which to accumulate text.
796*/
797struct dstr {
798 int nAlloc; /* Space allocated */
799 int nUsed; /* Space used */
800 char *z; /* The space */
801};
802
803/*
804** Append text to a dstr
805*/
806static void dstrAppend(struct dstr *p, const char *z, int divider){
drh83cc1392012-04-19 18:04:28 +0000807 int n = (int)strlen(z);
drhd1d9fc32004-01-07 19:24:48 +0000808 if( p->nUsed + n + 2 > p->nAlloc ){
809 char *zNew;
810 p->nAlloc = p->nAlloc*2 + n + 200;
drh17435752007-08-16 04:30:38 +0000811 zNew = sqlite3_realloc(p->z, p->nAlloc);
drhd1d9fc32004-01-07 19:24:48 +0000812 if( zNew==0 ){
drh17435752007-08-16 04:30:38 +0000813 sqlite3_free(p->z);
drhd1d9fc32004-01-07 19:24:48 +0000814 memset(p, 0, sizeof(*p));
815 return;
816 }
817 p->z = zNew;
818 }
819 if( divider && p->nUsed>0 ){
820 p->z[p->nUsed++] = divider;
821 }
822 memcpy(&p->z[p->nUsed], z, n+1);
823 p->nUsed += n;
824}
825
826/*
danielk19774adee202004-05-08 08:23:19 +0000827** Invoked for each callback from sqlite3ExecFunc
drhd1d9fc32004-01-07 19:24:48 +0000828*/
829static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
830 struct dstr *p = (struct dstr*)pData;
831 int i;
832 for(i=0; i<argc; i++){
833 if( argv[i]==0 ){
834 dstrAppend(p, "NULL", ' ');
835 }else{
836 dstrAppend(p, argv[i], ' ');
837 }
838 }
839 return 0;
840}
841
842/*
danielk1977e35ee192004-06-26 09:50:11 +0000843** Implementation of the x_sqlite_exec() function. This function takes
drhc22bd472002-05-10 13:14:07 +0000844** a single argument and attempts to execute that argument as SQL code.
drh6cbe1f12002-07-01 00:31:36 +0000845** This is illegal and should set the SQLITE_MISUSE flag on the database.
drhd1d9fc32004-01-07 19:24:48 +0000846**
danielk19776f8a5032004-05-10 10:34:51 +0000847** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec()
drhd1d9fc32004-01-07 19:24:48 +0000848** from within a function call.
drhc22bd472002-05-10 13:14:07 +0000849**
850** This routine simulates the effect of having two threads attempt to
851** use the same database at the same time.
852*/
danielk197751ad0ec2004-05-24 12:39:02 +0000853static void sqlite3ExecFunc(
danielk19770ae8b832004-05-25 12:05:56 +0000854 sqlite3_context *context,
danielk197751ad0ec2004-05-24 12:39:02 +0000855 int argc,
856 sqlite3_value **argv
857){
drhd1d9fc32004-01-07 19:24:48 +0000858 struct dstr x;
859 memset(&x, 0, sizeof(x));
drh37527852006-03-16 16:19:56 +0000860 (void)sqlite3_exec((sqlite3*)sqlite3_user_data(context),
drh03d847e2005-12-09 20:21:58 +0000861 (char*)sqlite3_value_text(argv[0]),
drhd1d9fc32004-01-07 19:24:48 +0000862 execFuncCallback, &x, 0);
danielk1977d8123362004-06-12 09:25:12 +0000863 sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
drh17435752007-08-16 04:30:38 +0000864 sqlite3_free(x.z);
drhc22bd472002-05-10 13:14:07 +0000865}
866
867/*
danielk1977d7263922007-02-05 14:21:47 +0000868** Implementation of tkt2213func(), a scalar function that takes exactly
869** one argument. It has two interesting features:
870**
871** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*.
872** If the three pointers returned are not the same an SQL error is raised.
873**
drh85b623f2007-12-13 21:54:09 +0000874** * Otherwise it returns a copy of the text representation of its
danielk1977d7263922007-02-05 14:21:47 +0000875** argument in such a way as the VDBE representation is a Mem* cell
876** with the MEM_Term flag clear.
877**
878** Ticket #2213 can therefore be tested by evaluating the following
879** SQL expression:
880**
881** tkt2213func(tkt2213func('a string'));
882*/
883static void tkt2213Function(
884 sqlite3_context *context,
885 int argc,
886 sqlite3_value **argv
887){
888 int nText;
889 unsigned char const *zText1;
890 unsigned char const *zText2;
891 unsigned char const *zText3;
892
893 nText = sqlite3_value_bytes(argv[0]);
894 zText1 = sqlite3_value_text(argv[0]);
895 zText2 = sqlite3_value_text(argv[0]);
896 zText3 = sqlite3_value_text(argv[0]);
897
898 if( zText1!=zText2 || zText2!=zText3 ){
899 sqlite3_result_error(context, "tkt2213 is not fixed", -1);
900 }else{
901 char *zCopy = (char *)sqlite3_malloc(nText);
902 memcpy(zCopy, zText1, nText);
903 sqlite3_result_text(context, zCopy, nText, sqlite3_free);
904 }
905}
906
907/*
drh9310ef22007-04-27 17:16:20 +0000908** The following SQL function takes 4 arguments. The 2nd and
909** 4th argument must be one of these strings: 'text', 'text16',
910** or 'blob' corresponding to API functions
911**
912** sqlite3_value_text()
913** sqlite3_value_text16()
914** sqlite3_value_blob()
915**
916** The third argument is a string, either 'bytes' or 'bytes16' or 'noop',
917** corresponding to APIs:
918**
919** sqlite3_value_bytes()
920** sqlite3_value_bytes16()
921** noop
922**
923** The APIs designated by the 2nd through 4th arguments are applied
924** to the first argument in order. If the pointers returned by the
925** second and fourth are different, this routine returns 1. Otherwise,
926** this routine returns 0.
927**
928** This function is used to test to see when returned pointers from
929** the _text(), _text16() and _blob() APIs become invalidated.
930*/
931static void ptrChngFunction(
932 sqlite3_context *context,
933 int argc,
934 sqlite3_value **argv
935){
936 const void *p1, *p2;
937 const char *zCmd;
938 if( argc!=4 ) return;
939 zCmd = (const char*)sqlite3_value_text(argv[1]);
940 if( zCmd==0 ) return;
941 if( strcmp(zCmd,"text")==0 ){
942 p1 = (const void*)sqlite3_value_text(argv[0]);
943#ifndef SQLITE_OMIT_UTF16
944 }else if( strcmp(zCmd, "text16")==0 ){
945 p1 = (const void*)sqlite3_value_text16(argv[0]);
946#endif
947 }else if( strcmp(zCmd, "blob")==0 ){
948 p1 = (const void*)sqlite3_value_blob(argv[0]);
949 }else{
950 return;
951 }
952 zCmd = (const char*)sqlite3_value_text(argv[2]);
953 if( zCmd==0 ) return;
954 if( strcmp(zCmd,"bytes")==0 ){
955 sqlite3_value_bytes(argv[0]);
956#ifndef SQLITE_OMIT_UTF16
957 }else if( strcmp(zCmd, "bytes16")==0 ){
958 sqlite3_value_bytes16(argv[0]);
959#endif
960 }else if( strcmp(zCmd, "noop")==0 ){
961 /* do nothing */
962 }else{
963 return;
964 }
965 zCmd = (const char*)sqlite3_value_text(argv[3]);
966 if( zCmd==0 ) return;
967 if( strcmp(zCmd,"text")==0 ){
968 p2 = (const void*)sqlite3_value_text(argv[0]);
969#ifndef SQLITE_OMIT_UTF16
970 }else if( strcmp(zCmd, "text16")==0 ){
971 p2 = (const void*)sqlite3_value_text16(argv[0]);
972#endif
973 }else if( strcmp(zCmd, "blob")==0 ){
974 p2 = (const void*)sqlite3_value_blob(argv[0]);
975 }else{
976 return;
977 }
978 sqlite3_result_int(context, p1!=p2);
979}
980
drh4a8ee3d2013-12-14 13:44:22 +0000981/*
982** This SQL function returns a different answer each time it is called, even if
983** the arguments are the same.
984*/
985static void nondeterministicFunction(
986 sqlite3_context *context,
987 int argc,
988 sqlite3_value **argv
989){
990 static int cnt = 0;
991 sqlite3_result_int(context, cnt++);
992}
drh9310ef22007-04-27 17:16:20 +0000993
994/*
drh4a8ee3d2013-12-14 13:44:22 +0000995** Usage: sqlite3_create_function DB
drhc22bd472002-05-10 13:14:07 +0000996**
danielk19776f8a5032004-05-10 10:34:51 +0000997** Call the sqlite3_create_function API on the given database in order
drhc22bd472002-05-10 13:14:07 +0000998** to create a function named "x_coalesce". This function does the same thing
999** as the "coalesce" function. This function also registers an SQL function
danielk1977e35ee192004-06-26 09:50:11 +00001000** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec()
drhc22bd472002-05-10 13:14:07 +00001001** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
1002** The effect is similar to trying to use the same database connection from
1003** two threads at the same time.
1004**
1005** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +00001006** sqlite3_create_function function while a query is in progress in order
drhc22bd472002-05-10 13:14:07 +00001007** to test the SQLITE_MISUSE detection logic.
1008*/
drhc2eef3b2002-08-31 18:53:06 +00001009static int test_create_function(
drhc22bd472002-05-10 13:14:07 +00001010 void *NotUsed,
1011 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1012 int argc, /* Number of arguments */
1013 char **argv /* Text of each argument */
1014){
drhc60d0442004-09-30 13:43:13 +00001015 int rc;
drh9bb575f2004-09-06 17:24:11 +00001016 sqlite3 *db;
danielk1977312d6b32004-06-29 13:18:23 +00001017
drhc22bd472002-05-10 13:14:07 +00001018 if( argc!=2 ){
1019 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
danielk19774397de52005-01-12 12:44:03 +00001020 " DB\"", 0);
drhc22bd472002-05-10 13:14:07 +00001021 return TCL_ERROR;
1022 }
drhb86ccfb2003-01-28 23:13:10 +00001023 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drh4a8ee3d2013-12-14 13:44:22 +00001024 rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_UTF8, 0,
drh4f0c5872007-03-26 22:05:01 +00001025 t1_ifnullFunc, 0, 0);
drh235a8182006-09-13 19:21:28 +00001026 if( rc==SQLITE_OK ){
drh4a8ee3d2013-12-14 13:44:22 +00001027 rc = sqlite3_create_function(db, "hex8", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
1028 0, hex8Func, 0, 0);
drh235a8182006-09-13 19:21:28 +00001029 }
drhaf304692007-04-23 23:56:31 +00001030#ifndef SQLITE_OMIT_UTF16
drh235a8182006-09-13 19:21:28 +00001031 if( rc==SQLITE_OK ){
drh4a8ee3d2013-12-14 13:44:22 +00001032 rc = sqlite3_create_function(db, "hex16", 1, SQLITE_UTF16 | SQLITE_DETERMINISTIC,
1033 0, hex16Func, 0, 0);
drh235a8182006-09-13 19:21:28 +00001034 }
drhaf304692007-04-23 23:56:31 +00001035#endif
danielk1977d7263922007-02-05 14:21:47 +00001036 if( rc==SQLITE_OK ){
1037 rc = sqlite3_create_function(db, "tkt2213func", 1, SQLITE_ANY, 0,
1038 tkt2213Function, 0, 0);
1039 }
drh9310ef22007-04-27 17:16:20 +00001040 if( rc==SQLITE_OK ){
1041 rc = sqlite3_create_function(db, "pointer_change", 4, SQLITE_ANY, 0,
1042 ptrChngFunction, 0, 0);
1043 }
danielk1977312d6b32004-06-29 13:18:23 +00001044
drh4a8ee3d2013-12-14 13:44:22 +00001045 /* Functions counter1() and counter2() have the same implementation - they
1046 ** both return an ascending integer with each call. But counter1() is marked
1047 ** as non-deterministic and counter2() is marked as deterministic.
1048 */
1049 if( rc==SQLITE_OK ){
1050 rc = sqlite3_create_function(db, "counter1", -1, SQLITE_UTF8,
1051 0, nondeterministicFunction, 0, 0);
1052 }
1053 if( rc==SQLITE_OK ){
1054 rc = sqlite3_create_function(db, "counter2", -1, SQLITE_UTF8|SQLITE_DETERMINISTIC,
1055 0, nondeterministicFunction, 0, 0);
1056 }
1057
drh5436dc22004-11-14 04:04:17 +00001058#ifndef SQLITE_OMIT_UTF16
danielk1977312d6b32004-06-29 13:18:23 +00001059 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
1060 ** because it is not tested anywhere else. */
drhc60d0442004-09-30 13:43:13 +00001061 if( rc==SQLITE_OK ){
drheee4c8c2008-02-18 22:24:57 +00001062 const void *zUtf16;
danielk1977576ec6b2005-01-21 11:55:25 +00001063 sqlite3_value *pVal;
drhf3a65f72007-08-22 20:18:21 +00001064 sqlite3_mutex_enter(db->mutex);
1065 pVal = sqlite3ValueNew(db);
drhb21c8cd2007-08-21 19:33:56 +00001066 sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
danielk1977a7a8e142008-02-13 18:25:27 +00001067 zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
drhf3a65f72007-08-22 20:18:21 +00001068 if( db->mallocFailed ){
1069 rc = SQLITE_NOMEM;
1070 }else{
danielk1977a7a8e142008-02-13 18:25:27 +00001071 rc = sqlite3_create_function16(db, zUtf16,
1072 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
drhf3a65f72007-08-22 20:18:21 +00001073 }
drhc60d0442004-09-30 13:43:13 +00001074 sqlite3ValueFree(pVal);
drhf3a65f72007-08-22 20:18:21 +00001075 sqlite3_mutex_leave(db->mutex);
drhc60d0442004-09-30 13:43:13 +00001076 }
drh5436dc22004-11-14 04:04:17 +00001077#endif
1078
drhc60d0442004-09-30 13:43:13 +00001079 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drh4f0c5872007-03-26 22:05:01 +00001080 Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
drhc22bd472002-05-10 13:14:07 +00001081 return TCL_OK;
1082}
1083
1084/*
1085** Routines to implement the x_count() aggregate function.
drh90669c12006-01-20 15:45:36 +00001086**
1087** x_count() counts the number of non-null arguments. But there are
1088** some twists for testing purposes.
1089**
1090** If the argument to x_count() is 40 then a UTF-8 error is reported
1091** on the step function. If x_count(41) is seen, then a UTF-16 error
1092** is reported on the step function. If the total count is 42, then
1093** a UTF-8 error is reported on the finalize function.
drhc22bd472002-05-10 13:14:07 +00001094*/
drh4f0c5872007-03-26 22:05:01 +00001095typedef struct t1CountCtx t1CountCtx;
1096struct t1CountCtx {
drhc22bd472002-05-10 13:14:07 +00001097 int n;
1098};
drh4f0c5872007-03-26 22:05:01 +00001099static void t1CountStep(
1100 sqlite3_context *context,
1101 int argc,
1102 sqlite3_value **argv
1103){
1104 t1CountCtx *p;
drh4f26d6c2004-05-26 23:25:30 +00001105 p = sqlite3_aggregate_context(context, sizeof(*p));
drh9c054832004-05-31 18:51:57 +00001106 if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
drhc22bd472002-05-10 13:14:07 +00001107 p->n++;
1108 }
drh90669c12006-01-20 15:45:36 +00001109 if( argc>0 ){
1110 int v = sqlite3_value_int(argv[0]);
1111 if( v==40 ){
1112 sqlite3_result_error(context, "value of 40 handed to x_count", -1);
danielk1977a1686c92006-01-23 07:52:37 +00001113#ifndef SQLITE_OMIT_UTF16
drh90669c12006-01-20 15:45:36 +00001114 }else if( v==41 ){
1115 const char zUtf16ErrMsg[] = { 0, 0x61, 0, 0x62, 0, 0x63, 0, 0, 0};
1116 sqlite3_result_error16(context, &zUtf16ErrMsg[1-SQLITE_BIGENDIAN], -1);
danielk1977a1686c92006-01-23 07:52:37 +00001117#endif
drh90669c12006-01-20 15:45:36 +00001118 }
1119 }
drhc22bd472002-05-10 13:14:07 +00001120}
drh4f0c5872007-03-26 22:05:01 +00001121static void t1CountFinalize(sqlite3_context *context){
1122 t1CountCtx *p;
drh4f26d6c2004-05-26 23:25:30 +00001123 p = sqlite3_aggregate_context(context, sizeof(*p));
drh90669c12006-01-20 15:45:36 +00001124 if( p ){
1125 if( p->n==42 ){
1126 sqlite3_result_error(context, "x_count totals to 42", -1);
1127 }else{
1128 sqlite3_result_int(context, p ? p->n : 0);
1129 }
1130 }
drhc22bd472002-05-10 13:14:07 +00001131}
1132
danielk1977c5512882009-08-10 04:37:49 +00001133#ifndef SQLITE_OMIT_DEPRECATED
danielk1977fa18bec2007-09-03 11:04:22 +00001134static void legacyCountStep(
1135 sqlite3_context *context,
1136 int argc,
1137 sqlite3_value **argv
1138){
1139 /* no-op */
1140}
shaneeec556d2008-10-12 00:27:53 +00001141
danielk1977fa18bec2007-09-03 11:04:22 +00001142static void legacyCountFinalize(sqlite3_context *context){
1143 sqlite3_result_int(context, sqlite3_aggregate_count(context));
1144}
shaneeec556d2008-10-12 00:27:53 +00001145#endif
danielk1977fa18bec2007-09-03 11:04:22 +00001146
drhc22bd472002-05-10 13:14:07 +00001147/*
danielk1977fa18bec2007-09-03 11:04:22 +00001148** Usage: sqlite3_create_aggregate DB
drhc22bd472002-05-10 13:14:07 +00001149**
danielk19776f8a5032004-05-10 10:34:51 +00001150** Call the sqlite3_create_function API on the given database in order
danielk1977fa18bec2007-09-03 11:04:22 +00001151** to create a function named "x_count". This function is similar
1152** to the built-in count() function, with a few special quirks
1153** for testing the sqlite3_result_error() APIs.
drhc22bd472002-05-10 13:14:07 +00001154**
1155** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +00001156** sqlite3_create_aggregate function while a query is in progress in order
drh90669c12006-01-20 15:45:36 +00001157** to test the SQLITE_MISUSE detection logic. See misuse.test.
1158**
1159** This routine was later extended to test the use of sqlite3_result_error()
1160** within aggregate functions.
danielk1977fa18bec2007-09-03 11:04:22 +00001161**
1162** Later: It is now also extended to register the aggregate function
1163** "legacy_count()" with the supplied database handle. This is used
1164** to test the deprecated sqlite3_aggregate_count() API.
drhc22bd472002-05-10 13:14:07 +00001165*/
drhc2eef3b2002-08-31 18:53:06 +00001166static int test_create_aggregate(
drhc22bd472002-05-10 13:14:07 +00001167 void *NotUsed,
1168 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1169 int argc, /* Number of arguments */
1170 char **argv /* Text of each argument */
1171){
drh9bb575f2004-09-06 17:24:11 +00001172 sqlite3 *db;
drhc60d0442004-09-30 13:43:13 +00001173 int rc;
drhc22bd472002-05-10 13:14:07 +00001174 if( argc!=2 ){
1175 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1176 " FILENAME\"", 0);
1177 return TCL_ERROR;
1178 }
drhb86ccfb2003-01-28 23:13:10 +00001179 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +00001180 rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
drh4f0c5872007-03-26 22:05:01 +00001181 t1CountStep,t1CountFinalize);
drhc60d0442004-09-30 13:43:13 +00001182 if( rc==SQLITE_OK ){
danielk1977fa18bec2007-09-03 11:04:22 +00001183 rc = sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
drh4f0c5872007-03-26 22:05:01 +00001184 t1CountStep,t1CountFinalize);
drhc60d0442004-09-30 13:43:13 +00001185 }
shaneeec556d2008-10-12 00:27:53 +00001186#ifndef SQLITE_OMIT_DEPRECATED
danielk1977fa18bec2007-09-03 11:04:22 +00001187 if( rc==SQLITE_OK ){
1188 rc = sqlite3_create_function(db, "legacy_count", 0, SQLITE_ANY, 0, 0,
1189 legacyCountStep, legacyCountFinalize
1190 );
1191 }
shaneeec556d2008-10-12 00:27:53 +00001192#endif
drhc60d0442004-09-30 13:43:13 +00001193 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk1977fa18bec2007-09-03 11:04:22 +00001194 Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
drhc22bd472002-05-10 13:14:07 +00001195 return TCL_OK;
1196}
1197
1198
drh3c23a882007-01-09 14:01:13 +00001199/*
1200** Usage: printf TEXT
1201**
1202** Send output to printf. Use this rather than puts to merge the output
1203** in the correct sequence with debugging printfs inserted into C code.
1204** Puts uses a separate buffer and debugging statements will be out of
1205** sequence if it is used.
1206*/
1207static int test_printf(
1208 void *NotUsed,
1209 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1210 int argc, /* Number of arguments */
1211 char **argv /* Text of each argument */
1212){
1213 if( argc!=2 ){
1214 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1215 " TEXT\"", 0);
1216 return TCL_ERROR;
1217 }
1218 printf("%s\n", argv[1]);
1219 return TCL_OK;
1220}
1221
1222
drhc22bd472002-05-10 13:14:07 +00001223
1224/*
danielk19776f8a5032004-05-10 10:34:51 +00001225** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
drhd1bf3512001-04-07 15:24:33 +00001226**
1227** Call mprintf with three integer arguments
1228*/
danielk19776f8a5032004-05-10 10:34:51 +00001229static int sqlite3_mprintf_int(
drhd1bf3512001-04-07 15:24:33 +00001230 void *NotUsed,
1231 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1232 int argc, /* Number of arguments */
1233 char **argv /* Text of each argument */
1234){
1235 int a[3], i;
1236 char *z;
1237 if( argc!=5 ){
1238 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1239 " FORMAT INT INT INT\"", 0);
1240 return TCL_ERROR;
1241 }
1242 for(i=2; i<5; i++){
1243 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
1244 }
danielk19776f8a5032004-05-10 10:34:51 +00001245 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
drhd1bf3512001-04-07 15:24:33 +00001246 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +00001247 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +00001248 return TCL_OK;
1249}
1250
1251/*
drhe9707672004-06-25 01:10:48 +00001252** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
1253**
1254** Call mprintf with three 64-bit integer arguments
1255*/
1256static int sqlite3_mprintf_int64(
1257 void *NotUsed,
1258 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1259 int argc, /* Number of arguments */
1260 char **argv /* Text of each argument */
1261){
1262 int i;
1263 sqlite_int64 a[3];
1264 char *z;
1265 if( argc!=5 ){
1266 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1267 " FORMAT INT INT INT\"", 0);
1268 return TCL_ERROR;
1269 }
1270 for(i=2; i<5; i++){
shaneh5f1d6b62010-09-30 16:51:25 +00001271 if( sqlite3Atoi64(argv[i], &a[i-2], 1000000, SQLITE_UTF8) ){
drhe9707672004-06-25 01:10:48 +00001272 Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
1273 return TCL_ERROR;
1274 }
1275 }
1276 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
1277 Tcl_AppendResult(interp, z, 0);
1278 sqlite3_free(z);
1279 return TCL_OK;
1280}
1281
1282/*
drhc5cad1e2009-02-01 00:21:09 +00001283** Usage: sqlite3_mprintf_long FORMAT INTEGER INTEGER INTEGER
1284**
1285** Call mprintf with three long integer arguments. This might be the
1286** same as sqlite3_mprintf_int or sqlite3_mprintf_int64, depending on
1287** platform.
1288*/
1289static int sqlite3_mprintf_long(
1290 void *NotUsed,
1291 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1292 int argc, /* Number of arguments */
1293 char **argv /* Text of each argument */
1294){
1295 int i;
1296 long int a[3];
1297 int b[3];
1298 char *z;
1299 if( argc!=5 ){
1300 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1301 " FORMAT INT INT INT\"", 0);
1302 return TCL_ERROR;
1303 }
1304 for(i=2; i<5; i++){
1305 if( Tcl_GetInt(interp, argv[i], &b[i-2]) ) return TCL_ERROR;
1306 a[i-2] = (long int)b[i-2];
drh7ed0cae2009-02-03 16:25:47 +00001307 a[i-2] &= (((u64)1)<<(sizeof(int)*8))-1;
drhc5cad1e2009-02-01 00:21:09 +00001308 }
1309 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
1310 Tcl_AppendResult(interp, z, 0);
1311 sqlite3_free(z);
1312 return TCL_OK;
1313}
1314
1315/*
danielk19776f8a5032004-05-10 10:34:51 +00001316** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
drhd1bf3512001-04-07 15:24:33 +00001317**
1318** Call mprintf with two integer arguments and one string argument
1319*/
danielk19776f8a5032004-05-10 10:34:51 +00001320static int sqlite3_mprintf_str(
drhd1bf3512001-04-07 15:24:33 +00001321 void *NotUsed,
1322 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1323 int argc, /* Number of arguments */
1324 char **argv /* Text of each argument */
1325){
1326 int a[3], i;
1327 char *z;
chwf220b242002-06-16 04:54:28 +00001328 if( argc<4 || argc>5 ){
drhd1bf3512001-04-07 15:24:33 +00001329 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
chwf220b242002-06-16 04:54:28 +00001330 " FORMAT INT INT ?STRING?\"", 0);
drhd1bf3512001-04-07 15:24:33 +00001331 return TCL_ERROR;
1332 }
1333 for(i=2; i<4; i++){
1334 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
1335 }
danielk19776f8a5032004-05-10 10:34:51 +00001336 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
drhd1bf3512001-04-07 15:24:33 +00001337 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +00001338 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +00001339 return TCL_OK;
1340}
1341
1342/*
drhb3738b62007-03-31 15:02:49 +00001343** Usage: sqlite3_snprintf_str INTEGER FORMAT INTEGER INTEGER STRING
1344**
1345** Call mprintf with two integer arguments and one string argument
1346*/
1347static int sqlite3_snprintf_str(
1348 void *NotUsed,
1349 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1350 int argc, /* Number of arguments */
1351 char **argv /* Text of each argument */
1352){
1353 int a[3], i;
1354 int n;
1355 char *z;
1356 if( argc<5 || argc>6 ){
1357 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1358 " INT FORMAT INT INT ?STRING?\"", 0);
1359 return TCL_ERROR;
1360 }
1361 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
1362 if( n<0 ){
1363 Tcl_AppendResult(interp, "N must be non-negative", 0);
1364 return TCL_ERROR;
1365 }
1366 for(i=3; i<5; i++){
1367 if( Tcl_GetInt(interp, argv[i], &a[i-3]) ) return TCL_ERROR;
1368 }
1369 z = sqlite3_malloc( n+1 );
1370 sqlite3_snprintf(n, z, argv[2], a[0], a[1], argc>4 ? argv[5] : NULL);
1371 Tcl_AppendResult(interp, z, 0);
1372 sqlite3_free(z);
1373 return TCL_OK;
1374}
1375
1376/*
drh63782852005-08-30 19:30:59 +00001377** Usage: sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE
drhd1bf3512001-04-07 15:24:33 +00001378**
1379** Call mprintf with two integer arguments and one double argument
1380*/
danielk19776f8a5032004-05-10 10:34:51 +00001381static int sqlite3_mprintf_double(
drhd1bf3512001-04-07 15:24:33 +00001382 void *NotUsed,
1383 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1384 int argc, /* Number of arguments */
1385 char **argv /* Text of each argument */
1386){
1387 int a[3], i;
1388 double r;
1389 char *z;
1390 if( argc!=5 ){
1391 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drh63782852005-08-30 19:30:59 +00001392 " FORMAT INT INT DOUBLE\"", 0);
drhd1bf3512001-04-07 15:24:33 +00001393 return TCL_ERROR;
1394 }
1395 for(i=2; i<4; i++){
1396 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
1397 }
1398 if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +00001399 z = sqlite3_mprintf(argv[1], a[0], a[1], r);
drhd1bf3512001-04-07 15:24:33 +00001400 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +00001401 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +00001402 return TCL_OK;
1403}
1404
1405/*
drh63782852005-08-30 19:30:59 +00001406** Usage: sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE
drhb621c232004-02-21 19:41:04 +00001407**
1408** Call mprintf with a single double argument which is the product of the
1409** two arguments given above. This is used to generate overflow and underflow
1410** doubles to test that they are converted properly.
1411*/
danielk19776f8a5032004-05-10 10:34:51 +00001412static int sqlite3_mprintf_scaled(
drhb621c232004-02-21 19:41:04 +00001413 void *NotUsed,
1414 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1415 int argc, /* Number of arguments */
1416 char **argv /* Text of each argument */
1417){
1418 int i;
1419 double r[2];
1420 char *z;
1421 if( argc!=4 ){
1422 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1423 " FORMAT DOUBLE DOUBLE\"", 0);
1424 return TCL_ERROR;
1425 }
1426 for(i=2; i<4; i++){
1427 if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
1428 }
danielk19776f8a5032004-05-10 10:34:51 +00001429 z = sqlite3_mprintf(argv[1], r[0]*r[1]);
drhb621c232004-02-21 19:41:04 +00001430 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +00001431 sqlite3_free(z);
drhb621c232004-02-21 19:41:04 +00001432 return TCL_OK;
1433}
1434
1435/*
drhe29b1a02004-07-17 21:56:09 +00001436** Usage: sqlite3_mprintf_stronly FORMAT STRING
1437**
1438** Call mprintf with a single double argument which is the product of the
1439** two arguments given above. This is used to generate overflow and underflow
1440** doubles to test that they are converted properly.
1441*/
1442static int sqlite3_mprintf_stronly(
1443 void *NotUsed,
1444 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1445 int argc, /* Number of arguments */
1446 char **argv /* Text of each argument */
1447){
1448 char *z;
1449 if( argc!=3 ){
1450 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1451 " FORMAT STRING\"", 0);
1452 return TCL_ERROR;
1453 }
1454 z = sqlite3_mprintf(argv[1], argv[2]);
1455 Tcl_AppendResult(interp, z, 0);
1456 sqlite3_free(z);
1457 return TCL_OK;
1458}
1459
1460/*
drh63782852005-08-30 19:30:59 +00001461** Usage: sqlite3_mprintf_hexdouble FORMAT HEX
1462**
1463** Call mprintf with a single double argument which is derived from the
1464** hexadecimal encoding of an IEEE double.
1465*/
1466static int sqlite3_mprintf_hexdouble(
1467 void *NotUsed,
1468 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1469 int argc, /* Number of arguments */
1470 char **argv /* Text of each argument */
1471){
1472 char *z;
1473 double r;
shane5e73db32008-07-08 03:04:58 +00001474 unsigned int x1, x2;
1475 sqlite_uint64 d;
drh63782852005-08-30 19:30:59 +00001476 if( argc!=3 ){
1477 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1478 " FORMAT STRING\"", 0);
1479 return TCL_ERROR;
1480 }
1481 if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){
1482 Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0);
1483 return TCL_ERROR;
1484 }
1485 d = x2;
1486 d = (d<<32) + x1;
1487 memcpy(&r, &d, sizeof(r));
1488 z = sqlite3_mprintf(argv[1], r);
1489 Tcl_AppendResult(interp, z, 0);
1490 sqlite3_free(z);
1491 return TCL_OK;
1492}
1493
1494/*
danielk1977c1def3e2008-08-30 13:25:10 +00001495** Usage: sqlite3_enable_shared_cache ?BOOLEAN?
danielk1977aef0bf62005-12-30 16:28:01 +00001496**
1497*/
drh6f7adc82006-01-11 21:41:20 +00001498#if !defined(SQLITE_OMIT_SHARED_CACHE)
1499static int test_enable_shared(
danielk197752622822006-01-09 09:59:49 +00001500 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
danielk1977aef0bf62005-12-30 16:28:01 +00001501 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1502 int objc, /* Number of arguments */
1503 Tcl_Obj *CONST objv[] /* Command arguments */
1504){
1505 int rc;
1506 int enable;
danielk197752622822006-01-09 09:59:49 +00001507 int ret = 0;
danielk1977aef0bf62005-12-30 16:28:01 +00001508
danielk1977c1def3e2008-08-30 13:25:10 +00001509 if( objc!=2 && objc!=1 ){
1510 Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?");
danielk1977aef0bf62005-12-30 16:28:01 +00001511 return TCL_ERROR;
1512 }
danielk1977502b4e02008-09-02 14:07:24 +00001513 ret = sqlite3GlobalConfig.sharedCacheEnabled;
danielk1977c1def3e2008-08-30 13:25:10 +00001514
1515 if( objc==2 ){
1516 if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){
1517 return TCL_ERROR;
1518 }
1519 rc = sqlite3_enable_shared_cache(enable);
1520 if( rc!=SQLITE_OK ){
1521 Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
1522 return TCL_ERROR;
1523 }
danielk1977aef0bf62005-12-30 16:28:01 +00001524 }
danielk197752622822006-01-09 09:59:49 +00001525 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret));
danielk1977aef0bf62005-12-30 16:28:01 +00001526 return TCL_OK;
1527}
1528#endif
1529
drh16a9b832007-05-05 18:39:25 +00001530
1531
danielk1977aef0bf62005-12-30 16:28:01 +00001532/*
drh4ac285a2006-09-15 07:28:50 +00001533** Usage: sqlite3_extended_result_codes DB BOOLEAN
1534**
1535*/
1536static int test_extended_result_codes(
1537 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1538 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1539 int objc, /* Number of arguments */
1540 Tcl_Obj *CONST objv[] /* Command arguments */
1541){
1542 int enable;
1543 sqlite3 *db;
1544
1545 if( objc!=3 ){
1546 Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN");
1547 return TCL_ERROR;
1548 }
1549 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1550 if( Tcl_GetBooleanFromObj(interp, objv[2], &enable) ) return TCL_ERROR;
1551 sqlite3_extended_result_codes(db, enable);
1552 return TCL_OK;
1553}
1554
1555/*
danielk1977161fb792006-01-24 10:58:21 +00001556** Usage: sqlite3_libversion_number
1557**
1558*/
1559static int test_libversion_number(
1560 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1561 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1562 int objc, /* Number of arguments */
1563 Tcl_Obj *CONST objv[] /* Command arguments */
1564){
1565 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_libversion_number()));
1566 return TCL_OK;
1567}
1568
1569/*
danielk1977deb802c2006-02-09 13:43:28 +00001570** Usage: sqlite3_table_column_metadata DB dbname tblname colname
1571**
1572*/
danielk1977deb802c2006-02-09 13:43:28 +00001573static int test_table_column_metadata(
1574 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1575 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1576 int objc, /* Number of arguments */
1577 Tcl_Obj *CONST objv[] /* Command arguments */
1578){
1579 sqlite3 *db;
1580 const char *zDb;
1581 const char *zTbl;
1582 const char *zCol;
1583 int rc;
1584 Tcl_Obj *pRet;
1585
1586 const char *zDatatype;
1587 const char *zCollseq;
1588 int notnull;
1589 int primarykey;
1590 int autoincrement;
1591
drh45d1b202014-12-09 22:24:42 +00001592 if( objc!=5 && objc!=4 ){
danielk1977deb802c2006-02-09 13:43:28 +00001593 Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname");
1594 return TCL_ERROR;
1595 }
1596 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1597 zDb = Tcl_GetString(objv[2]);
1598 zTbl = Tcl_GetString(objv[3]);
drh45d1b202014-12-09 22:24:42 +00001599 zCol = objc==5 ? Tcl_GetString(objv[4]) : 0;
danielk1977deb802c2006-02-09 13:43:28 +00001600
1601 if( strlen(zDb)==0 ) zDb = 0;
1602
1603 rc = sqlite3_table_column_metadata(db, zDb, zTbl, zCol,
1604 &zDatatype, &zCollseq, &notnull, &primarykey, &autoincrement);
1605
1606 if( rc!=SQLITE_OK ){
1607 Tcl_AppendResult(interp, sqlite3_errmsg(db), 0);
1608 return TCL_ERROR;
1609 }
1610
1611 pRet = Tcl_NewObj();
1612 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zDatatype, -1));
1613 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zCollseq, -1));
1614 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(notnull));
1615 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(primarykey));
1616 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(autoincrement));
1617 Tcl_SetObjResult(interp, pRet);
1618
1619 return TCL_OK;
1620}
danielk1977deb802c2006-02-09 13:43:28 +00001621
danielk1977dcbb5d32007-05-04 18:36:44 +00001622#ifndef SQLITE_OMIT_INCRBLOB
1623
dan61c7f592010-10-26 18:42:52 +00001624static int blobHandleFromObj(
1625 Tcl_Interp *interp,
1626 Tcl_Obj *pObj,
1627 sqlite3_blob **ppBlob
1628){
1629 char *z;
1630 int n;
1631
1632 z = Tcl_GetStringFromObj(pObj, &n);
1633 if( n==0 ){
1634 *ppBlob = 0;
1635 }else{
1636 int notUsed;
1637 Tcl_Channel channel;
1638 ClientData instanceData;
1639
1640 channel = Tcl_GetChannel(interp, z, &notUsed);
1641 if( !channel ) return TCL_ERROR;
1642
1643 Tcl_Flush(channel);
1644 Tcl_Seek(channel, 0, SEEK_SET);
1645
1646 instanceData = Tcl_GetChannelInstanceData(channel);
1647 *ppBlob = *((sqlite3_blob **)instanceData);
1648 }
1649
1650 return TCL_OK;
1651}
1652
dan4e76cc32010-10-20 18:56:04 +00001653static int test_blob_reopen(
1654 ClientData clientData, /* Not used */
1655 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1656 int objc, /* Number of arguments */
1657 Tcl_Obj *CONST objv[] /* Command arguments */
1658){
1659 Tcl_WideInt iRowid;
dan4e76cc32010-10-20 18:56:04 +00001660 sqlite3_blob *pBlob;
dan4e76cc32010-10-20 18:56:04 +00001661 int rc;
1662
dan4e76cc32010-10-20 18:56:04 +00001663 if( objc!=3 ){
1664 Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL ROWID");
1665 return TCL_ERROR;
1666 }
1667
dan61c7f592010-10-26 18:42:52 +00001668 if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
1669 if( Tcl_GetWideIntFromObj(interp, objv[2], &iRowid) ) return TCL_ERROR;
dan4e76cc32010-10-20 18:56:04 +00001670
1671 rc = sqlite3_blob_reopen(pBlob, iRowid);
1672 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +00001673 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
dan4e76cc32010-10-20 18:56:04 +00001674 }
1675
1676 return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
1677}
1678
danielk1977dcbb5d32007-05-04 18:36:44 +00001679#endif
drhc2e87a32006-06-27 15:16:14 +00001680
danielk1977deb802c2006-02-09 13:43:28 +00001681/*
danielk1977a393c032007-05-07 14:58:53 +00001682** Usage: sqlite3_create_collation_v2 DB-HANDLE NAME CMP-PROC DEL-PROC
danielk1977a9808b32007-05-07 09:32:45 +00001683**
1684** This Tcl proc is used for testing the experimental
danielk1977a393c032007-05-07 14:58:53 +00001685** sqlite3_create_collation_v2() interface.
danielk1977a9808b32007-05-07 09:32:45 +00001686*/
1687struct TestCollationX {
1688 Tcl_Interp *interp;
1689 Tcl_Obj *pCmp;
1690 Tcl_Obj *pDel;
1691};
1692typedef struct TestCollationX TestCollationX;
1693static void testCreateCollationDel(void *pCtx){
1694 TestCollationX *p = (TestCollationX *)pCtx;
1695
1696 int rc = Tcl_EvalObjEx(p->interp, p->pDel, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL);
1697 if( rc!=TCL_OK ){
1698 Tcl_BackgroundError(p->interp);
1699 }
1700
1701 Tcl_DecrRefCount(p->pCmp);
1702 Tcl_DecrRefCount(p->pDel);
1703 sqlite3_free((void *)p);
1704}
1705static int testCreateCollationCmp(
1706 void *pCtx,
1707 int nLeft,
1708 const void *zLeft,
1709 int nRight,
1710 const void *zRight
1711){
1712 TestCollationX *p = (TestCollationX *)pCtx;
1713 Tcl_Obj *pScript = Tcl_DuplicateObj(p->pCmp);
1714 int iRes = 0;
1715
1716 Tcl_IncrRefCount(pScript);
1717 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zLeft, nLeft));
1718 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zRight,nRight));
1719
1720 if( TCL_OK!=Tcl_EvalObjEx(p->interp, pScript, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL)
1721 || TCL_OK!=Tcl_GetIntFromObj(p->interp, Tcl_GetObjResult(p->interp), &iRes)
1722 ){
1723 Tcl_BackgroundError(p->interp);
1724 }
1725 Tcl_DecrRefCount(pScript);
1726
1727 return iRes;
1728}
danielk1977a393c032007-05-07 14:58:53 +00001729static int test_create_collation_v2(
danielk1977a9808b32007-05-07 09:32:45 +00001730 ClientData clientData, /* Not used */
1731 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1732 int objc, /* Number of arguments */
1733 Tcl_Obj *CONST objv[] /* Command arguments */
1734){
1735 TestCollationX *p;
1736 sqlite3 *db;
drhd55d57e2008-07-07 17:53:07 +00001737 int rc;
danielk1977a9808b32007-05-07 09:32:45 +00001738
1739 if( objc!=5 ){
1740 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE NAME CMP-PROC DEL-PROC");
1741 return TCL_ERROR;
1742 }
1743 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1744
1745 p = (TestCollationX *)sqlite3_malloc(sizeof(TestCollationX));
1746 p->pCmp = objv[3];
1747 p->pDel = objv[4];
1748 p->interp = interp;
1749 Tcl_IncrRefCount(p->pCmp);
1750 Tcl_IncrRefCount(p->pDel);
1751
drhd55d57e2008-07-07 17:53:07 +00001752 rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), 16,
1753 (void *)p, testCreateCollationCmp, testCreateCollationDel
1754 );
1755 if( rc!=SQLITE_MISUSE ){
1756 Tcl_AppendResult(interp, "sqlite3_create_collate_v2() failed to detect "
1757 "an invalid encoding", (char*)0);
1758 return TCL_ERROR;
1759 }
1760 rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), SQLITE_UTF8,
danielk1977a9808b32007-05-07 09:32:45 +00001761 (void *)p, testCreateCollationCmp, testCreateCollationDel
1762 );
1763 return TCL_OK;
1764}
1765
1766/*
dand2199f02010-08-27 17:48:52 +00001767** USAGE: sqlite3_create_function_v2 DB NAME NARG ENC ?SWITCHES?
1768**
1769** Available switches are:
1770**
1771** -func SCRIPT
1772** -step SCRIPT
1773** -final SCRIPT
1774** -destroy SCRIPT
1775*/
1776typedef struct CreateFunctionV2 CreateFunctionV2;
1777struct CreateFunctionV2 {
1778 Tcl_Interp *interp;
1779 Tcl_Obj *pFunc; /* Script for function invocation */
1780 Tcl_Obj *pStep; /* Script for agg. step invocation */
1781 Tcl_Obj *pFinal; /* Script for agg. finalization invocation */
1782 Tcl_Obj *pDestroy; /* Destructor script */
1783};
1784static void cf2Func(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
1785}
1786static void cf2Step(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
1787}
1788static void cf2Final(sqlite3_context *ctx){
1789}
1790static void cf2Destroy(void *pUser){
1791 CreateFunctionV2 *p = (CreateFunctionV2 *)pUser;
1792
1793 if( p->interp && p->pDestroy ){
1794 int rc = Tcl_EvalObjEx(p->interp, p->pDestroy, 0);
1795 if( rc!=TCL_OK ) Tcl_BackgroundError(p->interp);
1796 }
1797
1798 if( p->pFunc ) Tcl_DecrRefCount(p->pFunc);
1799 if( p->pStep ) Tcl_DecrRefCount(p->pStep);
1800 if( p->pFinal ) Tcl_DecrRefCount(p->pFinal);
1801 if( p->pDestroy ) Tcl_DecrRefCount(p->pDestroy);
1802 sqlite3_free(p);
1803}
1804static int test_create_function_v2(
1805 ClientData clientData, /* Not used */
1806 Tcl_Interp *interp, /* The invoking TCL interpreter */
1807 int objc, /* Number of arguments */
1808 Tcl_Obj *CONST objv[] /* Command arguments */
1809){
1810 sqlite3 *db;
1811 const char *zFunc;
1812 int nArg;
1813 int enc;
1814 CreateFunctionV2 *p;
1815 int i;
1816 int rc;
1817
1818 struct EncTable {
1819 const char *zEnc;
1820 int enc;
1821 } aEnc[] = {
1822 {"utf8", SQLITE_UTF8 },
1823 {"utf16", SQLITE_UTF16 },
1824 {"utf16le", SQLITE_UTF16LE },
1825 {"utf16be", SQLITE_UTF16BE },
1826 {"any", SQLITE_ANY },
1827 {"0", 0 }
1828 };
1829
1830 if( objc<5 || (objc%2)==0 ){
1831 Tcl_WrongNumArgs(interp, 1, objv, "DB NAME NARG ENC SWITCHES...");
1832 return TCL_ERROR;
1833 }
1834
1835 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1836 zFunc = Tcl_GetString(objv[2]);
1837 if( Tcl_GetIntFromObj(interp, objv[3], &nArg) ) return TCL_ERROR;
1838 if( Tcl_GetIndexFromObjStruct(interp, objv[4], aEnc, sizeof(aEnc[0]),
1839 "encoding", 0, &enc)
1840 ){
1841 return TCL_ERROR;
1842 }
1843 enc = aEnc[enc].enc;
1844
1845 p = sqlite3_malloc(sizeof(CreateFunctionV2));
1846 assert( p );
1847 memset(p, 0, sizeof(CreateFunctionV2));
1848 p->interp = interp;
1849
1850 for(i=5; i<objc; i+=2){
1851 int iSwitch;
1852 const char *azSwitch[] = {"-func", "-step", "-final", "-destroy", 0};
1853 if( Tcl_GetIndexFromObj(interp, objv[i], azSwitch, "switch", 0, &iSwitch) ){
1854 sqlite3_free(p);
1855 return TCL_ERROR;
1856 }
1857
1858 switch( iSwitch ){
1859 case 0: p->pFunc = objv[i+1]; break;
1860 case 1: p->pStep = objv[i+1]; break;
1861 case 2: p->pFinal = objv[i+1]; break;
1862 case 3: p->pDestroy = objv[i+1]; break;
1863 }
1864 }
1865 if( p->pFunc ) p->pFunc = Tcl_DuplicateObj(p->pFunc);
1866 if( p->pStep ) p->pStep = Tcl_DuplicateObj(p->pStep);
1867 if( p->pFinal ) p->pFinal = Tcl_DuplicateObj(p->pFinal);
1868 if( p->pDestroy ) p->pDestroy = Tcl_DuplicateObj(p->pDestroy);
1869
1870 if( p->pFunc ) Tcl_IncrRefCount(p->pFunc);
1871 if( p->pStep ) Tcl_IncrRefCount(p->pStep);
1872 if( p->pFinal ) Tcl_IncrRefCount(p->pFinal);
1873 if( p->pDestroy ) Tcl_IncrRefCount(p->pDestroy);
1874
1875 rc = sqlite3_create_function_v2(db, zFunc, nArg, enc, (void *)p,
1876 (p->pFunc ? cf2Func : 0),
1877 (p->pStep ? cf2Step : 0),
1878 (p->pFinal ? cf2Final : 0),
1879 cf2Destroy
1880 );
1881 if( rc!=SQLITE_OK ){
dand2199f02010-08-27 17:48:52 +00001882 Tcl_ResetResult(interp);
mistachkine84d8d32013-04-29 03:09:10 +00001883 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
dand2199f02010-08-27 17:48:52 +00001884 return TCL_ERROR;
1885 }
1886 return TCL_OK;
1887}
1888
1889/*
danielk197769e777f2006-06-14 10:38:02 +00001890** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC?
1891*/
1892static int test_load_extension(
1893 ClientData clientData, /* Not used */
1894 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1895 int objc, /* Number of arguments */
1896 Tcl_Obj *CONST objv[] /* Command arguments */
1897){
1898 Tcl_CmdInfo cmdInfo;
1899 sqlite3 *db;
1900 int rc;
1901 char *zDb;
1902 char *zFile;
1903 char *zProc = 0;
1904 char *zErr = 0;
1905
1906 if( objc!=4 && objc!=3 ){
1907 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?");
1908 return TCL_ERROR;
1909 }
1910 zDb = Tcl_GetString(objv[1]);
1911 zFile = Tcl_GetString(objv[2]);
1912 if( objc==4 ){
1913 zProc = Tcl_GetString(objv[3]);
1914 }
1915
1916 /* Extract the C database handle from the Tcl command name */
1917 if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
1918 Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
1919 return TCL_ERROR;
1920 }
1921 db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
1922 assert(db);
1923
1924 /* Call the underlying C function. If an error occurs, set rc to
1925 ** TCL_ERROR and load any error string into the interpreter. If no
1926 ** error occurs, set rc to TCL_OK.
1927 */
drhc2e87a32006-06-27 15:16:14 +00001928#ifdef SQLITE_OMIT_LOAD_EXTENSION
1929 rc = SQLITE_ERROR;
1930 zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()");
1931#else
danielk197769e777f2006-06-14 10:38:02 +00001932 rc = sqlite3_load_extension(db, zFile, zProc, &zErr);
drhc2e87a32006-06-27 15:16:14 +00001933#endif
danielk197769e777f2006-06-14 10:38:02 +00001934 if( rc!=SQLITE_OK ){
1935 Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE);
1936 rc = TCL_ERROR;
1937 }else{
1938 rc = TCL_OK;
1939 }
1940 sqlite3_free(zErr);
1941
1942 return rc;
1943}
1944
1945/*
drhc2e87a32006-06-27 15:16:14 +00001946** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF
1947*/
1948static int test_enable_load(
1949 ClientData clientData, /* Not used */
1950 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1951 int objc, /* Number of arguments */
1952 Tcl_Obj *CONST objv[] /* Command arguments */
1953){
1954 Tcl_CmdInfo cmdInfo;
1955 sqlite3 *db;
1956 char *zDb;
1957 int onoff;
1958
1959 if( objc!=3 ){
1960 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF");
1961 return TCL_ERROR;
1962 }
1963 zDb = Tcl_GetString(objv[1]);
1964
1965 /* Extract the C database handle from the Tcl command name */
1966 if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
1967 Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
1968 return TCL_ERROR;
1969 }
1970 db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
1971 assert(db);
1972
1973 /* Get the onoff parameter */
1974 if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){
1975 return TCL_ERROR;
1976 }
1977
1978#ifdef SQLITE_OMIT_LOAD_EXTENSION
1979 Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()");
1980 return TCL_ERROR;
1981#else
1982 sqlite3_enable_load_extension(db, onoff);
1983 return TCL_OK;
1984#endif
1985}
1986
1987/*
drh28b4e482002-03-11 02:06:13 +00001988** Usage: sqlite_abort
1989**
1990** Shutdown the process immediately. This is not a clean shutdown.
1991** This command is used to test the recoverability of a database in
1992** the event of a program crash.
1993*/
1994static int sqlite_abort(
1995 void *NotUsed,
1996 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1997 int argc, /* Number of arguments */
1998 char **argv /* Text of each argument */
1999){
shaneh2ceced12010-07-07 16:51:36 +00002000#if defined(_MSC_VER)
2001 /* We do this, otherwise the test will halt with a popup message
2002 * that we have to click away before the test will continue.
2003 */
2004 _set_abort_behavior( 0, _CALL_REPORTFAULT );
2005#endif
dand3f6b812010-07-19 12:44:14 +00002006 exit(255);
drh28b4e482002-03-11 02:06:13 +00002007 assert( interp==0 ); /* This will always fail */
2008 return TCL_OK;
2009}
2010
2011/*
drh6cbe1f12002-07-01 00:31:36 +00002012** The following routine is a user-defined SQL function whose purpose
2013** is to test the sqlite_set_result() API.
2014*/
danielk19770ae8b832004-05-25 12:05:56 +00002015static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
drh6cbe1f12002-07-01 00:31:36 +00002016 while( argc>=2 ){
drh03d847e2005-12-09 20:21:58 +00002017 const char *zArg0 = (char*)sqlite3_value_text(argv[0]);
danielk19776d88bad2004-05-27 14:23:36 +00002018 if( zArg0 ){
2019 if( 0==sqlite3StrICmp(zArg0, "int") ){
2020 sqlite3_result_int(context, sqlite3_value_int(argv[1]));
2021 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
2022 sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
2023 }else if( sqlite3StrICmp(zArg0,"string")==0 ){
drh03d847e2005-12-09 20:21:58 +00002024 sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1,
danielk1977d8123362004-06-12 09:25:12 +00002025 SQLITE_TRANSIENT);
danielk19776d88bad2004-05-27 14:23:36 +00002026 }else if( sqlite3StrICmp(zArg0,"double")==0 ){
2027 sqlite3_result_double(context, sqlite3_value_double(argv[1]));
2028 }else if( sqlite3StrICmp(zArg0,"null")==0 ){
2029 sqlite3_result_null(context);
2030 }else if( sqlite3StrICmp(zArg0,"value")==0 ){
2031 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
2032 }else{
2033 goto error_out;
2034 }
drh6cbe1f12002-07-01 00:31:36 +00002035 }else{
danielk19776d88bad2004-05-27 14:23:36 +00002036 goto error_out;
drh6cbe1f12002-07-01 00:31:36 +00002037 }
2038 argc -= 2;
2039 argv += 2;
2040 }
danielk19776d88bad2004-05-27 14:23:36 +00002041 return;
2042
2043error_out:
2044 sqlite3_result_error(context,"first argument should be one of: "
2045 "int int64 string double null value", -1);
drh6cbe1f12002-07-01 00:31:36 +00002046}
2047
2048/*
2049** Usage: sqlite_register_test_function DB NAME
2050**
2051** Register the test SQL function on the database DB under the name NAME.
2052*/
drhc2eef3b2002-08-31 18:53:06 +00002053static int test_register_func(
drh6cbe1f12002-07-01 00:31:36 +00002054 void *NotUsed,
2055 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
2056 int argc, /* Number of arguments */
2057 char **argv /* Text of each argument */
2058){
drh9bb575f2004-09-06 17:24:11 +00002059 sqlite3 *db;
drh6cbe1f12002-07-01 00:31:36 +00002060 int rc;
2061 if( argc!=3 ){
2062 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2063 " DB FUNCTION-NAME", 0);
2064 return TCL_ERROR;
2065 }
drhb86ccfb2003-01-28 23:13:10 +00002066 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977f9d64d22004-06-19 08:18:07 +00002067 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
danielk1977d8123362004-06-12 09:25:12 +00002068 testFunc, 0, 0);
drh6cbe1f12002-07-01 00:31:36 +00002069 if( rc!=0 ){
danielk1977f20b21c2004-05-31 23:56:42 +00002070 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
drh6cbe1f12002-07-01 00:31:36 +00002071 return TCL_ERROR;
2072 }
drhc60d0442004-09-30 13:43:13 +00002073 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drh6cbe1f12002-07-01 00:31:36 +00002074 return TCL_OK;
2075}
2076
2077/*
danielk1977106bb232004-05-21 10:08:53 +00002078** Usage: sqlite3_finalize STMT
drhb86ccfb2003-01-28 23:13:10 +00002079**
danielk1977106bb232004-05-21 10:08:53 +00002080** Finalize a statement handle.
drhb86ccfb2003-01-28 23:13:10 +00002081*/
2082static int test_finalize(
danielk1977106bb232004-05-21 10:08:53 +00002083 void * clientData,
2084 Tcl_Interp *interp,
2085 int objc,
2086 Tcl_Obj *CONST objv[]
drhb86ccfb2003-01-28 23:13:10 +00002087){
danielk1977106bb232004-05-21 10:08:53 +00002088 sqlite3_stmt *pStmt;
drhb86ccfb2003-01-28 23:13:10 +00002089 int rc;
drhdddb2f22007-01-03 23:37:28 +00002090 sqlite3 *db = 0;
danielk1977106bb232004-05-21 10:08:53 +00002091
2092 if( objc!=2 ){
2093 Tcl_AppendResult(interp, "wrong # args: should be \"",
2094 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
drhb86ccfb2003-01-28 23:13:10 +00002095 return TCL_ERROR;
2096 }
danielk1977106bb232004-05-21 10:08:53 +00002097
2098 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2099
danielk19774397de52005-01-12 12:44:03 +00002100 if( pStmt ){
2101 db = StmtToDb(pStmt);
2102 }
danielk1977fc57d7b2004-05-26 02:04:57 +00002103 rc = sqlite3_finalize(pStmt);
drh4f0c5872007-03-26 22:05:01 +00002104 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
danielk19774397de52005-01-12 12:44:03 +00002105 if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk1977106bb232004-05-21 10:08:53 +00002106 return TCL_OK;
2107}
2108
2109/*
drhd1d38482008-10-07 23:46:38 +00002110** Usage: sqlite3_stmt_status STMT CODE RESETFLAG
2111**
2112** Get the value of a status counter from a statement.
2113*/
2114static int test_stmt_status(
2115 void * clientData,
2116 Tcl_Interp *interp,
2117 int objc,
2118 Tcl_Obj *CONST objv[]
2119){
2120 int iValue;
mistachkin27b2f052015-01-12 19:49:46 +00002121 int i, op = 0, resetFlag;
drhd1d38482008-10-07 23:46:38 +00002122 const char *zOpName;
2123 sqlite3_stmt *pStmt;
2124
2125 static const struct {
2126 const char *zName;
2127 int op;
2128 } aOp[] = {
2129 { "SQLITE_STMTSTATUS_FULLSCAN_STEP", SQLITE_STMTSTATUS_FULLSCAN_STEP },
2130 { "SQLITE_STMTSTATUS_SORT", SQLITE_STMTSTATUS_SORT },
drha21a64d2010-04-06 22:33:55 +00002131 { "SQLITE_STMTSTATUS_AUTOINDEX", SQLITE_STMTSTATUS_AUTOINDEX },
drhbf159fa2013-06-25 22:01:22 +00002132 { "SQLITE_STMTSTATUS_VM_STEP", SQLITE_STMTSTATUS_VM_STEP },
drhd1d38482008-10-07 23:46:38 +00002133 };
2134 if( objc!=4 ){
2135 Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG");
2136 return TCL_ERROR;
2137 }
2138 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2139 zOpName = Tcl_GetString(objv[2]);
2140 for(i=0; i<ArraySize(aOp); i++){
2141 if( strcmp(aOp[i].zName, zOpName)==0 ){
2142 op = aOp[i].op;
2143 break;
2144 }
2145 }
2146 if( i>=ArraySize(aOp) ){
2147 if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR;
2148 }
2149 if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR;
2150 iValue = sqlite3_stmt_status(pStmt, op, resetFlag);
2151 Tcl_SetObjResult(interp, Tcl_NewIntObj(iValue));
2152 return TCL_OK;
2153}
2154
dan04489b62014-10-31 20:11:32 +00002155#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
2156/*
2157** Usage: sqlite3_stmt_scanstatus STMT IDX
2158*/
2159static int test_stmt_scanstatus(
2160 void * clientData,
2161 Tcl_Interp *interp,
2162 int objc,
2163 Tcl_Obj *CONST objv[]
2164){
2165 sqlite3_stmt *pStmt; /* First argument */
2166 int idx; /* Second argument */
2167
2168 const char *zName;
2169 const char *zExplain;
2170 sqlite3_int64 nLoop;
2171 sqlite3_int64 nVisit;
drh518140e2014-11-06 03:55:10 +00002172 double rEst;
dan04489b62014-10-31 20:11:32 +00002173 int res;
2174
2175 if( objc!=3 ){
2176 Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX");
2177 return TCL_ERROR;
2178 }
2179 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2180 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
2181
drhd1a1c232014-11-03 16:35:55 +00002182 res = sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop);
dan04489b62014-10-31 20:11:32 +00002183 if( res==0 ){
2184 Tcl_Obj *pRet = Tcl_NewObj();
2185 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nLoop", -1));
2186 Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nLoop));
drhd1a1c232014-11-03 16:35:55 +00002187 sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
dan04489b62014-10-31 20:11:32 +00002188 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nVisit", -1));
2189 Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nVisit));
drh518140e2014-11-06 03:55:10 +00002190 sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EST, (void*)&rEst);
dan04489b62014-10-31 20:11:32 +00002191 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nEst", -1));
drh518140e2014-11-06 03:55:10 +00002192 Tcl_ListObjAppendElement(0, pRet, Tcl_NewDoubleObj(rEst));
drhd1a1c232014-11-03 16:35:55 +00002193 sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NAME, (void*)&zName);
dan04489b62014-10-31 20:11:32 +00002194 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zName", -1));
2195 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zName, -1));
drhd1a1c232014-11-03 16:35:55 +00002196 sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
dan04489b62014-10-31 20:11:32 +00002197 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zExplain", -1));
2198 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zExplain, -1));
2199 Tcl_SetObjResult(interp, pRet);
2200 }else{
2201 Tcl_ResetResult(interp);
2202 }
2203 return TCL_OK;
2204}
2205
2206/*
2207** Usage: sqlite3_stmt_scanstatus_reset STMT
2208*/
2209static int test_stmt_scanstatus_reset(
2210 void * clientData,
2211 Tcl_Interp *interp,
2212 int objc,
2213 Tcl_Obj *CONST objv[]
2214){
2215 sqlite3_stmt *pStmt; /* First argument */
2216 if( objc!=2 ){
2217 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
2218 return TCL_ERROR;
2219 }
2220 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2221 sqlite3_stmt_scanstatus_reset(pStmt);
2222 return TCL_OK;
2223}
2224#endif
2225
drhd1d38482008-10-07 23:46:38 +00002226/*
drhbb5a9c32008-06-19 02:52:25 +00002227** Usage: sqlite3_next_stmt DB STMT
2228**
2229** Return the next statment in sequence after STMT.
2230*/
2231static int test_next_stmt(
2232 void * clientData,
2233 Tcl_Interp *interp,
2234 int objc,
2235 Tcl_Obj *CONST objv[]
2236){
2237 sqlite3_stmt *pStmt;
2238 sqlite3 *db = 0;
2239 char zBuf[50];
2240
2241 if( objc!=3 ){
2242 Tcl_AppendResult(interp, "wrong # args: should be \"",
2243 Tcl_GetStringFromObj(objv[0], 0), " DB STMT", 0);
2244 return TCL_ERROR;
2245 }
2246
2247 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2248 if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt) ) return TCL_ERROR;
2249 pStmt = sqlite3_next_stmt(db, pStmt);
2250 if( pStmt ){
2251 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
2252 Tcl_AppendResult(interp, zBuf, 0);
2253 }
2254 return TCL_OK;
2255}
2256
drhf03d9cc2010-11-16 23:10:25 +00002257/*
2258** Usage: sqlite3_stmt_readonly STMT
2259**
2260** Return true if STMT is a NULL pointer or a pointer to a statement
2261** that is guaranteed to leave the database unmodified.
2262*/
2263static int test_stmt_readonly(
2264 void * clientData,
2265 Tcl_Interp *interp,
2266 int objc,
2267 Tcl_Obj *CONST objv[]
2268){
2269 sqlite3_stmt *pStmt;
2270 int rc;
2271
2272 if( objc!=2 ){
2273 Tcl_AppendResult(interp, "wrong # args: should be \"",
2274 Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
2275 return TCL_ERROR;
2276 }
2277
2278 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2279 rc = sqlite3_stmt_readonly(pStmt);
2280 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
2281 return TCL_OK;
2282}
2283
dand9495cd2011-04-27 12:08:04 +00002284/*
drh2fb66932011-11-25 17:21:47 +00002285** Usage: sqlite3_stmt_busy STMT
2286**
2287** Return true if STMT is a non-NULL pointer to a statement
2288** that has been stepped but not to completion.
2289*/
2290static int test_stmt_busy(
2291 void * clientData,
2292 Tcl_Interp *interp,
2293 int objc,
2294 Tcl_Obj *CONST objv[]
2295){
2296 sqlite3_stmt *pStmt;
2297 int rc;
2298
2299 if( objc!=2 ){
2300 Tcl_AppendResult(interp, "wrong # args: should be \"",
2301 Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
2302 return TCL_ERROR;
2303 }
2304
2305 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2306 rc = sqlite3_stmt_busy(pStmt);
2307 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
2308 return TCL_OK;
2309}
2310
2311/*
dand9495cd2011-04-27 12:08:04 +00002312** Usage: uses_stmt_journal STMT
2313**
2314** Return true if STMT uses a statement journal.
2315*/
2316static int uses_stmt_journal(
2317 void * clientData,
2318 Tcl_Interp *interp,
2319 int objc,
2320 Tcl_Obj *CONST objv[]
2321){
2322 sqlite3_stmt *pStmt;
dand9495cd2011-04-27 12:08:04 +00002323
2324 if( objc!=2 ){
2325 Tcl_AppendResult(interp, "wrong # args: should be \"",
2326 Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
2327 return TCL_ERROR;
2328 }
2329
2330 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
drhcaffb1a2012-01-30 18:00:31 +00002331 sqlite3_stmt_readonly(pStmt);
dand9495cd2011-04-27 12:08:04 +00002332 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(((Vdbe *)pStmt)->usesStmtJournal));
2333 return TCL_OK;
2334}
2335
drhbb5a9c32008-06-19 02:52:25 +00002336
2337/*
danielk1977106bb232004-05-21 10:08:53 +00002338** Usage: sqlite3_reset STMT
2339**
danielk1977261919c2005-12-06 12:52:59 +00002340** Reset a statement handle.
danielk1977106bb232004-05-21 10:08:53 +00002341*/
2342static int test_reset(
2343 void * clientData,
2344 Tcl_Interp *interp,
2345 int objc,
2346 Tcl_Obj *CONST objv[]
2347){
2348 sqlite3_stmt *pStmt;
2349 int rc;
2350
2351 if( objc!=2 ){
2352 Tcl_AppendResult(interp, "wrong # args: should be \"",
2353 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
2354 return TCL_ERROR;
2355 }
2356
2357 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2358
danielk1977fc57d7b2004-05-26 02:04:57 +00002359 rc = sqlite3_reset(pStmt);
danielk1977261919c2005-12-06 12:52:59 +00002360 if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){
2361 return TCL_ERROR;
2362 }
drh4f0c5872007-03-26 22:05:01 +00002363 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
danielk1977261919c2005-12-06 12:52:59 +00002364/*
danielk1977106bb232004-05-21 10:08:53 +00002365 if( rc ){
drhb86ccfb2003-01-28 23:13:10 +00002366 return TCL_ERROR;
2367 }
danielk1977261919c2005-12-06 12:52:59 +00002368*/
drhb86ccfb2003-01-28 23:13:10 +00002369 return TCL_OK;
2370}
2371
drh5a387052003-01-11 14:19:51 +00002372/*
drhd89bd002005-01-22 03:03:54 +00002373** Usage: sqlite3_expired STMT
2374**
2375** Return TRUE if a recompilation of the statement is recommended.
2376*/
2377static int test_expired(
2378 void * clientData,
2379 Tcl_Interp *interp,
2380 int objc,
2381 Tcl_Obj *CONST objv[]
2382){
shaneeec556d2008-10-12 00:27:53 +00002383#ifndef SQLITE_OMIT_DEPRECATED
drhd89bd002005-01-22 03:03:54 +00002384 sqlite3_stmt *pStmt;
2385 if( objc!=2 ){
2386 Tcl_AppendResult(interp, "wrong # args: should be \"",
2387 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
2388 return TCL_ERROR;
2389 }
2390 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2391 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt)));
shaneeec556d2008-10-12 00:27:53 +00002392#endif
drhd89bd002005-01-22 03:03:54 +00002393 return TCL_OK;
2394}
2395
2396/*
drhf8db1bc2005-04-22 02:38:37 +00002397** Usage: sqlite3_transfer_bindings FROMSTMT TOSTMT
2398**
2399** Transfer all bindings from FROMSTMT over to TOSTMT
2400*/
2401static int test_transfer_bind(
2402 void * clientData,
2403 Tcl_Interp *interp,
2404 int objc,
2405 Tcl_Obj *CONST objv[]
2406){
shaneeec556d2008-10-12 00:27:53 +00002407#ifndef SQLITE_OMIT_DEPRECATED
drhf8db1bc2005-04-22 02:38:37 +00002408 sqlite3_stmt *pStmt1, *pStmt2;
2409 if( objc!=3 ){
2410 Tcl_AppendResult(interp, "wrong # args: should be \"",
2411 Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0);
2412 return TCL_ERROR;
2413 }
2414 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR;
2415 if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR;
2416 Tcl_SetObjResult(interp,
2417 Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2)));
shaneeec556d2008-10-12 00:27:53 +00002418#endif
drhf8db1bc2005-04-22 02:38:37 +00002419 return TCL_OK;
2420}
2421
2422/*
danielk1977fbcd5852004-06-15 02:44:18 +00002423** Usage: sqlite3_changes DB
drh50457892003-09-06 01:10:47 +00002424**
danielk1977fbcd5852004-06-15 02:44:18 +00002425** Return the number of changes made to the database by the last SQL
2426** execution.
drh50457892003-09-06 01:10:47 +00002427*/
danielk1977fbcd5852004-06-15 02:44:18 +00002428static int test_changes(
2429 void * clientData,
2430 Tcl_Interp *interp,
2431 int objc,
2432 Tcl_Obj *CONST objv[]
2433){
2434 sqlite3 *db;
2435 if( objc!=2 ){
2436 Tcl_AppendResult(interp, "wrong # args: should be \"",
2437 Tcl_GetString(objv[0]), " DB", 0);
2438 return TCL_ERROR;
2439 }
2440 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2441 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
2442 return TCL_OK;
2443}
drh50457892003-09-06 01:10:47 +00002444
2445/*
drh7c972de2003-09-06 22:18:07 +00002446** This is the "static_bind_value" that variables are bound to when
danielk19776f8a5032004-05-10 10:34:51 +00002447** the FLAG option of sqlite3_bind is "static"
drh50457892003-09-06 01:10:47 +00002448*/
drh7c972de2003-09-06 22:18:07 +00002449static char *sqlite_static_bind_value = 0;
drhf0313812006-09-04 15:53:53 +00002450static int sqlite_static_bind_nbyte = 0;
drh7c972de2003-09-06 22:18:07 +00002451
2452/*
danielk19776f8a5032004-05-10 10:34:51 +00002453** Usage: sqlite3_bind VM IDX VALUE FLAGS
drh7c972de2003-09-06 22:18:07 +00002454**
drhf7b54962013-05-28 12:11:54 +00002455** Sets the value of the IDX-th occurrence of "?" in the original SQL
drh7c972de2003-09-06 22:18:07 +00002456** string. VALUE is the new value. If FLAGS=="null" then VALUE is
2457** ignored and the value is set to NULL. If FLAGS=="static" then
2458** the value is set to the value of a static variable named
2459** "sqlite_static_bind_value". If FLAGS=="normal" then a copy
drhbf8aa2a2005-12-02 02:44:05 +00002460** of the VALUE is made. If FLAGS=="blob10" then a VALUE is ignored
2461** an a 10-byte blob "abc\000xyz\000pq" is inserted.
drh7c972de2003-09-06 22:18:07 +00002462*/
2463static int test_bind(
drh50457892003-09-06 01:10:47 +00002464 void *NotUsed,
2465 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
2466 int argc, /* Number of arguments */
2467 char **argv /* Text of each argument */
2468){
danielk1977fc57d7b2004-05-26 02:04:57 +00002469 sqlite3_stmt *pStmt;
drh50457892003-09-06 01:10:47 +00002470 int rc;
drh7c972de2003-09-06 22:18:07 +00002471 int idx;
2472 if( argc!=5 ){
drh50457892003-09-06 01:10:47 +00002473 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drh7c972de2003-09-06 22:18:07 +00002474 " VM IDX VALUE (null|static|normal)\"", 0);
drh50457892003-09-06 01:10:47 +00002475 return TCL_ERROR;
2476 }
danielk1977fc57d7b2004-05-26 02:04:57 +00002477 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
drh7c972de2003-09-06 22:18:07 +00002478 if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
2479 if( strcmp(argv[4],"null")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +00002480 rc = sqlite3_bind_null(pStmt, idx);
drh7c972de2003-09-06 22:18:07 +00002481 }else if( strcmp(argv[4],"static")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +00002482 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
drhf0313812006-09-04 15:53:53 +00002483 }else if( strcmp(argv[4],"static-nbytes")==0 ){
2484 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value,
2485 sqlite_static_bind_nbyte, 0);
drh7c972de2003-09-06 22:18:07 +00002486 }else if( strcmp(argv[4],"normal")==0 ){
danielk1977d8123362004-06-12 09:25:12 +00002487 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
drhbf8aa2a2005-12-02 02:44:05 +00002488 }else if( strcmp(argv[4],"blob10")==0 ){
2489 rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC);
drh7c972de2003-09-06 22:18:07 +00002490 }else{
2491 Tcl_AppendResult(interp, "4th argument should be "
2492 "\"null\" or \"static\" or \"normal\"", 0);
2493 return TCL_ERROR;
2494 }
drhc60d0442004-09-30 13:43:13 +00002495 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
drh50457892003-09-06 01:10:47 +00002496 if( rc ){
2497 char zBuf[50];
drh65545b52015-01-19 00:35:53 +00002498 sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
danielk1977f20b21c2004-05-31 23:56:42 +00002499 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
drh50457892003-09-06 01:10:47 +00002500 return TCL_ERROR;
2501 }
2502 return TCL_OK;
2503}
2504
drh5436dc22004-11-14 04:04:17 +00002505#ifndef SQLITE_OMIT_UTF16
danielk19774e6af132004-06-10 14:01:08 +00002506/*
2507** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
2508**
2509** This function is used to test that SQLite selects the correct collation
2510** sequence callback when multiple versions (for different text encodings)
2511** are available.
2512**
2513** Calling this routine registers the collation sequence "test_collate"
2514** with database handle <db>. The second argument must be a list of three
2515** boolean values. If the first is true, then a version of test_collate is
2516** registered for UTF-8, if the second is true, a version is registered for
2517** UTF-16le, if the third is true, a UTF-16be version is available.
2518** Previous versions of test_collate are deleted.
2519**
2520** The collation sequence test_collate is implemented by calling the
2521** following TCL script:
2522**
2523** "test_collate <enc> <lhs> <rhs>"
2524**
2525** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
2526** The <enc> parameter is the encoding of the collation function that
2527** SQLite selected to call. The TCL test script implements the
2528** "test_collate" proc.
2529**
peter.d.reid60ec9142014-09-06 16:39:46 +00002530** Note that this will only work with one interpreter at a time, as the
danielk19774e6af132004-06-10 14:01:08 +00002531** interp pointer to use when evaluating the TCL script is stored in
2532** pTestCollateInterp.
2533*/
2534static Tcl_Interp* pTestCollateInterp;
2535static int test_collate_func(
2536 void *pCtx,
2537 int nA, const void *zA,
2538 int nB, const void *zB
2539){
2540 Tcl_Interp *i = pTestCollateInterp;
dand2199f02010-08-27 17:48:52 +00002541 int encin = SQLITE_PTR_TO_INT(pCtx);
danielk19774e6af132004-06-10 14:01:08 +00002542 int res;
drh4db38a72005-09-01 12:16:28 +00002543 int n;
danielk19774e6af132004-06-10 14:01:08 +00002544
2545 sqlite3_value *pVal;
2546 Tcl_Obj *pX;
2547
2548 pX = Tcl_NewStringObj("test_collate", -1);
2549 Tcl_IncrRefCount(pX);
2550
2551 switch( encin ){
2552 case SQLITE_UTF8:
2553 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
2554 break;
2555 case SQLITE_UTF16LE:
2556 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
2557 break;
2558 case SQLITE_UTF16BE:
2559 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
2560 break;
2561 default:
2562 assert(0);
2563 }
2564
dan02fa4692009-08-17 17:06:58 +00002565 sqlite3BeginBenignMalloc();
danielk19771e536952007-08-16 10:09:01 +00002566 pVal = sqlite3ValueNew(0);
dan02fa4692009-08-17 17:06:58 +00002567 if( pVal ){
2568 sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
2569 n = sqlite3_value_bytes(pVal);
2570 Tcl_ListObjAppendElement(i,pX,
2571 Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
2572 sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
2573 n = sqlite3_value_bytes(pVal);
2574 Tcl_ListObjAppendElement(i,pX,
2575 Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
2576 sqlite3ValueFree(pVal);
2577 }
2578 sqlite3EndBenignMalloc();
danielk19774e6af132004-06-10 14:01:08 +00002579
2580 Tcl_EvalObjEx(i, pX, 0);
2581 Tcl_DecrRefCount(pX);
2582 Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
2583 return res;
2584}
2585static int test_collate(
2586 void * clientData,
2587 Tcl_Interp *interp,
2588 int objc,
2589 Tcl_Obj *CONST objv[]
2590){
2591 sqlite3 *db;
2592 int val;
danielk1977312d6b32004-06-29 13:18:23 +00002593 sqlite3_value *pVal;
drhc60d0442004-09-30 13:43:13 +00002594 int rc;
danielk19774e6af132004-06-10 14:01:08 +00002595
2596 if( objc!=5 ) goto bad_args;
2597 pTestCollateInterp = interp;
2598 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2599
2600 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +00002601 rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
2602 (void *)SQLITE_UTF8, val?test_collate_func:0);
2603 if( rc==SQLITE_OK ){
drheee4c8c2008-02-18 22:24:57 +00002604 const void *zUtf16;
drhc60d0442004-09-30 13:43:13 +00002605 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
2606 rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
2607 (void *)SQLITE_UTF16LE, val?test_collate_func:0);
2608 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
danielk1977312d6b32004-06-29 13:18:23 +00002609
drh86f8c192007-08-22 00:39:19 +00002610#if 0
danielk19779a30cf62006-01-18 04:26:07 +00002611 if( sqlite3_iMallocFail>0 ){
2612 sqlite3_iMallocFail++;
2613 }
2614#endif
drhf3a65f72007-08-22 20:18:21 +00002615 sqlite3_mutex_enter(db->mutex);
2616 pVal = sqlite3ValueNew(db);
drhb21c8cd2007-08-21 19:33:56 +00002617 sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
danielk1977a7a8e142008-02-13 18:25:27 +00002618 zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
drhf3a65f72007-08-22 20:18:21 +00002619 if( db->mallocFailed ){
2620 rc = SQLITE_NOMEM;
2621 }else{
danielk1977a7a8e142008-02-13 18:25:27 +00002622 rc = sqlite3_create_collation16(db, zUtf16, SQLITE_UTF16BE,
danielk19779a30cf62006-01-18 04:26:07 +00002623 (void *)SQLITE_UTF16BE, val?test_collate_func:0);
drhf3a65f72007-08-22 20:18:21 +00002624 }
drhc60d0442004-09-30 13:43:13 +00002625 sqlite3ValueFree(pVal);
drhf3a65f72007-08-22 20:18:21 +00002626 sqlite3_mutex_leave(db->mutex);
drhc60d0442004-09-30 13:43:13 +00002627 }
2628 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk19779a30cf62006-01-18 04:26:07 +00002629
2630 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +00002631 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
danielk19779a30cf62006-01-18 04:26:07 +00002632 return TCL_ERROR;
2633 }
danielk19774e6af132004-06-10 14:01:08 +00002634 return TCL_OK;
2635
2636bad_args:
2637 Tcl_AppendResult(interp, "wrong # args: should be \"",
2638 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
2639 return TCL_ERROR;
2640}
2641
drh268803a2005-12-14 20:11:30 +00002642/*
dan38fdead2014-04-01 10:19:02 +00002643** Usage: add_test_utf16bin_collate <db ptr>
2644**
2645** Add a utf-16 collation sequence named "utf16bin" to the database
2646** handle. This collation sequence compares arguments in the same way as the
2647** built-in collation "binary".
2648*/
2649static int test_utf16bin_collate_func(
2650 void *pCtx,
2651 int nA, const void *zA,
2652 int nB, const void *zB
2653){
2654 int nCmp = (nA>nB ? nB : nA);
2655 int res = memcmp(zA, zB, nCmp);
2656 if( res==0 ) res = nA - nB;
2657 return res;
2658}
2659static int test_utf16bin_collate(
2660 void * clientData,
2661 Tcl_Interp *interp,
2662 int objc,
2663 Tcl_Obj *CONST objv[]
2664){
2665 sqlite3 *db;
2666 int rc;
2667
2668 if( objc!=2 ) goto bad_args;
2669 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2670
2671 rc = sqlite3_create_collation(db, "utf16bin", SQLITE_UTF16, 0,
2672 test_utf16bin_collate_func
2673 );
2674 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
2675 return TCL_OK;
2676
2677bad_args:
2678 Tcl_WrongNumArgs(interp, 1, objv, "DB");
2679 return TCL_ERROR;
2680}
2681
2682/*
drh268803a2005-12-14 20:11:30 +00002683** When the collation needed callback is invoked, record the name of
2684** the requested collating function here. The recorded name is linked
2685** to a TCL variable and used to make sure that the requested collation
2686** name is correct.
2687*/
2688static char zNeededCollation[200];
2689static char *pzNeededCollation = zNeededCollation;
2690
2691
2692/*
2693** Called when a collating sequence is needed. Registered using
2694** sqlite3_collation_needed16().
2695*/
danielk1977312d6b32004-06-29 13:18:23 +00002696static void test_collate_needed_cb(
2697 void *pCtx,
2698 sqlite3 *db,
2699 int eTextRep,
drh268803a2005-12-14 20:11:30 +00002700 const void *pName
danielk1977312d6b32004-06-29 13:18:23 +00002701){
danielk197714db2662006-01-09 16:12:04 +00002702 int enc = ENC(db);
drh268803a2005-12-14 20:11:30 +00002703 int i;
2704 char *z;
2705 for(z = (char*)pName, i=0; *z || z[1]; z++){
2706 if( *z ) zNeededCollation[i++] = *z;
2707 }
2708 zNeededCollation[i] = 0;
danielk1977312d6b32004-06-29 13:18:23 +00002709 sqlite3_create_collation(
dand2199f02010-08-27 17:48:52 +00002710 db, "test_collate", ENC(db), SQLITE_INT_TO_PTR(enc), test_collate_func);
danielk1977312d6b32004-06-29 13:18:23 +00002711}
2712
2713/*
2714** Usage: add_test_collate_needed DB
2715*/
2716static int test_collate_needed(
2717 void * clientData,
2718 Tcl_Interp *interp,
2719 int objc,
2720 Tcl_Obj *CONST objv[]
2721){
2722 sqlite3 *db;
drhc60d0442004-09-30 13:43:13 +00002723 int rc;
danielk1977312d6b32004-06-29 13:18:23 +00002724
2725 if( objc!=2 ) goto bad_args;
2726 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +00002727 rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
drh268803a2005-12-14 20:11:30 +00002728 zNeededCollation[0] = 0;
drhc60d0442004-09-30 13:43:13 +00002729 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk1977312d6b32004-06-29 13:18:23 +00002730 return TCL_OK;
2731
2732bad_args:
2733 Tcl_WrongNumArgs(interp, 1, objv, "DB");
2734 return TCL_ERROR;
2735}
drh7d9bd4e2006-02-16 18:16:36 +00002736
2737/*
2738** tclcmd: add_alignment_test_collations DB
2739**
2740** Add two new collating sequences to the database DB
2741**
2742** utf16_aligned
2743** utf16_unaligned
2744**
2745** Both collating sequences use the same sort order as BINARY.
2746** The only difference is that the utf16_aligned collating
2747** sequence is declared with the SQLITE_UTF16_ALIGNED flag.
2748** Both collating functions increment the unaligned utf16 counter
2749** whenever they see a string that begins on an odd byte boundary.
2750*/
2751static int unaligned_string_counter = 0;
2752static int alignmentCollFunc(
2753 void *NotUsed,
2754 int nKey1, const void *pKey1,
2755 int nKey2, const void *pKey2
2756){
2757 int rc, n;
2758 n = nKey1<nKey2 ? nKey1 : nKey2;
dand2199f02010-08-27 17:48:52 +00002759 if( nKey1>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey1))) ) unaligned_string_counter++;
2760 if( nKey2>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey2))) ) unaligned_string_counter++;
drh7d9bd4e2006-02-16 18:16:36 +00002761 rc = memcmp(pKey1, pKey2, n);
2762 if( rc==0 ){
2763 rc = nKey1 - nKey2;
2764 }
2765 return rc;
2766}
2767static int add_alignment_test_collations(
2768 void * clientData,
2769 Tcl_Interp *interp,
2770 int objc,
2771 Tcl_Obj *CONST objv[]
2772){
2773 sqlite3 *db;
2774 if( objc>=2 ){
2775 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
danielk1977ebb32932009-04-28 15:35:38 +00002776 sqlite3_create_collation(db, "utf16_unaligned", SQLITE_UTF16,
drh7d9bd4e2006-02-16 18:16:36 +00002777 0, alignmentCollFunc);
danielk1977ebb32932009-04-28 15:35:38 +00002778 sqlite3_create_collation(db, "utf16_aligned", SQLITE_UTF16_ALIGNED,
drh7d9bd4e2006-02-16 18:16:36 +00002779 0, alignmentCollFunc);
2780 }
2781 return SQLITE_OK;
2782}
2783#endif /* !defined(SQLITE_OMIT_UTF16) */
danielk1977312d6b32004-06-29 13:18:23 +00002784
danielk1977c8e9a2d2004-06-25 12:08:46 +00002785/*
2786** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
2787**
2788** This function is used to test that SQLite selects the correct user
2789** function callback when multiple versions (for different text encodings)
2790** are available.
2791**
2792** Calling this routine registers up to three versions of the user function
2793** "test_function" with database handle <db>. If the second argument is
2794** true, then a version of test_function is registered for UTF-8, if the
2795** third is true, a version is registered for UTF-16le, if the fourth is
2796** true, a UTF-16be version is available. Previous versions of
2797** test_function are deleted.
2798**
2799** The user function is implemented by calling the following TCL script:
2800**
2801** "test_function <enc> <arg>"
2802**
2803** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
2804** single argument passed to the SQL function. The value returned by
2805** the TCL script is used as the return value of the SQL function. It
2806** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
2807** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
2808** prefers UTF-16BE.
2809*/
drh5436dc22004-11-14 04:04:17 +00002810#ifndef SQLITE_OMIT_UTF16
danielk1977c8e9a2d2004-06-25 12:08:46 +00002811static void test_function_utf8(
2812 sqlite3_context *pCtx,
2813 int nArg,
2814 sqlite3_value **argv
2815){
2816 Tcl_Interp *interp;
2817 Tcl_Obj *pX;
2818 sqlite3_value *pVal;
2819 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
2820 pX = Tcl_NewStringObj("test_function", -1);
2821 Tcl_IncrRefCount(pX);
2822 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
2823 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00002824 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00002825 Tcl_EvalObjEx(interp, pX, 0);
2826 Tcl_DecrRefCount(pX);
2827 sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
danielk19771e536952007-08-16 10:09:01 +00002828 pVal = sqlite3ValueNew(0);
drhb21c8cd2007-08-21 19:33:56 +00002829 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
danielk1977c8e9a2d2004-06-25 12:08:46 +00002830 SQLITE_UTF8, SQLITE_STATIC);
2831 sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
2832 -1, SQLITE_TRANSIENT);
2833 sqlite3ValueFree(pVal);
2834}
2835static void test_function_utf16le(
2836 sqlite3_context *pCtx,
2837 int nArg,
2838 sqlite3_value **argv
2839){
2840 Tcl_Interp *interp;
2841 Tcl_Obj *pX;
2842 sqlite3_value *pVal;
2843 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
2844 pX = Tcl_NewStringObj("test_function", -1);
2845 Tcl_IncrRefCount(pX);
2846 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
2847 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00002848 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00002849 Tcl_EvalObjEx(interp, pX, 0);
2850 Tcl_DecrRefCount(pX);
danielk19771e536952007-08-16 10:09:01 +00002851 pVal = sqlite3ValueNew(0);
drhb21c8cd2007-08-21 19:33:56 +00002852 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
danielk1977c8e9a2d2004-06-25 12:08:46 +00002853 SQLITE_UTF8, SQLITE_STATIC);
drh03d847e2005-12-09 20:21:58 +00002854 sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
danielk1977c8e9a2d2004-06-25 12:08:46 +00002855 sqlite3ValueFree(pVal);
2856}
2857static void test_function_utf16be(
2858 sqlite3_context *pCtx,
2859 int nArg,
2860 sqlite3_value **argv
2861){
2862 Tcl_Interp *interp;
2863 Tcl_Obj *pX;
2864 sqlite3_value *pVal;
2865 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
2866 pX = Tcl_NewStringObj("test_function", -1);
2867 Tcl_IncrRefCount(pX);
2868 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
2869 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00002870 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00002871 Tcl_EvalObjEx(interp, pX, 0);
2872 Tcl_DecrRefCount(pX);
danielk19771e536952007-08-16 10:09:01 +00002873 pVal = sqlite3ValueNew(0);
drhb21c8cd2007-08-21 19:33:56 +00002874 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
danielk1977c8e9a2d2004-06-25 12:08:46 +00002875 SQLITE_UTF8, SQLITE_STATIC);
drhde4fcfd2008-01-19 23:50:26 +00002876 sqlite3_result_text16(pCtx, sqlite3_value_text16le(pVal),
2877 -1, SQLITE_TRANSIENT);
2878 sqlite3_result_text16be(pCtx, sqlite3_value_text16le(pVal),
2879 -1, SQLITE_TRANSIENT);
danielk1977c8e9a2d2004-06-25 12:08:46 +00002880 sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
2881 -1, SQLITE_TRANSIENT);
2882 sqlite3ValueFree(pVal);
2883}
drh5436dc22004-11-14 04:04:17 +00002884#endif /* SQLITE_OMIT_UTF16 */
danielk1977c8e9a2d2004-06-25 12:08:46 +00002885static int test_function(
2886 void * clientData,
2887 Tcl_Interp *interp,
2888 int objc,
2889 Tcl_Obj *CONST objv[]
2890){
drh5436dc22004-11-14 04:04:17 +00002891#ifndef SQLITE_OMIT_UTF16
danielk1977c8e9a2d2004-06-25 12:08:46 +00002892 sqlite3 *db;
2893 int val;
2894
2895 if( objc!=5 ) goto bad_args;
2896 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2897
2898 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
2899 if( val ){
2900 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
2901 interp, test_function_utf8, 0, 0);
2902 }
2903 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
2904 if( val ){
2905 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
2906 interp, test_function_utf16le, 0, 0);
2907 }
2908 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
2909 if( val ){
2910 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
2911 interp, test_function_utf16be, 0, 0);
2912 }
2913
2914 return TCL_OK;
2915bad_args:
2916 Tcl_AppendResult(interp, "wrong # args: should be \"",
2917 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
drh5436dc22004-11-14 04:04:17 +00002918#endif /* SQLITE_OMIT_UTF16 */
danielk1977c8e9a2d2004-06-25 12:08:46 +00002919 return TCL_ERROR;
2920}
2921
danielk1977312d6b32004-06-29 13:18:23 +00002922/*
danba3cbf32010-06-30 04:29:03 +00002923** Usage: sqlite3_test_errstr <err code>
danielk1977312d6b32004-06-29 13:18:23 +00002924**
2925** Test that the english language string equivalents for sqlite error codes
2926** are sane. The parameter is an integer representing an sqlite error code.
2927** The result is a list of two elements, the string representation of the
2928** error code and the english language explanation.
2929*/
2930static int test_errstr(
2931 void * clientData,
2932 Tcl_Interp *interp,
2933 int objc,
2934 Tcl_Obj *CONST objv[]
2935){
2936 char *zCode;
2937 int i;
2938 if( objc!=1 ){
2939 Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
2940 }
2941
2942 zCode = Tcl_GetString(objv[1]);
2943 for(i=0; i<200; i++){
drh4f0c5872007-03-26 22:05:01 +00002944 if( 0==strcmp(t1ErrorName(i), zCode) ) break;
danielk1977312d6b32004-06-29 13:18:23 +00002945 }
2946 Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
2947 return TCL_OK;
2948}
2949
drh50457892003-09-06 01:10:47 +00002950/*
drh99ee3602003-02-16 19:13:36 +00002951** Usage: breakpoint
2952**
2953** This routine exists for one purpose - to provide a place to put a
2954** breakpoint with GDB that can be triggered using TCL code. The use
2955** for this is when a particular test fails on (say) the 1485th iteration.
2956** In the TCL test script, we can add code like this:
2957**
2958** if {$i==1485} breakpoint
2959**
2960** Then run testfixture in the debugger and wait for the breakpoint to
2961** fire. Then additional breakpoints can be set to trace down the bug.
2962*/
2963static int test_breakpoint(
2964 void *NotUsed,
2965 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
2966 int argc, /* Number of arguments */
2967 char **argv /* Text of each argument */
2968){
2969 return TCL_OK; /* Do nothing */
2970}
2971
drh241db312004-06-22 12:46:53 +00002972/*
drhb026e052007-05-02 01:34:31 +00002973** Usage: sqlite3_bind_zeroblob STMT IDX N
2974**
2975** Test the sqlite3_bind_zeroblob interface. STMT is a prepared statement.
2976** IDX is the index of a wildcard in the prepared statement. This command
2977** binds a N-byte zero-filled BLOB to the wildcard.
2978*/
2979static int test_bind_zeroblob(
2980 void * clientData,
2981 Tcl_Interp *interp,
2982 int objc,
2983 Tcl_Obj *CONST objv[]
2984){
2985 sqlite3_stmt *pStmt;
2986 int idx;
2987 int n;
2988 int rc;
2989
2990 if( objc!=4 ){
danielk197728c66302007-09-01 11:04:26 +00002991 Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N");
drhb026e052007-05-02 01:34:31 +00002992 return TCL_ERROR;
2993 }
2994
2995 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2996 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
2997 if( Tcl_GetIntFromObj(interp, objv[3], &n) ) return TCL_ERROR;
2998
2999 rc = sqlite3_bind_zeroblob(pStmt, idx, n);
3000 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3001 if( rc!=SQLITE_OK ){
3002 return TCL_ERROR;
3003 }
3004
3005 return TCL_OK;
3006}
3007
3008/*
drh241db312004-06-22 12:46:53 +00003009** Usage: sqlite3_bind_int STMT N VALUE
3010**
3011** Test the sqlite3_bind_int interface. STMT is a prepared statement.
3012** N is the index of a wildcard in the prepared statement. This command
3013** binds a 32-bit integer VALUE to that wildcard.
3014*/
3015static int test_bind_int(
danielk197751e3d8e2004-05-20 01:12:34 +00003016 void * clientData,
3017 Tcl_Interp *interp,
3018 int objc,
3019 Tcl_Obj *CONST objv[]
3020){
3021 sqlite3_stmt *pStmt;
3022 int idx;
3023 int value;
3024 int rc;
3025
3026 if( objc!=4 ){
3027 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00003028 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003029 return TCL_ERROR;
3030 }
3031
3032 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3033 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3034 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
3035
danielk1977c572ef72004-05-27 09:28:41 +00003036 rc = sqlite3_bind_int(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00003037 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003038 if( rc!=SQLITE_OK ){
3039 return TCL_ERROR;
3040 }
3041
3042 return TCL_OK;
3043}
3044
drh241db312004-06-22 12:46:53 +00003045
3046/*
3047** Usage: sqlite3_bind_int64 STMT N VALUE
3048**
3049** Test the sqlite3_bind_int64 interface. STMT is a prepared statement.
3050** N is the index of a wildcard in the prepared statement. This command
3051** binds a 64-bit integer VALUE to that wildcard.
3052*/
danielk197751e3d8e2004-05-20 01:12:34 +00003053static int test_bind_int64(
3054 void * clientData,
3055 Tcl_Interp *interp,
3056 int objc,
3057 Tcl_Obj *CONST objv[]
3058){
3059 sqlite3_stmt *pStmt;
3060 int idx;
drhb3f787f2012-09-29 14:45:54 +00003061 Tcl_WideInt value;
danielk197751e3d8e2004-05-20 01:12:34 +00003062 int rc;
3063
3064 if( objc!=4 ){
3065 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00003066 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003067 return TCL_ERROR;
3068 }
3069
3070 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3071 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3072 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
3073
3074 rc = sqlite3_bind_int64(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00003075 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003076 if( rc!=SQLITE_OK ){
3077 return TCL_ERROR;
3078 }
3079
3080 return TCL_OK;
3081}
3082
drh241db312004-06-22 12:46:53 +00003083
3084/*
3085** Usage: sqlite3_bind_double STMT N VALUE
3086**
3087** Test the sqlite3_bind_double interface. STMT is a prepared statement.
3088** N is the index of a wildcard in the prepared statement. This command
3089** binds a 64-bit integer VALUE to that wildcard.
3090*/
danielk197751e3d8e2004-05-20 01:12:34 +00003091static int test_bind_double(
3092 void * clientData,
3093 Tcl_Interp *interp,
3094 int objc,
3095 Tcl_Obj *CONST objv[]
3096){
3097 sqlite3_stmt *pStmt;
3098 int idx;
mistachkin27b2f052015-01-12 19:49:46 +00003099 double value = 0;
danielk197751e3d8e2004-05-20 01:12:34 +00003100 int rc;
drha06f17f2008-05-11 11:07:06 +00003101 const char *zVal;
3102 int i;
3103 static const struct {
3104 const char *zName; /* Name of the special floating point value */
3105 unsigned int iUpper; /* Upper 32 bits */
3106 unsigned int iLower; /* Lower 32 bits */
3107 } aSpecialFp[] = {
3108 { "NaN", 0x7fffffff, 0xffffffff },
3109 { "SNaN", 0x7ff7ffff, 0xffffffff },
3110 { "-NaN", 0xffffffff, 0xffffffff },
3111 { "-SNaN", 0xfff7ffff, 0xffffffff },
3112 { "+Inf", 0x7ff00000, 0x00000000 },
3113 { "-Inf", 0xfff00000, 0x00000000 },
3114 { "Epsilon", 0x00000000, 0x00000001 },
3115 { "-Epsilon", 0x80000000, 0x00000001 },
3116 { "NaN0", 0x7ff80000, 0x00000000 },
3117 { "-NaN0", 0xfff80000, 0x00000000 },
3118 };
danielk197751e3d8e2004-05-20 01:12:34 +00003119
3120 if( objc!=4 ){
3121 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00003122 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003123 return TCL_ERROR;
3124 }
3125
3126 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3127 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003128
drh394f07e2008-04-28 15:23:02 +00003129 /* Intercept the string "NaN" and generate a NaN value for it.
3130 ** All other strings are passed through to Tcl_GetDoubleFromObj().
3131 ** Tcl_GetDoubleFromObj() should understand "NaN" but some versions
3132 ** contain a bug.
3133 */
drha06f17f2008-05-11 11:07:06 +00003134 zVal = Tcl_GetString(objv[3]);
3135 for(i=0; i<sizeof(aSpecialFp)/sizeof(aSpecialFp[0]); i++){
3136 if( strcmp(aSpecialFp[i].zName, zVal)==0 ){
3137 sqlite3_uint64 x;
3138 x = aSpecialFp[i].iUpper;
3139 x <<= 32;
3140 x |= aSpecialFp[i].iLower;
drh0a667332008-05-11 17:22:01 +00003141 assert( sizeof(value)==8 );
3142 assert( sizeof(x)==8 );
3143 memcpy(&value, &x, 8);
drha06f17f2008-05-11 11:07:06 +00003144 break;
3145 }
3146 }
3147 if( i>=sizeof(aSpecialFp)/sizeof(aSpecialFp[0]) &&
3148 Tcl_GetDoubleFromObj(interp, objv[3], &value) ){
drh394f07e2008-04-28 15:23:02 +00003149 return TCL_ERROR;
3150 }
danielk197751e3d8e2004-05-20 01:12:34 +00003151 rc = sqlite3_bind_double(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00003152 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003153 if( rc!=SQLITE_OK ){
3154 return TCL_ERROR;
3155 }
3156
3157 return TCL_OK;
3158}
3159
drh241db312004-06-22 12:46:53 +00003160/*
3161** Usage: sqlite3_bind_null STMT N
3162**
3163** Test the sqlite3_bind_null interface. STMT is a prepared statement.
3164** N is the index of a wildcard in the prepared statement. This command
3165** binds a NULL to the wildcard.
3166*/
danielk197751e3d8e2004-05-20 01:12:34 +00003167static int test_bind_null(
3168 void * clientData,
3169 Tcl_Interp *interp,
3170 int objc,
3171 Tcl_Obj *CONST objv[]
3172){
3173 sqlite3_stmt *pStmt;
3174 int idx;
3175 int rc;
3176
3177 if( objc!=3 ){
3178 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00003179 Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003180 return TCL_ERROR;
3181 }
3182
3183 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3184 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3185
3186 rc = sqlite3_bind_null(pStmt, idx);
drhc60d0442004-09-30 13:43:13 +00003187 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003188 if( rc!=SQLITE_OK ){
3189 return TCL_ERROR;
3190 }
3191
3192 return TCL_OK;
3193}
3194
drh241db312004-06-22 12:46:53 +00003195/*
3196** Usage: sqlite3_bind_text STMT N STRING BYTES
3197**
3198** Test the sqlite3_bind_text interface. STMT is a prepared statement.
3199** N is the index of a wildcard in the prepared statement. This command
3200** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes
3201** long.
3202*/
danielk197751e3d8e2004-05-20 01:12:34 +00003203static int test_bind_text(
3204 void * clientData,
3205 Tcl_Interp *interp,
3206 int objc,
3207 Tcl_Obj *CONST objv[]
3208){
3209 sqlite3_stmt *pStmt;
3210 int idx;
3211 int bytes;
3212 char *value;
3213 int rc;
3214
3215 if( objc!=5 ){
3216 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00003217 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003218 return TCL_ERROR;
3219 }
3220
3221 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3222 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
drh10dfbbb2008-04-16 12:58:53 +00003223 value = (char*)Tcl_GetByteArrayFromObj(objv[3], &bytes);
danielk197751e3d8e2004-05-20 01:12:34 +00003224 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
3225
danielk1977d8123362004-06-12 09:25:12 +00003226 rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
drhc60d0442004-09-30 13:43:13 +00003227 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003228 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +00003229 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003230 return TCL_ERROR;
3231 }
3232
3233 return TCL_OK;
3234}
3235
drh241db312004-06-22 12:46:53 +00003236/*
danielk1977161fb792006-01-24 10:58:21 +00003237** Usage: sqlite3_bind_text16 ?-static? STMT N STRING BYTES
drh241db312004-06-22 12:46:53 +00003238**
3239** Test the sqlite3_bind_text16 interface. STMT is a prepared statement.
3240** N is the index of a wildcard in the prepared statement. This command
3241** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes
3242** long.
3243*/
danielk197751e3d8e2004-05-20 01:12:34 +00003244static int test_bind_text16(
3245 void * clientData,
3246 Tcl_Interp *interp,
3247 int objc,
3248 Tcl_Obj *CONST objv[]
3249){
drh5436dc22004-11-14 04:04:17 +00003250#ifndef SQLITE_OMIT_UTF16
danielk197751e3d8e2004-05-20 01:12:34 +00003251 sqlite3_stmt *pStmt;
3252 int idx;
3253 int bytes;
3254 char *value;
3255 int rc;
3256
drh7da5fcb2012-03-30 14:59:43 +00003257 void (*xDel)(void*) = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
danielk1977161fb792006-01-24 10:58:21 +00003258 Tcl_Obj *oStmt = objv[objc-4];
3259 Tcl_Obj *oN = objv[objc-3];
3260 Tcl_Obj *oString = objv[objc-2];
3261 Tcl_Obj *oBytes = objv[objc-1];
3262
3263 if( objc!=5 && objc!=6){
danielk197751e3d8e2004-05-20 01:12:34 +00003264 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00003265 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003266 return TCL_ERROR;
3267 }
3268
danielk1977161fb792006-01-24 10:58:21 +00003269 if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR;
3270 if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR;
3271 value = (char*)Tcl_GetByteArrayFromObj(oString, 0);
3272 if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003273
danielk1977161fb792006-01-24 10:58:21 +00003274 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel);
drhc60d0442004-09-30 13:43:13 +00003275 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003276 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +00003277 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003278 return TCL_ERROR;
3279 }
3280
drh5436dc22004-11-14 04:04:17 +00003281#endif /* SQLITE_OMIT_UTF16 */
danielk197751e3d8e2004-05-20 01:12:34 +00003282 return TCL_OK;
3283}
3284
drh241db312004-06-22 12:46:53 +00003285/*
danielk19775b159dc2007-05-17 16:34:43 +00003286** Usage: sqlite3_bind_blob ?-static? STMT N DATA BYTES
drh241db312004-06-22 12:46:53 +00003287**
3288** Test the sqlite3_bind_blob interface. STMT is a prepared statement.
3289** N is the index of a wildcard in the prepared statement. This command
3290** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size.
3291*/
danielk197751e3d8e2004-05-20 01:12:34 +00003292static int test_bind_blob(
3293 void * clientData,
3294 Tcl_Interp *interp,
3295 int objc,
3296 Tcl_Obj *CONST objv[]
3297){
3298 sqlite3_stmt *pStmt;
3299 int idx;
3300 int bytes;
3301 char *value;
3302 int rc;
danielk19775b159dc2007-05-17 16:34:43 +00003303 sqlite3_destructor_type xDestructor = SQLITE_TRANSIENT;
danielk197751e3d8e2004-05-20 01:12:34 +00003304
danielk19775b159dc2007-05-17 16:34:43 +00003305 if( objc!=5 && objc!=6 ){
danielk197751e3d8e2004-05-20 01:12:34 +00003306 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00003307 Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003308 return TCL_ERROR;
3309 }
3310
danielk19775b159dc2007-05-17 16:34:43 +00003311 if( objc==6 ){
3312 xDestructor = SQLITE_STATIC;
3313 objv++;
3314 }
3315
danielk197751e3d8e2004-05-20 01:12:34 +00003316 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3317 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3318 value = Tcl_GetString(objv[3]);
danielk197749e46432004-05-27 13:55:27 +00003319 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003320
danielk19775b159dc2007-05-17 16:34:43 +00003321 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, xDestructor);
drhc60d0442004-09-30 13:43:13 +00003322 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003323 if( rc!=SQLITE_OK ){
3324 return TCL_ERROR;
3325 }
3326
3327 return TCL_OK;
3328}
3329
drh99ee3602003-02-16 19:13:36 +00003330/*
drh75f6a032004-07-15 14:15:00 +00003331** Usage: sqlite3_bind_parameter_count STMT
3332**
3333** Return the number of wildcards in the given statement.
3334*/
3335static int test_bind_parameter_count(
3336 void * clientData,
3337 Tcl_Interp *interp,
3338 int objc,
3339 Tcl_Obj *CONST objv[]
3340){
3341 sqlite3_stmt *pStmt;
3342
3343 if( objc!=2 ){
3344 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
3345 return TCL_ERROR;
3346 }
3347 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3348 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
3349 return TCL_OK;
3350}
3351
3352/*
drh895d7472004-08-20 16:02:39 +00003353** Usage: sqlite3_bind_parameter_name STMT N
3354**
3355** Return the name of the Nth wildcard. The first wildcard is 1.
3356** An empty string is returned if N is out of range or if the wildcard
3357** is nameless.
3358*/
3359static int test_bind_parameter_name(
3360 void * clientData,
3361 Tcl_Interp *interp,
3362 int objc,
3363 Tcl_Obj *CONST objv[]
3364){
3365 sqlite3_stmt *pStmt;
3366 int i;
3367
3368 if( objc!=3 ){
3369 Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
3370 return TCL_ERROR;
3371 }
3372 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3373 if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
3374 Tcl_SetObjResult(interp,
3375 Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
3376 );
3377 return TCL_OK;
3378}
3379
3380/*
drhfa6bc002004-09-07 16:19:52 +00003381** Usage: sqlite3_bind_parameter_index STMT NAME
3382**
3383** Return the index of the wildcard called NAME. Return 0 if there is
3384** no such wildcard.
3385*/
3386static int test_bind_parameter_index(
3387 void * clientData,
3388 Tcl_Interp *interp,
3389 int objc,
3390 Tcl_Obj *CONST objv[]
3391){
3392 sqlite3_stmt *pStmt;
3393
3394 if( objc!=3 ){
3395 Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
3396 return TCL_ERROR;
3397 }
3398 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3399 Tcl_SetObjResult(interp,
3400 Tcl_NewIntObj(
3401 sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
3402 )
3403 );
3404 return TCL_OK;
3405}
3406
3407/*
danielk1977600dd0b2005-01-20 01:14:23 +00003408** Usage: sqlite3_clear_bindings STMT
3409**
3410*/
danielk1977600dd0b2005-01-20 01:14:23 +00003411static int test_clear_bindings(
3412 void * clientData,
3413 Tcl_Interp *interp,
3414 int objc,
3415 Tcl_Obj *CONST objv[]
3416){
3417 sqlite3_stmt *pStmt;
3418
3419 if( objc!=2 ){
3420 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
3421 return TCL_ERROR;
3422 }
3423 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3424 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
3425 return TCL_OK;
3426}
drhf9cb7f52006-06-27 20:06:44 +00003427
3428/*
3429** Usage: sqlite3_sleep MILLISECONDS
3430*/
3431static int test_sleep(
3432 void * clientData,
3433 Tcl_Interp *interp,
3434 int objc,
3435 Tcl_Obj *CONST objv[]
3436){
3437 int ms;
3438
3439 if( objc!=2 ){
3440 Tcl_WrongNumArgs(interp, 1, objv, "MILLISECONDS");
3441 return TCL_ERROR;
3442 }
3443 if( Tcl_GetIntFromObj(interp, objv[1], &ms) ){
3444 return TCL_ERROR;
3445 }
3446 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(ms)));
3447 return TCL_OK;
3448}
danielk1977600dd0b2005-01-20 01:14:23 +00003449
3450/*
drh99dfe5e2008-10-30 15:03:15 +00003451** Usage: sqlite3_extended_errcode DB
3452**
3453** Return the string representation of the most recent sqlite3_* API
3454** error code. e.g. "SQLITE_ERROR".
3455*/
3456static int test_ex_errcode(
3457 void * clientData,
3458 Tcl_Interp *interp,
3459 int objc,
3460 Tcl_Obj *CONST objv[]
3461){
3462 sqlite3 *db;
3463 int rc;
3464
3465 if( objc!=2 ){
3466 Tcl_AppendResult(interp, "wrong # args: should be \"",
3467 Tcl_GetString(objv[0]), " DB", 0);
3468 return TCL_ERROR;
3469 }
3470 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3471 rc = sqlite3_extended_errcode(db);
3472 Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0);
3473 return TCL_OK;
3474}
3475
3476
3477/*
danielk19776622cce2004-05-20 11:00:52 +00003478** Usage: sqlite3_errcode DB
3479**
3480** Return the string representation of the most recent sqlite3_* API
3481** error code. e.g. "SQLITE_ERROR".
3482*/
3483static int test_errcode(
3484 void * clientData,
3485 Tcl_Interp *interp,
3486 int objc,
3487 Tcl_Obj *CONST objv[]
3488){
3489 sqlite3 *db;
drh4ac285a2006-09-15 07:28:50 +00003490 int rc;
danielk19776622cce2004-05-20 11:00:52 +00003491
3492 if( objc!=2 ){
3493 Tcl_AppendResult(interp, "wrong # args: should be \"",
3494 Tcl_GetString(objv[0]), " DB", 0);
3495 return TCL_ERROR;
3496 }
3497 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
drh4ac285a2006-09-15 07:28:50 +00003498 rc = sqlite3_errcode(db);
drh99dfe5e2008-10-30 15:03:15 +00003499 Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0);
danielk19776622cce2004-05-20 11:00:52 +00003500 return TCL_OK;
3501}
3502
3503/*
danielk197704103022009-02-03 16:51:24 +00003504** Usage: sqlite3_errmsg DB
danielk19776622cce2004-05-20 11:00:52 +00003505**
3506** Returns the UTF-8 representation of the error message string for the
3507** most recent sqlite3_* API call.
3508*/
3509static int test_errmsg(
3510 void * clientData,
3511 Tcl_Interp *interp,
3512 int objc,
3513 Tcl_Obj *CONST objv[]
3514){
drh9bb575f2004-09-06 17:24:11 +00003515 sqlite3 *db;
danielk19776622cce2004-05-20 11:00:52 +00003516 const char *zErr;
3517
3518 if( objc!=2 ){
3519 Tcl_AppendResult(interp, "wrong # args: should be \"",
3520 Tcl_GetString(objv[0]), " DB", 0);
3521 return TCL_ERROR;
3522 }
3523 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3524
3525 zErr = sqlite3_errmsg(db);
3526 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
3527 return TCL_OK;
3528}
3529
3530/*
3531** Usage: test_errmsg16 DB
3532**
3533** Returns the UTF-16 representation of the error message string for the
3534** most recent sqlite3_* API call. This is a byte array object at the TCL
3535** level, and it includes the 0x00 0x00 terminator bytes at the end of the
3536** UTF-16 string.
3537*/
3538static int test_errmsg16(
3539 void * clientData,
3540 Tcl_Interp *interp,
3541 int objc,
3542 Tcl_Obj *CONST objv[]
3543){
drh5436dc22004-11-14 04:04:17 +00003544#ifndef SQLITE_OMIT_UTF16
drh9bb575f2004-09-06 17:24:11 +00003545 sqlite3 *db;
danielk19776622cce2004-05-20 11:00:52 +00003546 const void *zErr;
drhaed382f2009-04-01 18:40:32 +00003547 const char *z;
danielk1977950f0542006-01-18 05:51:57 +00003548 int bytes = 0;
danielk19776622cce2004-05-20 11:00:52 +00003549
3550 if( objc!=2 ){
3551 Tcl_AppendResult(interp, "wrong # args: should be \"",
3552 Tcl_GetString(objv[0]), " DB", 0);
3553 return TCL_ERROR;
3554 }
3555 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3556
3557 zErr = sqlite3_errmsg16(db);
danielk1977950f0542006-01-18 05:51:57 +00003558 if( zErr ){
drhaed382f2009-04-01 18:40:32 +00003559 z = zErr;
3560 for(bytes=0; z[bytes] || z[bytes+1]; bytes+=2){}
danielk1977950f0542006-01-18 05:51:57 +00003561 }
danielk19776622cce2004-05-20 11:00:52 +00003562 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
drh5436dc22004-11-14 04:04:17 +00003563#endif /* SQLITE_OMIT_UTF16 */
danielk19776622cce2004-05-20 11:00:52 +00003564 return TCL_OK;
3565}
3566
3567/*
drh1c767f02009-01-09 02:49:31 +00003568** Usage: sqlite3_prepare DB sql bytes ?tailvar?
danielk19776622cce2004-05-20 11:00:52 +00003569**
3570** Compile up to <bytes> bytes of the supplied SQL string <sql> using
3571** database handle <DB>. The parameter <tailval> is the name of a global
3572** variable that is set to the unused portion of <sql> (if any). A
3573** STMT handle is returned.
3574*/
3575static int test_prepare(
3576 void * clientData,
3577 Tcl_Interp *interp,
3578 int objc,
3579 Tcl_Obj *CONST objv[]
3580){
3581 sqlite3 *db;
3582 const char *zSql;
3583 int bytes;
3584 const char *zTail = 0;
3585 sqlite3_stmt *pStmt = 0;
3586 char zBuf[50];
danielk19774ad17132004-05-21 01:47:26 +00003587 int rc;
danielk19776622cce2004-05-20 11:00:52 +00003588
drh1c767f02009-01-09 02:49:31 +00003589 if( objc!=5 && objc!=4 ){
danielk19776622cce2004-05-20 11:00:52 +00003590 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh1c767f02009-01-09 02:49:31 +00003591 Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
danielk19776622cce2004-05-20 11:00:52 +00003592 return TCL_ERROR;
3593 }
3594 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3595 zSql = Tcl_GetString(objv[2]);
3596 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
3597
drh1c767f02009-01-09 02:49:31 +00003598 rc = sqlite3_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
dan937d0de2009-10-15 18:35:38 +00003599 Tcl_ResetResult(interp);
drhc60d0442004-09-30 13:43:13 +00003600 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drh1c767f02009-01-09 02:49:31 +00003601 if( zTail && objc>=5 ){
danielk19776622cce2004-05-20 11:00:52 +00003602 if( bytes>=0 ){
drh83cc1392012-04-19 18:04:28 +00003603 bytes = bytes - (int)(zTail-zSql);
danielk19776622cce2004-05-20 11:00:52 +00003604 }
drh7da5fcb2012-03-30 14:59:43 +00003605 if( (int)strlen(zTail)<bytes ){
drh83cc1392012-04-19 18:04:28 +00003606 bytes = (int)strlen(zTail);
danielk19773a2c8c82008-04-03 14:36:25 +00003607 }
danielk19776622cce2004-05-20 11:00:52 +00003608 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
3609 }
danielk19774ad17132004-05-21 01:47:26 +00003610 if( rc!=SQLITE_OK ){
3611 assert( pStmt==0 );
drh65545b52015-01-19 00:35:53 +00003612 sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
danielk19774ad17132004-05-21 01:47:26 +00003613 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
3614 return TCL_ERROR;
3615 }
danielk19776622cce2004-05-20 11:00:52 +00003616
danielk19774ad17132004-05-21 01:47:26 +00003617 if( pStmt ){
drh64b1bea2006-01-15 02:30:57 +00003618 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
danielk19774ad17132004-05-21 01:47:26 +00003619 Tcl_AppendResult(interp, zBuf, 0);
3620 }
danielk19776622cce2004-05-20 11:00:52 +00003621 return TCL_OK;
3622}
3623
3624/*
drh1c767f02009-01-09 02:49:31 +00003625** Usage: sqlite3_prepare_v2 DB sql bytes ?tailvar?
drhb900aaf2006-11-09 00:24:53 +00003626**
3627** Compile up to <bytes> bytes of the supplied SQL string <sql> using
3628** database handle <DB>. The parameter <tailval> is the name of a global
3629** variable that is set to the unused portion of <sql> (if any). A
3630** STMT handle is returned.
3631*/
3632static int test_prepare_v2(
3633 void * clientData,
3634 Tcl_Interp *interp,
3635 int objc,
3636 Tcl_Obj *CONST objv[]
3637){
3638 sqlite3 *db;
3639 const char *zSql;
dand89b8342014-11-27 11:36:36 +00003640 char *zCopy = 0; /* malloc() copy of zSql */
drhb900aaf2006-11-09 00:24:53 +00003641 int bytes;
3642 const char *zTail = 0;
3643 sqlite3_stmt *pStmt = 0;
3644 char zBuf[50];
3645 int rc;
3646
drh1c767f02009-01-09 02:49:31 +00003647 if( objc!=5 && objc!=4 ){
drhb900aaf2006-11-09 00:24:53 +00003648 Tcl_AppendResult(interp, "wrong # args: should be \"",
3649 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
3650 return TCL_ERROR;
3651 }
3652 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3653 zSql = Tcl_GetString(objv[2]);
3654 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
3655
dand89b8342014-11-27 11:36:36 +00003656 /* Instead of using zSql directly, make a copy into a buffer obtained
3657 ** directly from malloc(). The idea is to make it easier for valgrind
3658 ** to spot buffer overreads. */
3659 if( bytes>=0 ){
3660 zCopy = malloc(bytes);
3661 memcpy(zCopy, zSql, bytes);
3662 }else{
drh2c3abeb2014-12-05 00:32:09 +00003663 int n = (int)strlen(zSql) + 1;
dand89b8342014-11-27 11:36:36 +00003664 zCopy = malloc(n);
3665 memcpy(zCopy, zSql, n);
3666 }
3667 rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, objc>=5 ? &zTail : 0);
3668 free(zCopy);
3669 zTail = &zSql[(zTail - zCopy)];
3670
danielk19777e29e952007-04-19 11:09:01 +00003671 assert(rc==SQLITE_OK || pStmt==0);
dan937d0de2009-10-15 18:35:38 +00003672 Tcl_ResetResult(interp);
drhb900aaf2006-11-09 00:24:53 +00003673 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhe5d7bf12014-12-23 20:05:19 +00003674 if( rc==SQLITE_OK && zTail && objc>=5 ){
drhb900aaf2006-11-09 00:24:53 +00003675 if( bytes>=0 ){
drh83cc1392012-04-19 18:04:28 +00003676 bytes = bytes - (int)(zTail-zSql);
drhb900aaf2006-11-09 00:24:53 +00003677 }
3678 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
3679 }
3680 if( rc!=SQLITE_OK ){
3681 assert( pStmt==0 );
drh65545b52015-01-19 00:35:53 +00003682 sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
drhb900aaf2006-11-09 00:24:53 +00003683 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
3684 return TCL_ERROR;
3685 }
3686
3687 if( pStmt ){
3688 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
3689 Tcl_AppendResult(interp, zBuf, 0);
3690 }
3691 return TCL_OK;
3692}
3693
3694/*
drh4837f532008-05-23 14:49:49 +00003695** Usage: sqlite3_prepare_tkt3134 DB
3696**
3697** Generate a prepared statement for a zero-byte string as a test
peter.d.reid60ec9142014-09-06 16:39:46 +00003698** for ticket #3134. The string should be preceded by a zero byte.
drh4837f532008-05-23 14:49:49 +00003699*/
3700static int test_prepare_tkt3134(
3701 void * clientData,
3702 Tcl_Interp *interp,
3703 int objc,
3704 Tcl_Obj *CONST objv[]
3705){
3706 sqlite3 *db;
3707 static const char zSql[] = "\000SELECT 1";
3708 sqlite3_stmt *pStmt = 0;
3709 char zBuf[50];
3710 int rc;
3711
3712 if( objc!=2 ){
3713 Tcl_AppendResult(interp, "wrong # args: should be \"",
3714 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
3715 return TCL_ERROR;
3716 }
3717 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3718 rc = sqlite3_prepare_v2(db, &zSql[1], 0, &pStmt, 0);
3719 assert(rc==SQLITE_OK || pStmt==0);
3720 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
3721 if( rc!=SQLITE_OK ){
3722 assert( pStmt==0 );
drh65545b52015-01-19 00:35:53 +00003723 sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
drh4837f532008-05-23 14:49:49 +00003724 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
3725 return TCL_ERROR;
3726 }
3727
3728 if( pStmt ){
3729 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
3730 Tcl_AppendResult(interp, zBuf, 0);
3731 }
3732 return TCL_OK;
3733}
3734
3735/*
drhb900aaf2006-11-09 00:24:53 +00003736** Usage: sqlite3_prepare16 DB sql bytes tailvar
danielk19776622cce2004-05-20 11:00:52 +00003737**
3738** Compile up to <bytes> bytes of the supplied SQL string <sql> using
3739** database handle <DB>. The parameter <tailval> is the name of a global
3740** variable that is set to the unused portion of <sql> (if any). A
3741** STMT handle is returned.
3742*/
3743static int test_prepare16(
3744 void * clientData,
3745 Tcl_Interp *interp,
3746 int objc,
3747 Tcl_Obj *CONST objv[]
3748){
drh5436dc22004-11-14 04:04:17 +00003749#ifndef SQLITE_OMIT_UTF16
danielk19776622cce2004-05-20 11:00:52 +00003750 sqlite3 *db;
3751 const void *zSql;
3752 const void *zTail = 0;
3753 Tcl_Obj *pTail = 0;
3754 sqlite3_stmt *pStmt = 0;
drhc60d0442004-09-30 13:43:13 +00003755 char zBuf[50];
3756 int rc;
danielk19776622cce2004-05-20 11:00:52 +00003757 int bytes; /* The integer specified as arg 3 */
3758 int objlen; /* The byte-array length of arg 2 */
3759
drh1c767f02009-01-09 02:49:31 +00003760 if( objc!=5 && objc!=4 ){
danielk19776622cce2004-05-20 11:00:52 +00003761 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh1c767f02009-01-09 02:49:31 +00003762 Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
danielk19776622cce2004-05-20 11:00:52 +00003763 return TCL_ERROR;
3764 }
3765 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3766 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
3767 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
3768
drh1c767f02009-01-09 02:49:31 +00003769 rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
drhc60d0442004-09-30 13:43:13 +00003770 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
3771 if( rc ){
danielk19776622cce2004-05-20 11:00:52 +00003772 return TCL_ERROR;
3773 }
3774
drh1c767f02009-01-09 02:49:31 +00003775 if( objc>=5 ){
3776 if( zTail ){
drh83cc1392012-04-19 18:04:28 +00003777 objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql);
drh1c767f02009-01-09 02:49:31 +00003778 }else{
3779 objlen = 0;
3780 }
3781 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
3782 Tcl_IncrRefCount(pTail);
3783 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
3784 Tcl_DecrRefCount(pTail);
danielk19776622cce2004-05-20 11:00:52 +00003785 }
danielk19776622cce2004-05-20 11:00:52 +00003786
danielk19774ad17132004-05-21 01:47:26 +00003787 if( pStmt ){
drh64b1bea2006-01-15 02:30:57 +00003788 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
danielk19774ad17132004-05-21 01:47:26 +00003789 }
danielk19776622cce2004-05-20 11:00:52 +00003790 Tcl_AppendResult(interp, zBuf, 0);
drh5436dc22004-11-14 04:04:17 +00003791#endif /* SQLITE_OMIT_UTF16 */
danielk19776622cce2004-05-20 11:00:52 +00003792 return TCL_OK;
3793}
3794
danielk19774ad17132004-05-21 01:47:26 +00003795/*
drh1c767f02009-01-09 02:49:31 +00003796** Usage: sqlite3_prepare16_v2 DB sql bytes ?tailvar?
drhb900aaf2006-11-09 00:24:53 +00003797**
3798** Compile up to <bytes> bytes of the supplied SQL string <sql> using
3799** database handle <DB>. The parameter <tailval> is the name of a global
3800** variable that is set to the unused portion of <sql> (if any). A
3801** STMT handle is returned.
3802*/
3803static int test_prepare16_v2(
3804 void * clientData,
3805 Tcl_Interp *interp,
3806 int objc,
3807 Tcl_Obj *CONST objv[]
3808){
3809#ifndef SQLITE_OMIT_UTF16
3810 sqlite3 *db;
3811 const void *zSql;
3812 const void *zTail = 0;
3813 Tcl_Obj *pTail = 0;
3814 sqlite3_stmt *pStmt = 0;
3815 char zBuf[50];
3816 int rc;
3817 int bytes; /* The integer specified as arg 3 */
3818 int objlen; /* The byte-array length of arg 2 */
3819
drh1c767f02009-01-09 02:49:31 +00003820 if( objc!=5 && objc!=4 ){
drhb900aaf2006-11-09 00:24:53 +00003821 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh1c767f02009-01-09 02:49:31 +00003822 Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
drhb900aaf2006-11-09 00:24:53 +00003823 return TCL_ERROR;
3824 }
3825 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3826 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
3827 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
3828
drh1c767f02009-01-09 02:49:31 +00003829 rc = sqlite3_prepare16_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
drhb900aaf2006-11-09 00:24:53 +00003830 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
3831 if( rc ){
3832 return TCL_ERROR;
3833 }
3834
drh1c767f02009-01-09 02:49:31 +00003835 if( objc>=5 ){
3836 if( zTail ){
drh83cc1392012-04-19 18:04:28 +00003837 objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql);
drh1c767f02009-01-09 02:49:31 +00003838 }else{
3839 objlen = 0;
3840 }
3841 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
3842 Tcl_IncrRefCount(pTail);
3843 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
3844 Tcl_DecrRefCount(pTail);
drhb900aaf2006-11-09 00:24:53 +00003845 }
drhb900aaf2006-11-09 00:24:53 +00003846
3847 if( pStmt ){
3848 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
3849 }
3850 Tcl_AppendResult(interp, zBuf, 0);
3851#endif /* SQLITE_OMIT_UTF16 */
3852 return TCL_OK;
3853}
3854
3855/*
danielk19774ad17132004-05-21 01:47:26 +00003856** Usage: sqlite3_open filename ?options-list?
3857*/
3858static int test_open(
3859 void * clientData,
3860 Tcl_Interp *interp,
3861 int objc,
3862 Tcl_Obj *CONST objv[]
3863){
3864 const char *zFilename;
3865 sqlite3 *db;
danielk19774ad17132004-05-21 01:47:26 +00003866 char zBuf[100];
3867
drhafc91042008-02-21 02:09:45 +00003868 if( objc!=3 && objc!=2 && objc!=1 ){
danielk19774ad17132004-05-21 01:47:26 +00003869 Tcl_AppendResult(interp, "wrong # args: should be \"",
3870 Tcl_GetString(objv[0]), " filename options-list", 0);
3871 return TCL_ERROR;
3872 }
3873
drhafc91042008-02-21 02:09:45 +00003874 zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0;
drhcaffb1a2012-01-30 18:00:31 +00003875 sqlite3_open(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00003876
drh64b1bea2006-01-15 02:30:57 +00003877 if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
danielk19774ad17132004-05-21 01:47:26 +00003878 Tcl_AppendResult(interp, zBuf, 0);
3879 return TCL_OK;
3880}
3881
3882/*
dan286ab7c2011-05-06 18:34:54 +00003883** Usage: sqlite3_open_v2 FILENAME FLAGS VFS
3884*/
3885static int test_open_v2(
3886 void * clientData,
3887 Tcl_Interp *interp,
3888 int objc,
3889 Tcl_Obj *CONST objv[]
3890){
3891 const char *zFilename;
3892 const char *zVfs;
3893 int flags = 0;
3894 sqlite3 *db;
3895 int rc;
3896 char zBuf[100];
3897
3898 int nFlag;
3899 Tcl_Obj **apFlag;
3900 int i;
3901
3902 if( objc!=4 ){
3903 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS");
3904 return TCL_ERROR;
3905 }
3906 zFilename = Tcl_GetString(objv[1]);
3907 zVfs = Tcl_GetString(objv[3]);
3908 if( zVfs[0]==0x00 ) zVfs = 0;
3909
3910 rc = Tcl_ListObjGetElements(interp, objv[2], &nFlag, &apFlag);
3911 if( rc!=TCL_OK ) return rc;
3912 for(i=0; i<nFlag; i++){
3913 int iFlag;
3914 struct OpenFlag {
3915 const char *zFlag;
3916 int flag;
3917 } aFlag[] = {
3918 { "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY },
3919 { "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE },
3920 { "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE },
3921 { "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE },
3922 { "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE },
3923 { "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY },
3924 { "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB },
3925 { "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB },
3926 { "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB },
3927 { "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL },
3928 { "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL },
3929 { "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL },
3930 { "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL },
3931 { "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX },
3932 { "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX },
3933 { "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE },
3934 { "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE },
3935 { "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL },
3936 { "SQLITE_OPEN_URI", SQLITE_OPEN_URI },
3937 { 0, 0 }
3938 };
3939 rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]),
3940 "flag", 0, &iFlag
3941 );
3942 if( rc!=TCL_OK ) return rc;
3943 flags |= aFlag[iFlag].flag;
3944 }
3945
3946 rc = sqlite3_open_v2(zFilename, &db, flags, zVfs);
3947 if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
3948 Tcl_AppendResult(interp, zBuf, 0);
3949 return TCL_OK;
3950}
3951
3952/*
danielk19774ad17132004-05-21 01:47:26 +00003953** Usage: sqlite3_open16 filename options
3954*/
3955static int test_open16(
3956 void * clientData,
3957 Tcl_Interp *interp,
3958 int objc,
3959 Tcl_Obj *CONST objv[]
3960){
drh5436dc22004-11-14 04:04:17 +00003961#ifndef SQLITE_OMIT_UTF16
danielk19774ad17132004-05-21 01:47:26 +00003962 const void *zFilename;
3963 sqlite3 *db;
danielk19774ad17132004-05-21 01:47:26 +00003964 char zBuf[100];
3965
3966 if( objc!=3 ){
3967 Tcl_AppendResult(interp, "wrong # args: should be \"",
3968 Tcl_GetString(objv[0]), " filename options-list", 0);
3969 return TCL_ERROR;
3970 }
3971
3972 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
drhcaffb1a2012-01-30 18:00:31 +00003973 sqlite3_open16(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00003974
drh64b1bea2006-01-15 02:30:57 +00003975 if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
danielk19774ad17132004-05-21 01:47:26 +00003976 Tcl_AppendResult(interp, zBuf, 0);
drh5436dc22004-11-14 04:04:17 +00003977#endif /* SQLITE_OMIT_UTF16 */
danielk19774ad17132004-05-21 01:47:26 +00003978 return TCL_OK;
3979}
drhd3d39e92004-05-20 22:16:29 +00003980
3981/*
danielk1977bc6ada42004-06-30 08:20:16 +00003982** Usage: sqlite3_complete16 <UTF-16 string>
3983**
3984** Return 1 if the supplied argument is a complete SQL statement, or zero
3985** otherwise.
3986*/
3987static int test_complete16(
3988 void * clientData,
3989 Tcl_Interp *interp,
3990 int objc,
3991 Tcl_Obj *CONST objv[]
3992){
drhccae6022005-02-26 17:31:26 +00003993#if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16)
danielk1977bc6ada42004-06-30 08:20:16 +00003994 char *zBuf;
3995
3996 if( objc!=2 ){
3997 Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
3998 return TCL_ERROR;
3999 }
4000
drh03d847e2005-12-09 20:21:58 +00004001 zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0);
danielk1977bc6ada42004-06-30 08:20:16 +00004002 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
drhccae6022005-02-26 17:31:26 +00004003#endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */
danielk1977bc6ada42004-06-30 08:20:16 +00004004 return TCL_OK;
4005}
4006
4007/*
danielk1977106bb232004-05-21 10:08:53 +00004008** Usage: sqlite3_step STMT
4009**
4010** Advance the statement to the next row.
4011*/
danielk197717240fd2004-05-26 00:07:25 +00004012static int test_step(
danielk1977106bb232004-05-21 10:08:53 +00004013 void * clientData,
4014 Tcl_Interp *interp,
4015 int objc,
4016 Tcl_Obj *CONST objv[]
4017){
4018 sqlite3_stmt *pStmt;
4019 int rc;
4020
danielk1977e1cd9872004-05-22 10:33:04 +00004021 if( objc!=2 ){
danielk1977106bb232004-05-21 10:08:53 +00004022 Tcl_AppendResult(interp, "wrong # args: should be \"",
4023 Tcl_GetString(objv[0]), " STMT", 0);
4024 return TCL_ERROR;
4025 }
4026
4027 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
danielk197717240fd2004-05-26 00:07:25 +00004028 rc = sqlite3_step(pStmt);
danielk1977106bb232004-05-21 10:08:53 +00004029
danielk1977fbcd5852004-06-15 02:44:18 +00004030 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
drh4f0c5872007-03-26 22:05:01 +00004031 Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
danielk1977e1cd9872004-05-22 10:33:04 +00004032 return TCL_OK;
4033}
4034
danielk1977404ca072009-03-16 13:19:36 +00004035static int test_sql(
4036 void * clientData,
4037 Tcl_Interp *interp,
4038 int objc,
4039 Tcl_Obj *CONST objv[]
4040){
4041 sqlite3_stmt *pStmt;
4042
4043 if( objc!=2 ){
4044 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
4045 return TCL_ERROR;
4046 }
4047
4048 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4049 Tcl_SetResult(interp, (char *)sqlite3_sql(pStmt), TCL_VOLATILE);
4050 return TCL_OK;
4051}
4052
danielk1977e1cd9872004-05-22 10:33:04 +00004053/*
danielk197717240fd2004-05-26 00:07:25 +00004054** Usage: sqlite3_column_count STMT
4055**
4056** Return the number of columns returned by the sql statement STMT.
4057*/
4058static int test_column_count(
4059 void * clientData,
4060 Tcl_Interp *interp,
4061 int objc,
4062 Tcl_Obj *CONST objv[]
4063){
4064 sqlite3_stmt *pStmt;
4065
4066 if( objc!=2 ){
4067 Tcl_AppendResult(interp, "wrong # args: should be \"",
4068 Tcl_GetString(objv[0]), " STMT column", 0);
4069 return TCL_ERROR;
4070 }
4071
4072 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4073
4074 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
4075 return TCL_OK;
4076}
4077
4078/*
danielk19773cf86062004-05-26 10:11:05 +00004079** Usage: sqlite3_column_type STMT column
4080**
4081** Return the type of the data in column 'column' of the current row.
4082*/
4083static int test_column_type(
4084 void * clientData,
4085 Tcl_Interp *interp,
4086 int objc,
4087 Tcl_Obj *CONST objv[]
4088){
4089 sqlite3_stmt *pStmt;
4090 int col;
4091 int tp;
4092
4093 if( objc!=3 ){
4094 Tcl_AppendResult(interp, "wrong # args: should be \"",
4095 Tcl_GetString(objv[0]), " STMT column", 0);
4096 return TCL_ERROR;
4097 }
4098
4099 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4100 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4101
4102 tp = sqlite3_column_type(pStmt, col);
4103 switch( tp ){
drh9c054832004-05-31 18:51:57 +00004104 case SQLITE_INTEGER:
danielk19773cf86062004-05-26 10:11:05 +00004105 Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
4106 break;
drh9c054832004-05-31 18:51:57 +00004107 case SQLITE_NULL:
danielk19773cf86062004-05-26 10:11:05 +00004108 Tcl_SetResult(interp, "NULL", TCL_STATIC);
4109 break;
drh9c054832004-05-31 18:51:57 +00004110 case SQLITE_FLOAT:
danielk19773cf86062004-05-26 10:11:05 +00004111 Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
4112 break;
drh9c054832004-05-31 18:51:57 +00004113 case SQLITE_TEXT:
danielk19773cf86062004-05-26 10:11:05 +00004114 Tcl_SetResult(interp, "TEXT", TCL_STATIC);
4115 break;
drh9c054832004-05-31 18:51:57 +00004116 case SQLITE_BLOB:
danielk19773cf86062004-05-26 10:11:05 +00004117 Tcl_SetResult(interp, "BLOB", TCL_STATIC);
4118 break;
4119 default:
4120 assert(0);
4121 }
4122
4123 return TCL_OK;
4124}
4125
4126/*
danielk197704f2e682004-05-27 01:04:07 +00004127** Usage: sqlite3_column_int64 STMT column
danielk19773cf86062004-05-26 10:11:05 +00004128**
4129** Return the data in column 'column' of the current row cast as an
danielk197704f2e682004-05-27 01:04:07 +00004130** wide (64-bit) integer.
danielk19773cf86062004-05-26 10:11:05 +00004131*/
danielk197704f2e682004-05-27 01:04:07 +00004132static int test_column_int64(
danielk19773cf86062004-05-26 10:11:05 +00004133 void * clientData,
4134 Tcl_Interp *interp,
4135 int objc,
4136 Tcl_Obj *CONST objv[]
4137){
4138 sqlite3_stmt *pStmt;
4139 int col;
danielk197704f2e682004-05-27 01:04:07 +00004140 i64 iVal;
danielk19773cf86062004-05-26 10:11:05 +00004141
4142 if( objc!=3 ){
4143 Tcl_AppendResult(interp, "wrong # args: should be \"",
4144 Tcl_GetString(objv[0]), " STMT column", 0);
4145 return TCL_ERROR;
4146 }
4147
4148 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4149 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4150
danielk197704f2e682004-05-27 01:04:07 +00004151 iVal = sqlite3_column_int64(pStmt, col);
4152 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
4153 return TCL_OK;
4154}
4155
4156/*
danielk1977ea61b2c2004-05-27 01:49:51 +00004157** Usage: sqlite3_column_blob STMT column
4158*/
4159static int test_column_blob(
4160 void * clientData,
4161 Tcl_Interp *interp,
4162 int objc,
4163 Tcl_Obj *CONST objv[]
4164){
4165 sqlite3_stmt *pStmt;
4166 int col;
4167
4168 int len;
danielk1977c572ef72004-05-27 09:28:41 +00004169 const void *pBlob;
danielk1977ea61b2c2004-05-27 01:49:51 +00004170
4171 if( objc!=3 ){
4172 Tcl_AppendResult(interp, "wrong # args: should be \"",
4173 Tcl_GetString(objv[0]), " STMT column", 0);
4174 return TCL_ERROR;
4175 }
4176
4177 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4178 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4179
danielk1977ea61b2c2004-05-27 01:49:51 +00004180 len = sqlite3_column_bytes(pStmt, col);
drh9310ef22007-04-27 17:16:20 +00004181 pBlob = sqlite3_column_blob(pStmt, col);
danielk1977ea61b2c2004-05-27 01:49:51 +00004182 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
4183 return TCL_OK;
4184}
4185
4186/*
danielk197704f2e682004-05-27 01:04:07 +00004187** Usage: sqlite3_column_double STMT column
4188**
4189** Return the data in column 'column' of the current row cast as a double.
4190*/
4191static int test_column_double(
4192 void * clientData,
4193 Tcl_Interp *interp,
4194 int objc,
4195 Tcl_Obj *CONST objv[]
4196){
4197 sqlite3_stmt *pStmt;
4198 int col;
4199 double rVal;
4200
4201 if( objc!=3 ){
4202 Tcl_AppendResult(interp, "wrong # args: should be \"",
4203 Tcl_GetString(objv[0]), " STMT column", 0);
4204 return TCL_ERROR;
4205 }
4206
4207 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4208 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4209
4210 rVal = sqlite3_column_double(pStmt, col);
danielk1977c572ef72004-05-27 09:28:41 +00004211 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
danielk19773cf86062004-05-26 10:11:05 +00004212 return TCL_OK;
4213}
4214
4215/*
danielk197717240fd2004-05-26 00:07:25 +00004216** Usage: sqlite3_data_count STMT
4217**
4218** Return the number of columns returned by the sql statement STMT.
4219*/
4220static int test_data_count(
4221 void * clientData,
4222 Tcl_Interp *interp,
4223 int objc,
4224 Tcl_Obj *CONST objv[]
4225){
4226 sqlite3_stmt *pStmt;
4227
4228 if( objc!=2 ){
4229 Tcl_AppendResult(interp, "wrong # args: should be \"",
4230 Tcl_GetString(objv[0]), " STMT column", 0);
4231 return TCL_ERROR;
4232 }
4233
4234 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4235
4236 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
4237 return TCL_OK;
4238}
4239
4240/*
danielk197704f2e682004-05-27 01:04:07 +00004241** Usage: sqlite3_column_text STMT column
4242**
4243** Usage: sqlite3_column_decltype STMT column
4244**
4245** Usage: sqlite3_column_name STMT column
4246*/
4247static int test_stmt_utf8(
drh241db312004-06-22 12:46:53 +00004248 void * clientData, /* Pointer to SQLite API function to be invoke */
danielk197704f2e682004-05-27 01:04:07 +00004249 Tcl_Interp *interp,
4250 int objc,
4251 Tcl_Obj *CONST objv[]
4252){
4253 sqlite3_stmt *pStmt;
4254 int col;
danielk197744a376f2008-08-12 15:04:58 +00004255 const char *(*xFunc)(sqlite3_stmt*, int);
danielk1977f93bbbe2004-05-27 10:30:52 +00004256 const char *zRet;
danielk197704f2e682004-05-27 01:04:07 +00004257
danielk197744a376f2008-08-12 15:04:58 +00004258 xFunc = (const char *(*)(sqlite3_stmt*, int))clientData;
danielk197704f2e682004-05-27 01:04:07 +00004259 if( objc!=3 ){
4260 Tcl_AppendResult(interp, "wrong # args: should be \"",
4261 Tcl_GetString(objv[0]), " STMT column", 0);
4262 return TCL_ERROR;
4263 }
4264
4265 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4266 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
danielk1977f93bbbe2004-05-27 10:30:52 +00004267 zRet = xFunc(pStmt, col);
4268 if( zRet ){
4269 Tcl_SetResult(interp, (char *)zRet, 0);
4270 }
danielk197704f2e682004-05-27 01:04:07 +00004271 return TCL_OK;
4272}
4273
danielk19776b456a22005-03-21 04:04:02 +00004274static int test_global_recover(
4275 void * clientData,
4276 Tcl_Interp *interp,
4277 int objc,
4278 Tcl_Obj *CONST objv[]
4279){
shaneeec556d2008-10-12 00:27:53 +00004280#ifndef SQLITE_OMIT_DEPRECATED
danielk19776b456a22005-03-21 04:04:02 +00004281 int rc;
4282 if( objc!=1 ){
4283 Tcl_WrongNumArgs(interp, 1, objv, "");
4284 return TCL_ERROR;
4285 }
4286 rc = sqlite3_global_recover();
drh4f0c5872007-03-26 22:05:01 +00004287 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
danielk19776b456a22005-03-21 04:04:02 +00004288#endif
4289 return TCL_OK;
4290}
4291
danielk197704f2e682004-05-27 01:04:07 +00004292/*
4293** Usage: sqlite3_column_text STMT column
4294**
4295** Usage: sqlite3_column_decltype STMT column
4296**
4297** Usage: sqlite3_column_name STMT column
4298*/
4299static int test_stmt_utf16(
drh241db312004-06-22 12:46:53 +00004300 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00004301 Tcl_Interp *interp,
4302 int objc,
4303 Tcl_Obj *CONST objv[]
4304){
drh5436dc22004-11-14 04:04:17 +00004305#ifndef SQLITE_OMIT_UTF16
danielk197704f2e682004-05-27 01:04:07 +00004306 sqlite3_stmt *pStmt;
4307 int col;
4308 Tcl_Obj *pRet;
4309 const void *zName16;
danielk197744a376f2008-08-12 15:04:58 +00004310 const void *(*xFunc)(sqlite3_stmt*, int);
danielk197704f2e682004-05-27 01:04:07 +00004311
danielk197744a376f2008-08-12 15:04:58 +00004312 xFunc = (const void *(*)(sqlite3_stmt*, int))clientData;
danielk197704f2e682004-05-27 01:04:07 +00004313 if( objc!=3 ){
4314 Tcl_AppendResult(interp, "wrong # args: should be \"",
4315 Tcl_GetString(objv[0]), " STMT column", 0);
4316 return TCL_ERROR;
4317 }
4318
4319 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4320 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4321
4322 zName16 = xFunc(pStmt, col);
danielk1977f93bbbe2004-05-27 10:30:52 +00004323 if( zName16 ){
drhaed382f2009-04-01 18:40:32 +00004324 int n;
4325 const char *z = zName16;
4326 for(n=0; z[n] || z[n+1]; n+=2){}
4327 pRet = Tcl_NewByteArrayObj(zName16, n+2);
danielk1977f93bbbe2004-05-27 10:30:52 +00004328 Tcl_SetObjResult(interp, pRet);
4329 }
drh5436dc22004-11-14 04:04:17 +00004330#endif /* SQLITE_OMIT_UTF16 */
danielk197704f2e682004-05-27 01:04:07 +00004331
4332 return TCL_OK;
4333}
4334
4335/*
4336** Usage: sqlite3_column_int STMT column
4337**
4338** Usage: sqlite3_column_bytes STMT column
4339**
4340** Usage: sqlite3_column_bytes16 STMT column
4341**
4342*/
4343static int test_stmt_int(
drh241db312004-06-22 12:46:53 +00004344 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00004345 Tcl_Interp *interp,
4346 int objc,
4347 Tcl_Obj *CONST objv[]
4348){
4349 sqlite3_stmt *pStmt;
4350 int col;
danielk197744a376f2008-08-12 15:04:58 +00004351 int (*xFunc)(sqlite3_stmt*, int);
danielk197704f2e682004-05-27 01:04:07 +00004352
danielk197755a25a12008-09-11 10:29:15 +00004353 xFunc = (int (*)(sqlite3_stmt*, int))clientData;
danielk197704f2e682004-05-27 01:04:07 +00004354 if( objc!=3 ){
4355 Tcl_AppendResult(interp, "wrong # args: should be \"",
4356 Tcl_GetString(objv[0]), " STMT column", 0);
4357 return TCL_ERROR;
4358 }
4359
4360 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4361 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4362
4363 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
4364 return TCL_OK;
4365}
4366
danielk19776622cce2004-05-20 11:00:52 +00004367/*
drhcacb2082005-01-11 15:28:33 +00004368** Usage: sqlite_set_magic DB MAGIC-NUMBER
4369**
4370** Set the db->magic value. This is used to test error recovery logic.
4371*/
4372static int sqlite_set_magic(
4373 void * clientData,
4374 Tcl_Interp *interp,
4375 int argc,
4376 char **argv
4377){
4378 sqlite3 *db;
4379 if( argc!=3 ){
4380 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4381 " DB MAGIC", 0);
4382 return TCL_ERROR;
4383 }
4384 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4385 if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
4386 db->magic = SQLITE_MAGIC_OPEN;
4387 }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
4388 db->magic = SQLITE_MAGIC_CLOSED;
4389 }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
4390 db->magic = SQLITE_MAGIC_BUSY;
4391 }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
4392 db->magic = SQLITE_MAGIC_ERROR;
drh902b9ee2008-12-05 17:17:07 +00004393 }else if( Tcl_GetInt(interp, argv[2], (int*)&db->magic) ){
drhcacb2082005-01-11 15:28:33 +00004394 return TCL_ERROR;
4395 }
4396 return TCL_OK;
4397}
4398
4399/*
drhc5cdca62005-01-11 16:54:14 +00004400** Usage: sqlite3_interrupt DB
4401**
4402** Trigger an interrupt on DB
4403*/
4404static int test_interrupt(
4405 void * clientData,
4406 Tcl_Interp *interp,
4407 int argc,
4408 char **argv
4409){
4410 sqlite3 *db;
4411 if( argc!=2 ){
4412 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
4413 return TCL_ERROR;
4414 }
4415 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4416 sqlite3_interrupt(db);
4417 return TCL_OK;
4418}
4419
drh79158e12005-09-06 21:40:45 +00004420static u8 *sqlite3_stack_baseline = 0;
4421
drhc5cdca62005-01-11 16:54:14 +00004422/*
drh79158e12005-09-06 21:40:45 +00004423** Fill the stack with a known bitpattern.
danielk1977600dd0b2005-01-20 01:14:23 +00004424*/
drh79158e12005-09-06 21:40:45 +00004425static void prepStack(void){
4426 int i;
4427 u32 bigBuf[65536];
drhbc2be0c2011-08-30 00:53:50 +00004428 for(i=0; i<sizeof(bigBuf)/sizeof(bigBuf[0]); i++) bigBuf[i] = 0xdeadbeef;
drh79158e12005-09-06 21:40:45 +00004429 sqlite3_stack_baseline = (u8*)&bigBuf[65536];
4430}
4431
4432/*
4433** Get the current stack depth. Used for debugging only.
4434*/
4435u64 sqlite3StackDepth(void){
4436 u8 x;
4437 return (u64)(sqlite3_stack_baseline - &x);
4438}
4439
4440/*
4441** Usage: sqlite3_stack_used DB SQL
4442**
4443** Try to measure the amount of stack space used by a call to sqlite3_exec
4444*/
4445static int test_stack_used(
danielk1977600dd0b2005-01-20 01:14:23 +00004446 void * clientData,
4447 Tcl_Interp *interp,
4448 int argc,
4449 char **argv
4450){
4451 sqlite3 *db;
drh79158e12005-09-06 21:40:45 +00004452 int i;
4453 if( argc!=3 ){
4454 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4455 " DB SQL", 0);
danielk1977600dd0b2005-01-20 01:14:23 +00004456 return TCL_ERROR;
4457 }
drh79158e12005-09-06 21:40:45 +00004458 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4459 prepStack();
drh37527852006-03-16 16:19:56 +00004460 (void)sqlite3_exec(db, argv[2], 0, 0, 0);
drh79158e12005-09-06 21:40:45 +00004461 for(i=65535; i>=0 && ((u32*)sqlite3_stack_baseline)[-i]==0xdeadbeef; i--){}
4462 Tcl_SetObjResult(interp, Tcl_NewIntObj(i*4));
danielk1977600dd0b2005-01-20 01:14:23 +00004463 return TCL_OK;
4464}
danielk1977600dd0b2005-01-20 01:14:23 +00004465
4466/*
danielk19779636c4e2005-01-25 04:27:54 +00004467** Usage: sqlite_delete_function DB function-name
4468**
4469** Delete the user function 'function-name' from database handle DB. It
4470** is assumed that the user function was created as UTF8, any number of
4471** arguments (the way the TCL interface does it).
4472*/
4473static int delete_function(
4474 void * clientData,
4475 Tcl_Interp *interp,
4476 int argc,
4477 char **argv
4478){
4479 int rc;
4480 sqlite3 *db;
4481 if( argc!=3 ){
4482 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4483 " DB function-name", 0);
4484 return TCL_ERROR;
4485 }
4486 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4487 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
drh4f0c5872007-03-26 22:05:01 +00004488 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
danielk19779636c4e2005-01-25 04:27:54 +00004489 return TCL_OK;
4490}
4491
4492/*
4493** Usage: sqlite_delete_collation DB collation-name
4494**
4495** Delete the collation sequence 'collation-name' from database handle
4496** DB. It is assumed that the collation sequence was created as UTF8 (the
4497** way the TCL interface does it).
4498*/
4499static int delete_collation(
4500 void * clientData,
4501 Tcl_Interp *interp,
4502 int argc,
4503 char **argv
4504){
4505 int rc;
4506 sqlite3 *db;
4507 if( argc!=3 ){
4508 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4509 " DB function-name", 0);
4510 return TCL_ERROR;
4511 }
4512 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4513 rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
drh4f0c5872007-03-26 22:05:01 +00004514 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
danielk19779636c4e2005-01-25 04:27:54 +00004515 return TCL_OK;
4516}
4517
4518/*
drh3e1d8e62005-05-26 16:23:34 +00004519** Usage: sqlite3_get_autocommit DB
4520**
4521** Return true if the database DB is currently in auto-commit mode.
4522** Return false if not.
4523*/
4524static int get_autocommit(
4525 void * clientData,
4526 Tcl_Interp *interp,
4527 int argc,
4528 char **argv
4529){
4530 char zBuf[30];
4531 sqlite3 *db;
4532 if( argc!=2 ){
4533 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4534 " DB", 0);
4535 return TCL_ERROR;
4536 }
4537 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drh65545b52015-01-19 00:35:53 +00004538 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3_get_autocommit(db));
drh3e1d8e62005-05-26 16:23:34 +00004539 Tcl_AppendResult(interp, zBuf, 0);
4540 return TCL_OK;
4541}
4542
4543/*
drh30867652006-07-06 10:59:57 +00004544** Usage: sqlite3_busy_timeout DB MS
4545**
4546** Set the busy timeout. This is more easily done using the timeout
4547** method of the TCL interface. But we need a way to test the case
4548** where it returns SQLITE_MISUSE.
4549*/
4550static int test_busy_timeout(
4551 void * clientData,
4552 Tcl_Interp *interp,
4553 int argc,
4554 char **argv
4555){
4556 int rc, ms;
4557 sqlite3 *db;
4558 if( argc!=3 ){
4559 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4560 " DB", 0);
4561 return TCL_ERROR;
4562 }
4563 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4564 if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR;
4565 rc = sqlite3_busy_timeout(db, ms);
mistachkine84d8d32013-04-29 03:09:10 +00004566 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drh30867652006-07-06 10:59:57 +00004567 return TCL_OK;
4568}
4569
4570/*
drh92febd92004-08-20 18:34:20 +00004571** Usage: tcl_variable_type VARIABLENAME
4572**
4573** Return the name of the internal representation for the
4574** value of the given variable.
4575*/
4576static int tcl_variable_type(
4577 void * clientData,
4578 Tcl_Interp *interp,
4579 int objc,
4580 Tcl_Obj *CONST objv[]
4581){
4582 Tcl_Obj *pVar;
4583 if( objc!=2 ){
4584 Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
4585 return TCL_ERROR;
4586 }
4587 pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
4588 if( pVar==0 ) return TCL_ERROR;
4589 if( pVar->typePtr ){
4590 Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
4591 }
4592 return TCL_OK;
4593}
4594
4595/*
drh6aafc292006-01-05 15:50:06 +00004596** Usage: sqlite3_release_memory ?N?
4597**
4598** Attempt to release memory currently held but not actually required.
4599** The integer N is the number of bytes we are trying to release. The
4600** return value is the amount of memory actually released.
4601*/
4602static int test_release_memory(
4603 void * clientData,
4604 Tcl_Interp *interp,
4605 int objc,
4606 Tcl_Obj *CONST objv[]
4607){
drh6f7adc82006-01-11 21:41:20 +00004608#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
drh6aafc292006-01-05 15:50:06 +00004609 int N;
4610 int amt;
4611 if( objc!=1 && objc!=2 ){
4612 Tcl_WrongNumArgs(interp, 1, objv, "?N?");
4613 return TCL_ERROR;
4614 }
4615 if( objc==2 ){
4616 if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
4617 }else{
4618 N = -1;
4619 }
4620 amt = sqlite3_release_memory(N);
4621 Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
4622#endif
4623 return TCL_OK;
4624}
4625
drh09419b42011-11-16 19:29:17 +00004626
4627/*
4628** Usage: sqlite3_db_release_memory DB
4629**
4630** Attempt to release memory currently held by database DB. Return the
4631** result code (which in the current implementation is always zero).
4632*/
4633static int test_db_release_memory(
4634 void * clientData,
4635 Tcl_Interp *interp,
4636 int objc,
4637 Tcl_Obj *CONST objv[]
4638){
4639 sqlite3 *db;
4640 int rc;
4641 if( objc!=2 ){
4642 Tcl_WrongNumArgs(interp, 1, objv, "DB");
4643 return TCL_ERROR;
4644 }
4645 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4646 rc = sqlite3_db_release_memory(db);
4647 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
4648 return TCL_OK;
4649}
4650
drh6aafc292006-01-05 15:50:06 +00004651/*
drh283829c2011-11-17 00:56:20 +00004652** Usage: sqlite3_db_filename DB DBNAME
4653**
4654** Return the name of a file associated with a database.
4655*/
4656static int test_db_filename(
4657 void * clientData,
4658 Tcl_Interp *interp,
4659 int objc,
4660 Tcl_Obj *CONST objv[]
4661){
4662 sqlite3 *db;
4663 const char *zDbName;
4664 if( objc!=3 ){
4665 Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
4666 return TCL_ERROR;
4667 }
4668 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4669 zDbName = Tcl_GetString(objv[2]);
4670 Tcl_AppendResult(interp, sqlite3_db_filename(db, zDbName), (void*)0);
4671 return TCL_OK;
4672}
4673
4674/*
drh421377e2012-03-15 21:28:54 +00004675** Usage: sqlite3_db_readonly DB DBNAME
4676**
4677** Return 1 or 0 if DBNAME is readonly or not. Return -1 if DBNAME does
4678** not exist.
4679*/
4680static int test_db_readonly(
4681 void * clientData,
4682 Tcl_Interp *interp,
4683 int objc,
4684 Tcl_Obj *CONST objv[]
4685){
4686 sqlite3 *db;
4687 const char *zDbName;
4688 if( objc!=3 ){
4689 Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
4690 return TCL_ERROR;
4691 }
4692 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4693 zDbName = Tcl_GetString(objv[2]);
4694 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_db_readonly(db, zDbName)));
4695 return TCL_OK;
4696}
4697
4698/*
drh6aafc292006-01-05 15:50:06 +00004699** Usage: sqlite3_soft_heap_limit ?N?
4700**
4701** Query or set the soft heap limit for the current thread. The
4702** limit is only changed if the N is present. The previous limit
4703** is returned.
4704*/
4705static int test_soft_heap_limit(
4706 void * clientData,
4707 Tcl_Interp *interp,
4708 int objc,
4709 Tcl_Obj *CONST objv[]
4710){
drhf82ccf62010-09-15 17:54:31 +00004711 sqlite3_int64 amt;
drhb3f787f2012-09-29 14:45:54 +00004712 Tcl_WideInt N = -1;
drh6aafc292006-01-05 15:50:06 +00004713 if( objc!=1 && objc!=2 ){
4714 Tcl_WrongNumArgs(interp, 1, objv, "?N?");
4715 return TCL_ERROR;
4716 }
drh6aafc292006-01-05 15:50:06 +00004717 if( objc==2 ){
drhf82ccf62010-09-15 17:54:31 +00004718 if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
drh6aafc292006-01-05 15:50:06 +00004719 }
drhf82ccf62010-09-15 17:54:31 +00004720 amt = sqlite3_soft_heap_limit64(N);
4721 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt));
drh6aafc292006-01-05 15:50:06 +00004722 return TCL_OK;
4723}
4724
4725/*
drhb4bc7052006-01-11 23:40:33 +00004726** Usage: sqlite3_thread_cleanup
4727**
4728** Call the sqlite3_thread_cleanup API.
4729*/
4730static int test_thread_cleanup(
4731 void * clientData,
4732 Tcl_Interp *interp,
4733 int objc,
4734 Tcl_Obj *CONST objv[]
4735){
shaneeec556d2008-10-12 00:27:53 +00004736#ifndef SQLITE_OMIT_DEPRECATED
drhb4bc7052006-01-11 23:40:33 +00004737 sqlite3_thread_cleanup();
shaneeec556d2008-10-12 00:27:53 +00004738#endif
drhb4bc7052006-01-11 23:40:33 +00004739 return TCL_OK;
4740}
4741
drhb4bc7052006-01-11 23:40:33 +00004742/*
drhc6ba55f2007-04-05 17:36:18 +00004743** Usage: sqlite3_pager_refcounts DB
4744**
drhf5345442007-04-09 12:45:02 +00004745** Return a list of numbers which are the PagerRefcount for all
4746** pagers on each database connection.
drhc6ba55f2007-04-05 17:36:18 +00004747*/
4748static int test_pager_refcounts(
4749 void * clientData,
4750 Tcl_Interp *interp,
4751 int objc,
4752 Tcl_Obj *CONST objv[]
4753){
4754 sqlite3 *db;
4755 int i;
4756 int v, *a;
4757 Tcl_Obj *pResult;
4758
4759 if( objc!=2 ){
4760 Tcl_AppendResult(interp, "wrong # args: should be \"",
drhf5345442007-04-09 12:45:02 +00004761 Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
drhc6ba55f2007-04-05 17:36:18 +00004762 return TCL_ERROR;
4763 }
4764 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4765 pResult = Tcl_NewObj();
4766 for(i=0; i<db->nDb; i++){
4767 if( db->aDb[i].pBt==0 ){
4768 v = -1;
4769 }else{
drh27641702007-08-22 02:56:42 +00004770 sqlite3_mutex_enter(db->mutex);
drhc6ba55f2007-04-05 17:36:18 +00004771 a = sqlite3PagerStats(sqlite3BtreePager(db->aDb[i].pBt));
4772 v = a[0];
drh27641702007-08-22 02:56:42 +00004773 sqlite3_mutex_leave(db->mutex);
drhc6ba55f2007-04-05 17:36:18 +00004774 }
4775 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(v));
4776 }
4777 Tcl_SetObjResult(interp, pResult);
4778 return TCL_OK;
4779}
4780
4781
4782/*
drh80788d82006-09-02 14:50:23 +00004783** tclcmd: working_64bit_int
4784**
4785** Some TCL builds (ex: cygwin) do not support 64-bit integers. This
4786** leads to a number of test failures. The present command checks the
4787** TCL build to see whether or not it supports 64-bit integers. It
4788** returns TRUE if it does and FALSE if not.
4789**
4790** This command is used to warn users that their TCL build is defective
4791** and that the errors they are seeing in the test scripts might be
4792** a result of their defective TCL rather than problems in SQLite.
4793*/
4794static int working_64bit_int(
4795 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4796 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4797 int objc, /* Number of arguments */
4798 Tcl_Obj *CONST objv[] /* Command arguments */
4799){
4800 Tcl_Obj *pTestObj;
4801 int working = 0;
4802
4803 pTestObj = Tcl_NewWideIntObj(1000000*(i64)1234567890);
4804 working = strcmp(Tcl_GetString(pTestObj), "1234567890000000")==0;
4805 Tcl_DecrRefCount(pTestObj);
4806 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(working));
4807 return TCL_OK;
4808}
4809
4810
4811/*
drh9bc54492007-10-23 14:49:59 +00004812** tclcmd: vfs_unlink_test
4813**
4814** This TCL command unregisters the primary VFS and then registers
4815** it back again. This is used to test the ability to register a
4816** VFS when none are previously registered, and the ability to
4817** unregister the only available VFS. Ticket #2738
4818*/
4819static int vfs_unlink_test(
4820 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4821 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4822 int objc, /* Number of arguments */
4823 Tcl_Obj *CONST objv[] /* Command arguments */
4824){
4825 int i;
drh91fd4d42008-01-19 20:11:25 +00004826 sqlite3_vfs *pMain;
drh9bc54492007-10-23 14:49:59 +00004827 sqlite3_vfs *apVfs[20];
drh91fd4d42008-01-19 20:11:25 +00004828 sqlite3_vfs one, two;
drh9bc54492007-10-23 14:49:59 +00004829
drh91fd4d42008-01-19 20:11:25 +00004830 sqlite3_vfs_unregister(0); /* Unregister of NULL is harmless */
4831 one.zName = "__one";
4832 two.zName = "__two";
4833
4834 /* Calling sqlite3_vfs_register with 2nd argument of 0 does not
4835 ** change the default VFS
4836 */
4837 pMain = sqlite3_vfs_find(0);
4838 sqlite3_vfs_register(&one, 0);
4839 assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
4840 sqlite3_vfs_register(&two, 0);
4841 assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
4842
4843 /* We can find a VFS by its name */
4844 assert( sqlite3_vfs_find("__one")==&one );
4845 assert( sqlite3_vfs_find("__two")==&two );
4846
4847 /* Calling sqlite_vfs_register with non-zero second parameter changes the
4848 ** default VFS, even if the 1st parameter is an existig VFS that is
4849 ** previously registered as the non-default.
4850 */
4851 sqlite3_vfs_register(&one, 1);
4852 assert( sqlite3_vfs_find("__one")==&one );
4853 assert( sqlite3_vfs_find("__two")==&two );
4854 assert( sqlite3_vfs_find(0)==&one );
4855 sqlite3_vfs_register(&two, 1);
4856 assert( sqlite3_vfs_find("__one")==&one );
4857 assert( sqlite3_vfs_find("__two")==&two );
4858 assert( sqlite3_vfs_find(0)==&two );
4859 if( pMain ){
4860 sqlite3_vfs_register(pMain, 1);
4861 assert( sqlite3_vfs_find("__one")==&one );
4862 assert( sqlite3_vfs_find("__two")==&two );
4863 assert( sqlite3_vfs_find(0)==pMain );
4864 }
4865
4866 /* Unlink the default VFS. Repeat until there are no more VFSes
4867 ** registered.
4868 */
drh9bc54492007-10-23 14:49:59 +00004869 for(i=0; i<sizeof(apVfs)/sizeof(apVfs[0]); i++){
4870 apVfs[i] = sqlite3_vfs_find(0);
4871 if( apVfs[i] ){
4872 assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
4873 sqlite3_vfs_unregister(apVfs[i]);
4874 assert( 0==sqlite3_vfs_find(apVfs[i]->zName) );
4875 }
4876 }
4877 assert( 0==sqlite3_vfs_find(0) );
mlcreech1f045332008-04-08 03:07:54 +00004878
4879 /* Register the main VFS as non-default (will be made default, since
4880 ** it'll be the only one in existence).
4881 */
4882 sqlite3_vfs_register(pMain, 0);
4883 assert( sqlite3_vfs_find(0)==pMain );
4884
4885 /* Un-register the main VFS again to restore an empty VFS list */
4886 sqlite3_vfs_unregister(pMain);
4887 assert( 0==sqlite3_vfs_find(0) );
drh91fd4d42008-01-19 20:11:25 +00004888
4889 /* Relink all VFSes in reverse order. */
drh9bc54492007-10-23 14:49:59 +00004890 for(i=sizeof(apVfs)/sizeof(apVfs[0])-1; i>=0; i--){
4891 if( apVfs[i] ){
4892 sqlite3_vfs_register(apVfs[i], 1);
4893 assert( apVfs[i]==sqlite3_vfs_find(0) );
4894 assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
4895 }
4896 }
drh91fd4d42008-01-19 20:11:25 +00004897
4898 /* Unregister out sample VFSes. */
4899 sqlite3_vfs_unregister(&one);
4900 sqlite3_vfs_unregister(&two);
4901
4902 /* Unregistering a VFS that is not currently registered is harmless */
4903 sqlite3_vfs_unregister(&one);
4904 sqlite3_vfs_unregister(&two);
4905 assert( sqlite3_vfs_find("__one")==0 );
4906 assert( sqlite3_vfs_find("__two")==0 );
4907
4908 /* We should be left with the original default VFS back as the
4909 ** original */
4910 assert( sqlite3_vfs_find(0)==pMain );
4911
drh9bc54492007-10-23 14:49:59 +00004912 return TCL_OK;
4913}
4914
drh93aed5a2008-01-16 17:46:38 +00004915/*
drhc8d75672008-07-08 02:12:37 +00004916** tclcmd: vfs_initfail_test
4917**
4918** This TCL command attempts to vfs_find and vfs_register when the
4919** sqlite3_initialize() interface is failing. All calls should fail.
4920*/
4921static int vfs_initfail_test(
4922 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4923 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4924 int objc, /* Number of arguments */
4925 Tcl_Obj *CONST objv[] /* Command arguments */
4926){
4927 sqlite3_vfs one;
4928 one.zName = "__one";
4929
4930 if( sqlite3_vfs_find(0) ) return TCL_ERROR;
4931 sqlite3_vfs_register(&one, 0);
4932 if( sqlite3_vfs_find(0) ) return TCL_ERROR;
4933 sqlite3_vfs_register(&one, 1);
4934 if( sqlite3_vfs_find(0) ) return TCL_ERROR;
4935 return TCL_OK;
4936}
4937
4938/*
drha2820972008-07-07 13:31:58 +00004939** Saved VFSes
4940*/
4941static sqlite3_vfs *apVfs[20];
4942static int nVfs = 0;
4943
4944/*
4945** tclcmd: vfs_unregister_all
4946**
4947** Unregister all VFSes.
4948*/
4949static int vfs_unregister_all(
4950 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4951 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4952 int objc, /* Number of arguments */
4953 Tcl_Obj *CONST objv[] /* Command arguments */
4954){
4955 int i;
4956 for(i=0; i<ArraySize(apVfs); i++){
4957 apVfs[i] = sqlite3_vfs_find(0);
4958 if( apVfs[i]==0 ) break;
4959 sqlite3_vfs_unregister(apVfs[i]);
4960 }
4961 nVfs = i;
4962 return TCL_OK;
4963}
4964/*
4965** tclcmd: vfs_reregister_all
4966**
4967** Restore all VFSes that were removed using vfs_unregister_all
4968*/
4969static int vfs_reregister_all(
4970 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4971 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4972 int objc, /* Number of arguments */
4973 Tcl_Obj *CONST objv[] /* Command arguments */
4974){
4975 int i;
4976 for(i=0; i<nVfs; i++){
4977 sqlite3_vfs_register(apVfs[i], i==0);
4978 }
4979 return TCL_OK;
4980}
4981
4982
4983/*
drh55176252008-01-22 14:50:16 +00004984** tclcmd: file_control_test DB
4985**
4986** This TCL command runs the sqlite3_file_control interface and
4987** verifies correct operation of the same.
4988*/
4989static int file_control_test(
4990 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4991 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4992 int objc, /* Number of arguments */
4993 Tcl_Obj *CONST objv[] /* Command arguments */
4994){
4995 int iArg = 0;
4996 sqlite3 *db;
4997 int rc;
4998
4999 if( objc!=2 ){
5000 Tcl_AppendResult(interp, "wrong # args: should be \"",
5001 Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
5002 return TCL_ERROR;
5003 }
5004 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
5005 rc = sqlite3_file_control(db, 0, 0, &iArg);
drh0b52b7d2011-01-26 19:46:22 +00005006 assert( rc==SQLITE_NOTFOUND );
drh55176252008-01-22 14:50:16 +00005007 rc = sqlite3_file_control(db, "notadatabase", SQLITE_FCNTL_LOCKSTATE, &iArg);
5008 assert( rc==SQLITE_ERROR );
5009 rc = sqlite3_file_control(db, "main", -1, &iArg);
drh0b52b7d2011-01-26 19:46:22 +00005010 assert( rc==SQLITE_NOTFOUND );
drh55176252008-01-22 14:50:16 +00005011 rc = sqlite3_file_control(db, "temp", -1, &iArg);
drh0b52b7d2011-01-26 19:46:22 +00005012 assert( rc==SQLITE_NOTFOUND || rc==SQLITE_ERROR );
aswiftaebf4132008-11-21 00:10:35 +00005013
5014 return TCL_OK;
5015}
5016
5017
5018/*
5019** tclcmd: file_control_lasterrno_test DB
5020**
5021** This TCL command runs the sqlite3_file_control interface and
5022** verifies correct operation of the SQLITE_LAST_ERRNO verb.
5023*/
5024static int file_control_lasterrno_test(
5025 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5026 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5027 int objc, /* Number of arguments */
5028 Tcl_Obj *CONST objv[] /* Command arguments */
5029){
5030 int iArg = 0;
5031 sqlite3 *db;
5032 int rc;
5033
5034 if( objc!=2 ){
5035 Tcl_AppendResult(interp, "wrong # args: should be \"",
5036 Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
5037 return TCL_ERROR;
5038 }
shane9db299f2009-01-30 05:59:10 +00005039 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5040 return TCL_ERROR;
5041 }
aswiftaebf4132008-11-21 00:10:35 +00005042 rc = sqlite3_file_control(db, NULL, SQLITE_LAST_ERRNO, &iArg);
shane9db299f2009-01-30 05:59:10 +00005043 if( rc ){
5044 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5045 return TCL_ERROR;
5046 }
aswiftaebf4132008-11-21 00:10:35 +00005047 if( iArg!=0 ) {
5048 Tcl_AppendResult(interp, "Unexpected non-zero errno: ",
5049 Tcl_GetStringFromObj(Tcl_NewIntObj(iArg), 0), " ", 0);
5050 return TCL_ERROR;
5051 }
drh55176252008-01-22 14:50:16 +00005052 return TCL_OK;
5053}
5054
5055/*
dan6e09d692010-07-27 18:34:15 +00005056** tclcmd: file_control_chunksize_test DB DBNAME SIZE
5057**
5058** This TCL command runs the sqlite3_file_control interface and
5059** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
5060** SQLITE_SET_LOCKPROXYFILE verbs.
5061*/
5062static int file_control_chunksize_test(
5063 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5064 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5065 int objc, /* Number of arguments */
5066 Tcl_Obj *CONST objv[] /* Command arguments */
5067){
5068 int nSize; /* New chunk size */
5069 char *zDb; /* Db name ("main", "temp" etc.) */
5070 sqlite3 *db; /* Database handle */
5071 int rc; /* file_control() return code */
5072
5073 if( objc!=4 ){
5074 Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
5075 return TCL_ERROR;
5076 }
5077 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
5078 || Tcl_GetIntFromObj(interp, objv[3], &nSize)
5079 ){
5080 return TCL_ERROR;
5081 }
5082 zDb = Tcl_GetString(objv[2]);
5083 if( zDb[0]=='\0' ) zDb = NULL;
5084
5085 rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_CHUNK_SIZE, (void *)&nSize);
5086 if( rc ){
mistachkine84d8d32013-04-29 03:09:10 +00005087 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
dan6e09d692010-07-27 18:34:15 +00005088 return TCL_ERROR;
5089 }
5090 return TCL_OK;
5091}
5092
5093/*
dan661d71a2011-03-30 19:08:03 +00005094** tclcmd: file_control_sizehint_test DB DBNAME SIZE
5095**
drhfdd7f712011-08-13 10:47:51 +00005096** This TCL command runs the sqlite3_file_control interface
5097** with SQLITE_FCNTL_SIZE_HINT
dan661d71a2011-03-30 19:08:03 +00005098*/
5099static int file_control_sizehint_test(
5100 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5101 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5102 int objc, /* Number of arguments */
5103 Tcl_Obj *CONST objv[] /* Command arguments */
5104){
drhb3f787f2012-09-29 14:45:54 +00005105 Tcl_WideInt nSize; /* Hinted size */
dan661d71a2011-03-30 19:08:03 +00005106 char *zDb; /* Db name ("main", "temp" etc.) */
5107 sqlite3 *db; /* Database handle */
5108 int rc; /* file_control() return code */
5109
5110 if( objc!=4 ){
5111 Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
5112 return TCL_ERROR;
5113 }
5114 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
5115 || Tcl_GetWideIntFromObj(interp, objv[3], &nSize)
5116 ){
5117 return TCL_ERROR;
5118 }
5119 zDb = Tcl_GetString(objv[2]);
5120 if( zDb[0]=='\0' ) zDb = NULL;
5121
5122 rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_SIZE_HINT, (void *)&nSize);
5123 if( rc ){
mistachkine84d8d32013-04-29 03:09:10 +00005124 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
dan661d71a2011-03-30 19:08:03 +00005125 return TCL_ERROR;
5126 }
5127 return TCL_OK;
5128}
5129
5130/*
drhad245812010-06-01 00:28:42 +00005131** tclcmd: file_control_lockproxy_test DB PWD
aswiftaebf4132008-11-21 00:10:35 +00005132**
5133** This TCL command runs the sqlite3_file_control interface and
5134** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
5135** SQLITE_SET_LOCKPROXYFILE verbs.
5136*/
5137static int file_control_lockproxy_test(
5138 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5139 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5140 int objc, /* Number of arguments */
5141 Tcl_Obj *CONST objv[] /* Command arguments */
5142){
aswiftaebf4132008-11-21 00:10:35 +00005143 sqlite3 *db;
aswiftaebf4132008-11-21 00:10:35 +00005144
drhad245812010-06-01 00:28:42 +00005145 if( objc!=3 ){
aswiftaebf4132008-11-21 00:10:35 +00005146 Tcl_AppendResult(interp, "wrong # args: should be \"",
drhad245812010-06-01 00:28:42 +00005147 Tcl_GetStringFromObj(objv[0], 0), " DB PWD", 0);
aswiftaebf4132008-11-21 00:10:35 +00005148 return TCL_ERROR;
5149 }
shane9db299f2009-01-30 05:59:10 +00005150 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5151 return TCL_ERROR;
5152 }
aswiftaebf4132008-11-21 00:10:35 +00005153
drh9b35ea62008-11-29 02:20:26 +00005154#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
drhd2cb50b2009-01-09 21:41:17 +00005155# if defined(__APPLE__)
drh9b35ea62008-11-29 02:20:26 +00005156# define SQLITE_ENABLE_LOCKING_STYLE 1
5157# else
5158# define SQLITE_ENABLE_LOCKING_STYLE 0
5159# endif
5160#endif
drhd2cb50b2009-01-09 21:41:17 +00005161#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
drh7708e972008-11-29 00:56:52 +00005162 {
aswiftaebf4132008-11-21 00:10:35 +00005163 char *testPath;
drh103fe742008-12-11 02:56:07 +00005164 int rc;
drhcaffb1a2012-01-30 18:00:31 +00005165 int nPwd;
5166 const char *zPwd;
drhad245812010-06-01 00:28:42 +00005167 char proxyPath[400];
5168
drhcaffb1a2012-01-30 18:00:31 +00005169 zPwd = Tcl_GetStringFromObj(objv[2], &nPwd);
drhad245812010-06-01 00:28:42 +00005170 if( sizeof(proxyPath)<nPwd+20 ){
5171 Tcl_AppendResult(interp, "PWD too big", (void*)0);
5172 return TCL_ERROR;
5173 }
drh65545b52015-01-19 00:35:53 +00005174 sqlite3_snprintf(sizeof(proxyPath), proxyPath, "%s/test.proxy", zPwd);
drh7708e972008-11-29 00:56:52 +00005175 rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
5176 if( rc ){
shane9db299f2009-01-30 05:59:10 +00005177 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5178 return TCL_ERROR;
drh7708e972008-11-29 00:56:52 +00005179 }
aswiftaebf4132008-11-21 00:10:35 +00005180 rc = sqlite3_file_control(db, NULL, SQLITE_GET_LOCKPROXYFILE, &testPath);
shane9db299f2009-01-30 05:59:10 +00005181 if( strncmp(proxyPath,testPath,11) ){
drh7708e972008-11-29 00:56:52 +00005182 Tcl_AppendResult(interp, "Lock proxy file did not match the "
5183 "previously assigned value", 0);
aswiftaebf4132008-11-21 00:10:35 +00005184 return TCL_ERROR;
5185 }
drh7708e972008-11-29 00:56:52 +00005186 if( rc ){
5187 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5188 return TCL_ERROR;
5189 }
5190 rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
5191 if( rc ){
5192 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5193 return TCL_ERROR;
5194 }
aswiftaebf4132008-11-21 00:10:35 +00005195 }
5196#endif
5197 return TCL_OK;
5198}
5199
mistachkin6b98d672014-05-30 16:42:35 +00005200#if SQLITE_OS_WIN
drhd0cdf012011-07-13 16:03:46 +00005201/*
5202** tclcmd: file_control_win32_av_retry DB NRETRY DELAY
5203**
5204** This TCL command runs the sqlite3_file_control interface with
5205** the SQLITE_FCNTL_WIN32_AV_RETRY opcode.
5206*/
5207static int file_control_win32_av_retry(
5208 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5209 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5210 int objc, /* Number of arguments */
5211 Tcl_Obj *CONST objv[] /* Command arguments */
5212){
5213 sqlite3 *db;
5214 int rc;
5215 int a[2];
5216 char z[100];
5217
5218 if( objc!=4 ){
5219 Tcl_AppendResult(interp, "wrong # args: should be \"",
5220 Tcl_GetStringFromObj(objv[0], 0), " DB NRETRY DELAY", 0);
5221 return TCL_ERROR;
5222 }
5223 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5224 return TCL_ERROR;
5225 }
5226 if( Tcl_GetIntFromObj(interp, objv[2], &a[0]) ) return TCL_ERROR;
5227 if( Tcl_GetIntFromObj(interp, objv[3], &a[1]) ) return TCL_ERROR;
5228 rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a);
5229 sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]);
5230 Tcl_AppendResult(interp, z, (char*)0);
5231 return TCL_OK;
5232}
5233
drh253cea52011-07-26 16:23:25 +00005234/*
mistachkin6b98d672014-05-30 16:42:35 +00005235** tclcmd: file_control_win32_set_handle DB HANDLE
5236**
5237** This TCL command runs the sqlite3_file_control interface with
5238** the SQLITE_FCNTL_WIN32_SET_HANDLE opcode.
5239*/
5240static int file_control_win32_set_handle(
5241 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5242 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5243 int objc, /* Number of arguments */
5244 Tcl_Obj *CONST objv[] /* Command arguments */
5245){
5246 sqlite3 *db;
5247 int rc;
5248 HANDLE hFile = NULL;
5249 char z[100];
5250
5251 if( objc!=3 ){
5252 Tcl_AppendResult(interp, "wrong # args: should be \"",
5253 Tcl_GetStringFromObj(objv[0], 0), " DB HANDLE", 0);
5254 return TCL_ERROR;
5255 }
5256 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5257 return TCL_ERROR;
5258 }
5259 if( getWin32Handle(interp, Tcl_GetString(objv[2]), &hFile) ){
5260 return TCL_ERROR;
5261 }
5262 rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_SET_HANDLE,
5263 (void*)&hFile);
5264 sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
5265 Tcl_AppendResult(interp, z, (char*)0);
5266 return TCL_OK;
5267}
5268#endif
5269
5270/*
drh253cea52011-07-26 16:23:25 +00005271** tclcmd: file_control_persist_wal DB PERSIST-FLAG
5272**
5273** This TCL command runs the sqlite3_file_control interface with
5274** the SQLITE_FCNTL_PERSIST_WAL opcode.
5275*/
5276static int file_control_persist_wal(
5277 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5278 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5279 int objc, /* Number of arguments */
5280 Tcl_Obj *CONST objv[] /* Command arguments */
5281){
5282 sqlite3 *db;
5283 int rc;
5284 int bPersist;
5285 char z[100];
5286
5287 if( objc!=3 ){
5288 Tcl_AppendResult(interp, "wrong # args: should be \"",
5289 Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
5290 return TCL_ERROR;
5291 }
5292 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5293 return TCL_ERROR;
5294 }
5295 if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR;
5296 rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist);
5297 sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist);
5298 Tcl_AppendResult(interp, z, (char*)0);
5299 return TCL_OK;
5300}
5301
drhf12b3f62011-12-21 14:42:29 +00005302/*
drhcb15f352011-12-23 01:04:17 +00005303** tclcmd: file_control_powersafe_overwrite DB PSOW-FLAG
drhf12b3f62011-12-21 14:42:29 +00005304**
5305** This TCL command runs the sqlite3_file_control interface with
drhcb15f352011-12-23 01:04:17 +00005306** the SQLITE_FCNTL_POWERSAFE_OVERWRITE opcode.
drhf12b3f62011-12-21 14:42:29 +00005307*/
drhcb15f352011-12-23 01:04:17 +00005308static int file_control_powersafe_overwrite(
drhf12b3f62011-12-21 14:42:29 +00005309 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5310 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5311 int objc, /* Number of arguments */
5312 Tcl_Obj *CONST objv[] /* Command arguments */
5313){
5314 sqlite3 *db;
5315 int rc;
drhcb15f352011-12-23 01:04:17 +00005316 int b;
drhf12b3f62011-12-21 14:42:29 +00005317 char z[100];
5318
5319 if( objc!=3 ){
5320 Tcl_AppendResult(interp, "wrong # args: should be \"",
5321 Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
5322 return TCL_ERROR;
5323 }
5324 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5325 return TCL_ERROR;
5326 }
drhcb15f352011-12-23 01:04:17 +00005327 if( Tcl_GetIntFromObj(interp, objv[2], &b) ) return TCL_ERROR;
5328 rc = sqlite3_file_control(db,NULL,SQLITE_FCNTL_POWERSAFE_OVERWRITE,(void*)&b);
5329 sqlite3_snprintf(sizeof(z), z, "%d %d", rc, b);
drhf12b3f62011-12-21 14:42:29 +00005330 Tcl_AppendResult(interp, z, (char*)0);
5331 return TCL_OK;
5332}
5333
aswiftaebf4132008-11-21 00:10:35 +00005334
5335/*
drhde60fc22011-12-14 17:53:36 +00005336** tclcmd: file_control_vfsname DB ?AUXDB?
5337**
5338** Return a string that describes the stack of VFSes.
5339*/
5340static int file_control_vfsname(
5341 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5342 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5343 int objc, /* Number of arguments */
5344 Tcl_Obj *CONST objv[] /* Command arguments */
5345){
5346 sqlite3 *db;
5347 const char *zDbName = "main";
5348 char *zVfsName = 0;
5349
5350 if( objc!=2 && objc!=3 ){
5351 Tcl_AppendResult(interp, "wrong # args: should be \"",
5352 Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
5353 return TCL_ERROR;
5354 }
5355 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5356 return TCL_ERROR;
5357 }
5358 if( objc==3 ){
5359 zDbName = Tcl_GetString(objv[2]);
5360 }
5361 sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName);
5362 Tcl_AppendResult(interp, zVfsName, (char*)0);
5363 sqlite3_free(zVfsName);
5364 return TCL_OK;
5365}
5366
drh696b33e2012-12-06 19:01:42 +00005367/*
5368** tclcmd: file_control_tempfilename DB ?AUXDB?
5369**
5370** Return a string that is a temporary filename
5371*/
5372static int file_control_tempfilename(
5373 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5374 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5375 int objc, /* Number of arguments */
5376 Tcl_Obj *CONST objv[] /* Command arguments */
5377){
5378 sqlite3 *db;
5379 const char *zDbName = "main";
5380 char *zTName = 0;
5381
5382 if( objc!=2 && objc!=3 ){
5383 Tcl_AppendResult(interp, "wrong # args: should be \"",
5384 Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
5385 return TCL_ERROR;
5386 }
5387 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5388 return TCL_ERROR;
5389 }
5390 if( objc==3 ){
5391 zDbName = Tcl_GetString(objv[2]);
5392 }
5393 sqlite3_file_control(db, zDbName, SQLITE_FCNTL_TEMPFILENAME, (void*)&zTName);
5394 Tcl_AppendResult(interp, zTName, (char*)0);
5395 sqlite3_free(zTName);
5396 return TCL_OK;
5397}
5398
drhde60fc22011-12-14 17:53:36 +00005399
5400/*
danielk1977e339d652008-06-28 11:23:00 +00005401** tclcmd: sqlite3_vfs_list
5402**
5403** Return a tcl list containing the names of all registered vfs's.
5404*/
5405static int vfs_list(
5406 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5407 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5408 int objc, /* Number of arguments */
5409 Tcl_Obj *CONST objv[] /* Command arguments */
5410){
5411 sqlite3_vfs *pVfs;
5412 Tcl_Obj *pRet = Tcl_NewObj();
5413 if( objc!=1 ){
5414 Tcl_WrongNumArgs(interp, 1, objv, "");
5415 return TCL_ERROR;
5416 }
5417 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
5418 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(pVfs->zName, -1));
5419 }
5420 Tcl_SetObjResult(interp, pRet);
5421 return TCL_OK;
5422}
5423
5424/*
drhb1a6c3c2008-03-20 16:30:17 +00005425** tclcmd: sqlite3_limit DB ID VALUE
5426**
5427** This TCL command runs the sqlite3_limit interface and
5428** verifies correct operation of the same.
5429*/
5430static int test_limit(
5431 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5432 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5433 int objc, /* Number of arguments */
5434 Tcl_Obj *CONST objv[] /* Command arguments */
5435){
5436 sqlite3 *db;
5437 int rc;
5438 static const struct {
5439 char *zName;
5440 int id;
5441 } aId[] = {
5442 { "SQLITE_LIMIT_LENGTH", SQLITE_LIMIT_LENGTH },
5443 { "SQLITE_LIMIT_SQL_LENGTH", SQLITE_LIMIT_SQL_LENGTH },
5444 { "SQLITE_LIMIT_COLUMN", SQLITE_LIMIT_COLUMN },
5445 { "SQLITE_LIMIT_EXPR_DEPTH", SQLITE_LIMIT_EXPR_DEPTH },
5446 { "SQLITE_LIMIT_COMPOUND_SELECT", SQLITE_LIMIT_COMPOUND_SELECT },
5447 { "SQLITE_LIMIT_VDBE_OP", SQLITE_LIMIT_VDBE_OP },
5448 { "SQLITE_LIMIT_FUNCTION_ARG", SQLITE_LIMIT_FUNCTION_ARG },
5449 { "SQLITE_LIMIT_ATTACHED", SQLITE_LIMIT_ATTACHED },
5450 { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
5451 { "SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER },
drh417168a2009-09-07 18:14:02 +00005452 { "SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH },
drh3705ef62014-10-08 15:53:21 +00005453 { "SQLITE_LIMIT_WORKER_THREADS", SQLITE_LIMIT_WORKER_THREADS },
drhb092b032015-05-02 18:25:25 +00005454 { "SQLITE_LIMIT_PRINTF_WIDTH", SQLITE_LIMIT_PRINTF_WIDTH },
drh521cc842008-04-15 02:36:33 +00005455
5456 /* Out of range test cases */
5457 { "SQLITE_LIMIT_TOOSMALL", -1, },
drhb092b032015-05-02 18:25:25 +00005458 { "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_PRINTF_WIDTH+1 },
drhb1a6c3c2008-03-20 16:30:17 +00005459 };
mistachkin27b2f052015-01-12 19:49:46 +00005460 int i, id = 0;
drhb1a6c3c2008-03-20 16:30:17 +00005461 int val;
5462 const char *zId;
5463
5464 if( objc!=4 ){
5465 Tcl_AppendResult(interp, "wrong # args: should be \"",
5466 Tcl_GetStringFromObj(objv[0], 0), " DB ID VALUE", 0);
5467 return TCL_ERROR;
5468 }
5469 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
5470 zId = Tcl_GetString(objv[2]);
5471 for(i=0; i<sizeof(aId)/sizeof(aId[0]); i++){
5472 if( strcmp(zId, aId[i].zName)==0 ){
5473 id = aId[i].id;
5474 break;
5475 }
5476 }
5477 if( i>=sizeof(aId)/sizeof(aId[0]) ){
5478 Tcl_AppendResult(interp, "unknown limit type: ", zId, (char*)0);
5479 return TCL_ERROR;
5480 }
5481 if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
5482 rc = sqlite3_limit(db, id, val);
5483 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5484 return TCL_OK;
5485}
5486
5487/*
drh93aed5a2008-01-16 17:46:38 +00005488** tclcmd: save_prng_state
drha2820972008-07-07 13:31:58 +00005489**
5490** Save the state of the pseudo-random number generator.
5491** At the same time, verify that sqlite3_test_control works even when
5492** called with an out-of-range opcode.
drh93aed5a2008-01-16 17:46:38 +00005493*/
5494static int save_prng_state(
5495 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5496 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5497 int objc, /* Number of arguments */
5498 Tcl_Obj *CONST objv[] /* Command arguments */
5499){
drha2820972008-07-07 13:31:58 +00005500 int rc = sqlite3_test_control(9999);
5501 assert( rc==0 );
5502 rc = sqlite3_test_control(-1);
5503 assert( rc==0 );
drh2fa18682008-03-19 14:15:34 +00005504 sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SAVE);
drh93aed5a2008-01-16 17:46:38 +00005505 return TCL_OK;
5506}
5507/*
5508** tclcmd: restore_prng_state
5509*/
5510static int restore_prng_state(
5511 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5512 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5513 int objc, /* Number of arguments */
5514 Tcl_Obj *CONST objv[] /* Command arguments */
5515){
drh2fa18682008-03-19 14:15:34 +00005516 sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESTORE);
drh93aed5a2008-01-16 17:46:38 +00005517 return TCL_OK;
5518}
5519/*
5520** tclcmd: reset_prng_state
5521*/
5522static int reset_prng_state(
5523 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5524 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5525 int objc, /* Number of arguments */
5526 Tcl_Obj *CONST objv[] /* Command arguments */
5527){
drh2fa18682008-03-19 14:15:34 +00005528 sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESET);
drh93aed5a2008-01-16 17:46:38 +00005529 return TCL_OK;
5530}
5531
danielk1977062d4cb2008-08-29 09:10:02 +00005532/*
drh09fe6142013-11-29 15:06:27 +00005533** tclcmd: database_may_be_corrupt
5534**
5535** Indicate that database files might be corrupt. In other words, set the normal
5536** state of operation.
5537*/
5538static int database_may_be_corrupt(
5539 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5540 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5541 int objc, /* Number of arguments */
5542 Tcl_Obj *CONST objv[] /* Command arguments */
5543){
5544 sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 0);
5545 return TCL_OK;
5546}
5547/*
5548** tclcmd: database_never_corrupt
5549**
5550** Indicate that database files are always well-formed. This enables extra assert()
5551** statements that test conditions that are always true for well-formed databases.
5552*/
5553static int database_never_corrupt(
5554 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5555 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5556 int objc, /* Number of arguments */
5557 Tcl_Obj *CONST objv[] /* Command arguments */
5558){
5559 sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 1);
5560 return TCL_OK;
5561}
5562
5563/*
danielk1977062d4cb2008-08-29 09:10:02 +00005564** tclcmd: pcache_stats
5565*/
5566static int test_pcache_stats(
5567 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5568 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5569 int objc, /* Number of arguments */
5570 Tcl_Obj *CONST objv[] /* Command arguments */
5571){
5572 int nMin;
5573 int nMax;
5574 int nCurrent;
5575 int nRecyclable;
5576 Tcl_Obj *pRet;
5577
5578 sqlite3PcacheStats(&nCurrent, &nMax, &nMin, &nRecyclable);
5579
5580 pRet = Tcl_NewObj();
5581 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("current", -1));
5582 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCurrent));
5583 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("max", -1));
5584 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMax));
5585 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("min", -1));
5586 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMin));
5587 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("recyclable", -1));
5588 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nRecyclable));
5589
5590 Tcl_SetObjResult(interp, pRet);
5591
5592 return TCL_OK;
5593}
5594
drh69910da2009-03-27 12:32:54 +00005595#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
danielk1977404ca072009-03-16 13:19:36 +00005596static void test_unlock_notify_cb(void **aArg, int nArg){
5597 int ii;
5598 for(ii=0; ii<nArg; ii++){
5599 Tcl_EvalEx((Tcl_Interp *)aArg[ii], "unlock_notify", -1, TCL_EVAL_GLOBAL);
5600 }
5601}
drh69910da2009-03-27 12:32:54 +00005602#endif /* SQLITE_ENABLE_UNLOCK_NOTIFY */
danielk1977404ca072009-03-16 13:19:36 +00005603
5604/*
5605** tclcmd: sqlite3_unlock_notify db
5606*/
5607#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
5608static int test_unlock_notify(
5609 ClientData clientData, /* Unused */
5610 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5611 int objc, /* Number of arguments */
5612 Tcl_Obj *CONST objv[] /* Command arguments */
5613){
5614 sqlite3 *db;
5615 int rc;
5616
5617 if( objc!=2 ){
5618 Tcl_WrongNumArgs(interp, 1, objv, "DB");
5619 return TCL_ERROR;
5620 }
5621
5622 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5623 return TCL_ERROR;
5624 }
5625 rc = sqlite3_unlock_notify(db, test_unlock_notify_cb, (void *)interp);
5626 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
5627 return TCL_OK;
5628}
5629#endif
5630
dan87c1fe12010-05-03 12:14:15 +00005631/*
5632** tclcmd: sqlite3_wal_checkpoint db ?NAME?
5633*/
5634static int test_wal_checkpoint(
5635 ClientData clientData, /* Unused */
5636 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5637 int objc, /* Number of arguments */
5638 Tcl_Obj *CONST objv[] /* Command arguments */
5639){
5640 char *zDb = 0;
5641 sqlite3 *db;
5642 int rc;
5643
5644 if( objc!=3 && objc!=2 ){
5645 Tcl_WrongNumArgs(interp, 1, objv, "DB ?NAME?");
5646 return TCL_ERROR;
5647 }
5648
5649 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5650 return TCL_ERROR;
5651 }
5652 if( objc==3 ){
5653 zDb = Tcl_GetString(objv[2]);
5654 }
5655 rc = sqlite3_wal_checkpoint(db, zDb);
5656 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
5657 return TCL_OK;
5658}
5659
daneb8763d2010-08-17 14:52:22 +00005660/*
dan9c5e3682011-02-07 15:12:12 +00005661** tclcmd: sqlite3_wal_checkpoint_v2 db MODE ?NAME?
5662**
5663** This command calls the wal_checkpoint_v2() function with the specified
5664** mode argument (passive, full or restart). If present, the database name
5665** NAME is passed as the second argument to wal_checkpoint_v2(). If it the
5666** NAME argument is not present, a NULL pointer is passed instead.
5667**
5668** If wal_checkpoint_v2() returns any value other than SQLITE_BUSY or
5669** SQLITE_OK, then this command returns TCL_ERROR. The Tcl result is set
5670** to the error message obtained from sqlite3_errmsg().
5671**
5672** Otherwise, this command returns a list of three integers. The first integer
5673** is 1 if SQLITE_BUSY was returned, or 0 otherwise. The following two integers
drhf7b54962013-05-28 12:11:54 +00005674** are the values returned via the output parameters by wal_checkpoint_v2() -
dan9c5e3682011-02-07 15:12:12 +00005675** the number of frames in the log and the number of frames in the log
5676** that have been checkpointed.
5677*/
5678static int test_wal_checkpoint_v2(
5679 ClientData clientData, /* Unused */
5680 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5681 int objc, /* Number of arguments */
5682 Tcl_Obj *CONST objv[] /* Command arguments */
5683){
5684 char *zDb = 0;
5685 sqlite3 *db;
5686 int rc;
5687
5688 int eMode;
5689 int nLog = -555;
5690 int nCkpt = -555;
5691 Tcl_Obj *pRet;
5692
danf26a1542014-12-02 19:04:54 +00005693 const char * aMode[] = { "passive", "full", "restart", "truncate", 0 };
dan9c5e3682011-02-07 15:12:12 +00005694 assert( SQLITE_CHECKPOINT_PASSIVE==0 );
5695 assert( SQLITE_CHECKPOINT_FULL==1 );
5696 assert( SQLITE_CHECKPOINT_RESTART==2 );
danf26a1542014-12-02 19:04:54 +00005697 assert( SQLITE_CHECKPOINT_TRUNCATE==3 );
dan9c5e3682011-02-07 15:12:12 +00005698
5699 if( objc!=3 && objc!=4 ){
5700 Tcl_WrongNumArgs(interp, 1, objv, "DB MODE ?NAME?");
5701 return TCL_ERROR;
5702 }
5703
5704 if( objc==4 ){
5705 zDb = Tcl_GetString(objv[3]);
5706 }
dan2928d322014-12-05 20:46:19 +00005707 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) || (
5708 TCL_OK!=Tcl_GetIntFromObj(0, objv[2], &eMode)
5709 && TCL_OK!=Tcl_GetIndexFromObj(interp, objv[2], aMode, "mode", 0, &eMode)
5710 )){
dan9c5e3682011-02-07 15:12:12 +00005711 return TCL_ERROR;
5712 }
5713
5714 rc = sqlite3_wal_checkpoint_v2(db, zDb, eMode, &nLog, &nCkpt);
5715 if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
dan2928d322014-12-05 20:46:19 +00005716 const char *zErrCode = sqlite3ErrName(rc);
dan9778bd72014-12-09 20:13:40 +00005717 Tcl_ResetResult(interp);
dan2928d322014-12-05 20:46:19 +00005718 Tcl_AppendResult(interp, zErrCode, " - ", (char *)sqlite3_errmsg(db), 0);
dan9c5e3682011-02-07 15:12:12 +00005719 return TCL_ERROR;
5720 }
5721
5722 pRet = Tcl_NewObj();
5723 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(rc==SQLITE_BUSY?1:0));
5724 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nLog));
5725 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCkpt));
5726 Tcl_SetObjResult(interp, pRet);
5727
5728 return TCL_OK;
5729}
5730
5731/*
dan9af10622014-12-15 16:27:12 +00005732** tclcmd: sqlite3_wal_autocheckpoint db VALUE
5733*/
5734static int test_wal_autocheckpoint(
5735 ClientData clientData, /* Unused */
5736 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5737 int objc, /* Number of arguments */
5738 Tcl_Obj *CONST objv[] /* Command arguments */
5739){
5740 sqlite3 *db;
5741 int rc;
5742 int iVal;
5743
5744
5745 if( objc!=3 ){
5746 Tcl_WrongNumArgs(interp, 1, objv, "DB VALUE");
5747 return TCL_ERROR;
5748 }
5749
5750 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
5751 || Tcl_GetIntFromObj(0, objv[2], &iVal)
5752 ){
5753 return TCL_ERROR;
5754 }
5755
5756 rc = sqlite3_wal_autocheckpoint(db, iVal);
5757 Tcl_ResetResult(interp);
5758 if( rc!=SQLITE_OK ){
5759 const char *zErrCode = sqlite3ErrName(rc);
5760 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErrCode, -1));
5761 return TCL_ERROR;
5762 }
5763
5764 return TCL_OK;
5765}
5766
5767
5768/*
daneb8763d2010-08-17 14:52:22 +00005769** tclcmd: test_sqlite3_log ?SCRIPT?
5770*/
5771static struct LogCallback {
5772 Tcl_Interp *pInterp;
5773 Tcl_Obj *pObj;
5774} logcallback = {0, 0};
5775static void xLogcallback(void *unused, int err, char *zMsg){
5776 Tcl_Obj *pNew = Tcl_DuplicateObj(logcallback.pObj);
5777 Tcl_IncrRefCount(pNew);
5778 Tcl_ListObjAppendElement(
mistachkine84d8d32013-04-29 03:09:10 +00005779 0, pNew, Tcl_NewStringObj(sqlite3ErrName(err), -1)
daneb8763d2010-08-17 14:52:22 +00005780 );
5781 Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zMsg, -1));
5782 Tcl_EvalObjEx(logcallback.pInterp, pNew, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
5783 Tcl_DecrRefCount(pNew);
5784}
5785static int test_sqlite3_log(
5786 ClientData clientData,
5787 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5788 int objc, /* Number of arguments */
5789 Tcl_Obj *CONST objv[] /* Command arguments */
5790){
5791 if( objc>2 ){
5792 Tcl_WrongNumArgs(interp, 1, objv, "SCRIPT");
5793 return TCL_ERROR;
5794 }
5795 if( logcallback.pObj ){
5796 Tcl_DecrRefCount(logcallback.pObj);
5797 logcallback.pObj = 0;
5798 logcallback.pInterp = 0;
5799 sqlite3_config(SQLITE_CONFIG_LOG, 0, 0);
5800 }
5801 if( objc>1 ){
5802 logcallback.pObj = objv[1];
5803 Tcl_IncrRefCount(logcallback.pObj);
5804 logcallback.pInterp = interp;
5805 sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, 0);
5806 }
5807 return TCL_OK;
5808}
drh9bc54492007-10-23 14:49:59 +00005809
5810/*
drha2c8a952009-10-13 18:38:34 +00005811** tcl_objproc COMMANDNAME ARGS...
5812**
5813** Run a TCL command using its objProc interface. Throw an error if
5814** the command has no objProc interface.
5815*/
5816static int runAsObjProc(
5817 void * clientData,
5818 Tcl_Interp *interp,
5819 int objc,
5820 Tcl_Obj *CONST objv[]
5821){
5822 Tcl_CmdInfo cmdInfo;
5823 if( objc<2 ){
5824 Tcl_WrongNumArgs(interp, 1, objv, "COMMAND ...");
5825 return TCL_ERROR;
5826 }
5827 if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
5828 Tcl_AppendResult(interp, "command not found: ",
5829 Tcl_GetString(objv[1]), (char*)0);
5830 return TCL_ERROR;
5831 }
5832 if( cmdInfo.objProc==0 ){
5833 Tcl_AppendResult(interp, "command has no objProc: ",
5834 Tcl_GetString(objv[1]), (char*)0);
5835 return TCL_ERROR;
5836 }
5837 return cmdInfo.objProc(cmdInfo.objClientData, interp, objc-1, objv+1);
5838}
5839
dan91da6b82010-11-15 14:51:33 +00005840#ifndef SQLITE_OMIT_EXPLAIN
5841/*
5842** WARNING: The following function, printExplainQueryPlan() is an exact
5843** copy of example code from eqp.in (eqp.html). If this code is modified,
5844** then the documentation copy needs to be modified as well.
5845*/
5846/*
5847** Argument pStmt is a prepared SQL statement. This function compiles
5848** an EXPLAIN QUERY PLAN command to report on the prepared statement,
5849** and prints the report to stdout using printf().
5850*/
5851int printExplainQueryPlan(sqlite3_stmt *pStmt){
5852 const char *zSql; /* Input SQL */
5853 char *zExplain; /* SQL with EXPLAIN QUERY PLAN prepended */
5854 sqlite3_stmt *pExplain; /* Compiled EXPLAIN QUERY PLAN command */
5855 int rc; /* Return code from sqlite3_prepare_v2() */
5856
5857 zSql = sqlite3_sql(pStmt);
5858 if( zSql==0 ) return SQLITE_ERROR;
5859
5860 zExplain = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zSql);
5861 if( zExplain==0 ) return SQLITE_NOMEM;
5862
5863 rc = sqlite3_prepare_v2(sqlite3_db_handle(pStmt), zExplain, -1, &pExplain, 0);
5864 sqlite3_free(zExplain);
5865 if( rc!=SQLITE_OK ) return rc;
5866
5867 while( SQLITE_ROW==sqlite3_step(pExplain) ){
5868 int iSelectid = sqlite3_column_int(pExplain, 0);
5869 int iOrder = sqlite3_column_int(pExplain, 1);
5870 int iFrom = sqlite3_column_int(pExplain, 2);
5871 const char *zDetail = (const char *)sqlite3_column_text(pExplain, 3);
5872
5873 printf("%d %d %d %s\n", iSelectid, iOrder, iFrom, zDetail);
5874 }
5875
5876 return sqlite3_finalize(pExplain);
5877}
5878
5879static int test_print_eqp(
5880 void * clientData,
5881 Tcl_Interp *interp,
5882 int objc,
5883 Tcl_Obj *CONST objv[]
5884){
5885 int rc;
5886 sqlite3_stmt *pStmt;
5887
5888 if( objc!=2 ){
5889 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
5890 return TCL_ERROR;
5891 }
5892 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
5893 rc = printExplainQueryPlan(pStmt);
shaneh7c5d8fb2011-06-22 14:21:31 +00005894 /* This is needed on Windows so that a test case using this
5895 ** function can open a read pipe and get the output of
5896 ** printExplainQueryPlan() immediately.
5897 */
5898 fflush(stdout);
dan91da6b82010-11-15 14:51:33 +00005899 Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
5900 return TCL_OK;
5901}
5902#endif /* SQLITE_OMIT_EXPLAIN */
drha2c8a952009-10-13 18:38:34 +00005903
5904/*
danc17d6962011-06-21 12:47:30 +00005905** sqlite3_test_control VERB ARGS...
5906*/
5907static int test_test_control(
5908 void * clientData,
5909 Tcl_Interp *interp,
5910 int objc,
5911 Tcl_Obj *CONST objv[]
5912){
5913 struct Verb {
5914 const char *zName;
5915 int i;
5916 } aVerb[] = {
5917 { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
drh917682a2015-01-30 15:40:15 +00005918 { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP },
drh1ffede82015-01-30 20:59:27 +00005919 { "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER },
danc17d6962011-06-21 12:47:30 +00005920 };
5921 int iVerb;
5922 int iFlag;
5923 int rc;
5924
5925 if( objc<2 ){
5926 Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS...");
5927 return TCL_ERROR;
5928 }
5929
5930 rc = Tcl_GetIndexFromObjStruct(
5931 interp, objv[1], aVerb, sizeof(aVerb[0]), "VERB", 0, &iVerb
5932 );
5933 if( rc!=TCL_OK ) return rc;
5934
5935 iFlag = aVerb[iVerb].i;
5936 switch( iFlag ){
5937 case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
5938 int val;
5939 if( objc!=3 ){
5940 Tcl_WrongNumArgs(interp, 2, objv, "ONOFF");
5941 return TCL_ERROR;
5942 }
5943 if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
5944 sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val);
5945 break;
5946 }
dan8930c2a2014-04-03 16:25:29 +00005947
5948 case SQLITE_TESTCTRL_SORTER_MMAP: {
5949 int val;
5950 sqlite3 *db;
5951 if( objc!=4 ){
5952 Tcl_WrongNumArgs(interp, 2, objv, "DB LIMIT");
5953 return TCL_ERROR;
5954 }
5955 if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
5956 if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
5957 sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, val);
5958 break;
5959 }
drh917682a2015-01-30 15:40:15 +00005960
drh1ffede82015-01-30 20:59:27 +00005961 case SQLITE_TESTCTRL_IMPOSTER: {
5962 int onOff, tnum;
5963 const char *zDbName;
drh917682a2015-01-30 15:40:15 +00005964 sqlite3 *db;
5965 if( objc!=6 ){
drh1ffede82015-01-30 20:59:27 +00005966 Tcl_WrongNumArgs(interp, 2, objv, "DB dbName onOff tnum");
drh917682a2015-01-30 15:40:15 +00005967 return TCL_ERROR;
5968 }
5969 if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
drh1ffede82015-01-30 20:59:27 +00005970 zDbName = Tcl_GetString(objv[3]);
5971 if( Tcl_GetIntFromObj(interp, objv[4], &onOff) ) return TCL_ERROR;
5972 if( Tcl_GetIntFromObj(interp, objv[5], &tnum) ) return TCL_ERROR;
5973 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zDbName, onOff, tnum);
drh917682a2015-01-30 15:40:15 +00005974 break;
5975 }
danc17d6962011-06-21 12:47:30 +00005976 }
5977
5978 Tcl_ResetResult(interp);
5979 return TCL_OK;
5980}
5981
mistachkindaf9a5a2013-03-23 09:56:39 +00005982#if SQLITE_OS_UNIX
dana72014f2013-03-16 20:19:21 +00005983#include <sys/time.h>
5984#include <sys/resource.h>
5985
5986static int test_getrusage(
5987 void * clientData,
5988 Tcl_Interp *interp,
5989 int objc,
5990 Tcl_Obj *CONST objv[]
5991){
5992 char buf[1024];
5993 struct rusage r;
5994 memset(&r, 0, sizeof(r));
5995 getrusage(RUSAGE_SELF, &r);
5996
drh65545b52015-01-19 00:35:53 +00005997 sqlite3_snprintf(sizeof(buf), buf,
5998 "ru_utime=%d.%06d ru_stime=%d.%06d ru_minflt=%d ru_majflt=%d",
dan5d8a1372013-03-19 19:28:06 +00005999 (int)r.ru_utime.tv_sec, (int)r.ru_utime.tv_usec,
6000 (int)r.ru_stime.tv_sec, (int)r.ru_stime.tv_usec,
6001 (int)r.ru_minflt, (int)r.ru_majflt
dana72014f2013-03-16 20:19:21 +00006002 );
6003 Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
6004 return TCL_OK;
6005}
mistachkindaf9a5a2013-03-23 09:56:39 +00006006#endif
dana72014f2013-03-16 20:19:21 +00006007
drh80084ca2011-07-11 23:45:44 +00006008#if SQLITE_OS_WIN
6009/*
6010** Information passed from the main thread into the windows file locker
6011** background thread.
6012*/
6013struct win32FileLocker {
mistachkin176f1b42011-08-02 23:34:00 +00006014 char *evName; /* Name of event to signal thread startup */
drh80084ca2011-07-11 23:45:44 +00006015 HANDLE h; /* Handle of the file to be locked */
6016 int delay1; /* Delay before locking */
6017 int delay2; /* Delay before unlocking */
6018 int ok; /* Finished ok */
6019 int err; /* True if an error occurs */
6020};
6021#endif
6022
6023
6024#if SQLITE_OS_WIN
drh7da5fcb2012-03-30 14:59:43 +00006025#include <process.h>
drh80084ca2011-07-11 23:45:44 +00006026/*
6027** The background thread that does file locking.
6028*/
6029static void win32_file_locker(void *pAppData){
6030 struct win32FileLocker *p = (struct win32FileLocker*)pAppData;
mistachkin176f1b42011-08-02 23:34:00 +00006031 if( p->evName ){
6032 HANDLE ev = OpenEvent(EVENT_MODIFY_STATE, FALSE, p->evName);
6033 if ( ev ){
6034 SetEvent(ev);
6035 CloseHandle(ev);
6036 }
6037 }
drh80084ca2011-07-11 23:45:44 +00006038 if( p->delay1 ) Sleep(p->delay1);
6039 if( LockFile(p->h, 0, 0, 100000000, 0) ){
6040 Sleep(p->delay2);
6041 UnlockFile(p->h, 0, 0, 100000000, 0);
6042 p->ok = 1;
6043 }else{
6044 p->err = 1;
6045 }
6046 CloseHandle(p->h);
6047 p->h = 0;
6048 p->delay1 = 0;
6049 p->delay2 = 0;
6050}
6051#endif
6052
6053#if SQLITE_OS_WIN
6054/*
6055** lock_win32_file FILENAME DELAY1 DELAY2
6056**
6057** Get an exclusive manditory lock on file for DELAY2 milliseconds.
6058** Wait DELAY1 milliseconds before acquiring the lock.
6059*/
6060static int win32_file_lock(
6061 void * clientData,
6062 Tcl_Interp *interp,
6063 int objc,
6064 Tcl_Obj *CONST objv[]
6065){
mistachkin176f1b42011-08-02 23:34:00 +00006066 static struct win32FileLocker x = { "win32_file_lock", 0, 0, 0, 0, 0 };
drh80084ca2011-07-11 23:45:44 +00006067 const char *zFilename;
mistachkin176f1b42011-08-02 23:34:00 +00006068 char zBuf[200];
drh80084ca2011-07-11 23:45:44 +00006069 int retry = 0;
mistachkin176f1b42011-08-02 23:34:00 +00006070 HANDLE ev;
6071 DWORD wResult;
drh80084ca2011-07-11 23:45:44 +00006072
6073 if( objc!=4 && objc!=1 ){
6074 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2");
6075 return TCL_ERROR;
6076 }
6077 if( objc==1 ){
drh80084ca2011-07-11 23:45:44 +00006078 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d",
6079 x.ok, x.err, x.delay1, x.delay2, x.h);
6080 Tcl_AppendResult(interp, zBuf, (char*)0);
6081 return TCL_OK;
6082 }
drhd0cdf012011-07-13 16:03:46 +00006083 while( x.h && retry<30 ){
drh80084ca2011-07-11 23:45:44 +00006084 retry++;
6085 Sleep(100);
6086 }
6087 if( x.h ){
6088 Tcl_AppendResult(interp, "busy", (char*)0);
6089 return TCL_ERROR;
6090 }
6091 if( Tcl_GetIntFromObj(interp, objv[2], &x.delay1) ) return TCL_ERROR;
6092 if( Tcl_GetIntFromObj(interp, objv[3], &x.delay2) ) return TCL_ERROR;
6093 zFilename = Tcl_GetString(objv[1]);
6094 x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE,
6095 FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
6096 FILE_ATTRIBUTE_NORMAL, 0);
6097 if( !x.h ){
6098 Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0);
6099 return TCL_ERROR;
6100 }
mistachkin176f1b42011-08-02 23:34:00 +00006101 ev = CreateEvent(NULL, TRUE, FALSE, x.evName);
6102 if ( !ev ){
6103 Tcl_AppendResult(interp, "cannot create event: ", x.evName, (char*)0);
6104 return TCL_ERROR;
6105 }
drh80084ca2011-07-11 23:45:44 +00006106 _beginthread(win32_file_locker, 0, (void*)&x);
6107 Sleep(0);
mistachkin176f1b42011-08-02 23:34:00 +00006108 if ( (wResult = WaitForSingleObject(ev, 10000))!=WAIT_OBJECT_0 ){
6109 sqlite3_snprintf(sizeof(zBuf), zBuf, "0x%x", wResult);
6110 Tcl_AppendResult(interp, "wait failed: ", zBuf, (char*)0);
6111 CloseHandle(ev);
6112 return TCL_ERROR;
6113 }
6114 CloseHandle(ev);
drh80084ca2011-07-11 23:45:44 +00006115 return TCL_OK;
6116}
mistachkin37418272013-08-28 05:49:39 +00006117
6118/*
6119** exists_win32_path PATH
6120**
6121** Returns non-zero if the specified path exists, whose fully qualified name
mistachkin3259fe72013-08-28 17:59:38 +00006122** may exceed 260 characters if it is prefixed with "\\?\".
mistachkin37418272013-08-28 05:49:39 +00006123*/
6124static int win32_exists_path(
6125 void *clientData,
6126 Tcl_Interp *interp,
6127 int objc,
6128 Tcl_Obj *CONST objv[]
6129){
6130 if( objc!=2 ){
6131 Tcl_WrongNumArgs(interp, 1, objv, "PATH");
6132 return TCL_ERROR;
6133 }
6134 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
6135 GetFileAttributesW( Tcl_GetUnicode(objv[1]))!=INVALID_FILE_ATTRIBUTES ));
6136 return TCL_OK;
6137}
6138
6139/*
6140** find_win32_file PATTERN
6141**
6142** Returns a list of entries in a directory that match the specified pattern,
6143** whose fully qualified name may exceed 248 characters if it is prefixed with
6144** "\\?\".
6145*/
6146static int win32_find_file(
6147 void *clientData,
6148 Tcl_Interp *interp,
6149 int objc,
6150 Tcl_Obj *CONST objv[]
6151){
6152 HANDLE hFindFile = INVALID_HANDLE_VALUE;
6153 WIN32_FIND_DATAW findData;
6154 Tcl_Obj *listObj;
6155 DWORD lastErrno;
6156 if( objc!=2 ){
6157 Tcl_WrongNumArgs(interp, 1, objv, "PATTERN");
6158 return TCL_ERROR;
6159 }
6160 hFindFile = FindFirstFileW(Tcl_GetUnicode(objv[1]), &findData);
6161 if( hFindFile==INVALID_HANDLE_VALUE ){
6162 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
6163 return TCL_ERROR;
6164 }
6165 listObj = Tcl_NewObj();
6166 Tcl_IncrRefCount(listObj);
6167 do {
6168 Tcl_ListObjAppendElement(interp, listObj, Tcl_NewUnicodeObj(
6169 findData.cFileName, -1));
6170 Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(
6171 findData.dwFileAttributes));
6172 } while( FindNextFileW(hFindFile, &findData) );
6173 lastErrno = GetLastError();
6174 if( lastErrno!=NO_ERROR && lastErrno!=ERROR_NO_MORE_FILES ){
6175 FindClose(hFindFile);
6176 Tcl_DecrRefCount(listObj);
6177 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
6178 return TCL_ERROR;
6179 }
6180 FindClose(hFindFile);
6181 Tcl_SetObjResult(interp, listObj);
6182 return TCL_OK;
6183}
6184
6185/*
6186** delete_win32_file FILENAME
6187**
mistachkin3259fe72013-08-28 17:59:38 +00006188** Deletes the specified file, whose fully qualified name may exceed 260
mistachkin37418272013-08-28 05:49:39 +00006189** characters if it is prefixed with "\\?\".
6190*/
6191static int win32_delete_file(
6192 void *clientData,
6193 Tcl_Interp *interp,
6194 int objc,
6195 Tcl_Obj *CONST objv[]
6196){
6197 if( objc!=2 ){
6198 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
6199 return TCL_ERROR;
6200 }
6201 if( !DeleteFileW(Tcl_GetUnicode(objv[1])) ){
6202 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
6203 return TCL_ERROR;
6204 }
6205 Tcl_ResetResult(interp);
6206 return TCL_OK;
6207}
6208
6209/*
6210** make_win32_dir DIRECTORY
6211**
6212** Creates the specified directory, whose fully qualified name may exceed 248
6213** characters if it is prefixed with "\\?\".
6214*/
6215static int win32_mkdir(
6216 void *clientData,
6217 Tcl_Interp *interp,
6218 int objc,
6219 Tcl_Obj *CONST objv[]
6220){
6221 if( objc!=2 ){
6222 Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY");
6223 return TCL_ERROR;
6224 }
6225 if( !CreateDirectoryW(Tcl_GetUnicode(objv[1]), NULL) ){
6226 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
6227 return TCL_ERROR;
6228 }
6229 Tcl_ResetResult(interp);
6230 return TCL_OK;
6231}
6232
6233/*
6234** remove_win32_dir DIRECTORY
6235**
6236** Removes the specified directory, whose fully qualified name may exceed 248
6237** characters if it is prefixed with "\\?\".
6238*/
6239static int win32_rmdir(
6240 void *clientData,
6241 Tcl_Interp *interp,
6242 int objc,
6243 Tcl_Obj *CONST objv[]
6244){
6245 if( objc!=2 ){
6246 Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY");
6247 return TCL_ERROR;
6248 }
6249 if( !RemoveDirectoryW(Tcl_GetUnicode(objv[1])) ){
6250 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
6251 return TCL_ERROR;
6252 }
6253 Tcl_ResetResult(interp);
6254 return TCL_OK;
6255}
drh80084ca2011-07-11 23:45:44 +00006256#endif
danc17d6962011-06-21 12:47:30 +00006257
drhd0cdf012011-07-13 16:03:46 +00006258
danc17d6962011-06-21 12:47:30 +00006259/*
drhf58ee7f2010-12-06 21:06:09 +00006260** optimization_control DB OPT BOOLEAN
6261**
6262** Enable or disable query optimizations using the sqlite3_test_control()
6263** interface. Disable if BOOLEAN is false and enable if BOOLEAN is true.
6264** OPT is the name of the optimization to be disabled.
6265*/
6266static int optimization_control(
6267 void * clientData,
6268 Tcl_Interp *interp,
6269 int objc,
6270 Tcl_Obj *CONST objv[]
6271){
6272 int i;
6273 sqlite3 *db;
6274 const char *zOpt;
6275 int onoff;
drhfc30b042012-08-20 16:08:29 +00006276 int mask = 0;
drhf58ee7f2010-12-06 21:06:09 +00006277 static const struct {
6278 const char *zOptName;
6279 int mask;
6280 } aOpt[] = {
drh9d5a5792013-06-28 13:43:33 +00006281 { "all", SQLITE_AllOpts },
6282 { "none", 0 },
6283 { "query-flattener", SQLITE_QueryFlattener },
6284 { "column-cache", SQLITE_ColumnCache },
6285 { "groupby-order", SQLITE_GroupByOrder },
6286 { "factor-constants", SQLITE_FactorOutConst },
drh9d5a5792013-06-28 13:43:33 +00006287 { "distinct-opt", SQLITE_DistinctOpt },
6288 { "cover-idx-scan", SQLITE_CoverIdxScan },
6289 { "order-by-idx-join", SQLITE_OrderByIdxJoin },
6290 { "transitive", SQLITE_Transitive },
6291 { "subquery-coroutine", SQLITE_SubqCoroutine },
6292 { "omit-noop-join", SQLITE_OmitNoopJoin },
drhd7d71472014-10-22 19:57:16 +00006293 { "stat3", SQLITE_Stat34 },
6294 { "stat4", SQLITE_Stat34 },
drhf58ee7f2010-12-06 21:06:09 +00006295 };
6296
6297 if( objc!=4 ){
6298 Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN");
6299 return TCL_ERROR;
6300 }
6301 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
6302 if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR;
6303 zOpt = Tcl_GetString(objv[2]);
6304 for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
6305 if( strcmp(zOpt, aOpt[i].zOptName)==0 ){
6306 mask = aOpt[i].mask;
6307 break;
6308 }
6309 }
6310 if( onoff ) mask = ~mask;
6311 if( i>=sizeof(aOpt)/sizeof(aOpt[0]) ){
6312 Tcl_AppendResult(interp, "unknown optimization - should be one of:",
6313 (char*)0);
6314 for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
drh9d5a5792013-06-28 13:43:33 +00006315 Tcl_AppendResult(interp, " ", aOpt[i].zOptName, (char*)0);
drhf58ee7f2010-12-06 21:06:09 +00006316 }
6317 return TCL_ERROR;
6318 }
6319 sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask);
6320 return TCL_OK;
6321}
6322
drh248f2be2013-04-23 20:10:13 +00006323typedef struct sqlite3_api_routines sqlite3_api_routines;
6324/*
drhea41dc42013-04-25 19:31:33 +00006325** load_static_extension DB NAME ...
drh248f2be2013-04-23 20:10:13 +00006326**
drhea41dc42013-04-25 19:31:33 +00006327** Load one or more statically linked extensions.
drh248f2be2013-04-23 20:10:13 +00006328*/
6329static int tclLoadStaticExtensionCmd(
6330 void * clientData,
6331 Tcl_Interp *interp,
6332 int objc,
6333 Tcl_Obj *CONST objv[]
6334){
drh8416fc72013-04-25 16:42:55 +00006335 extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*);
6336 extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
drh1728bcb2014-11-10 16:49:56 +00006337 extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*);
drh51ed2982014-06-16 12:44:32 +00006338 extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
drhe50db1c2013-04-25 14:31:46 +00006339 extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
drh8416fc72013-04-25 16:42:55 +00006340 extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
drhea41dc42013-04-25 19:31:33 +00006341 extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*);
drhdef33672013-05-28 20:25:54 +00006342 extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
drh248f2be2013-04-23 20:10:13 +00006343 extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*);
drhb7045ab2013-04-25 14:59:01 +00006344 extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*);
drh5f8cdac2013-10-14 21:14:42 +00006345 extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*);
drh24b64222013-04-25 11:58:36 +00006346 extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*);
drh248f2be2013-04-23 20:10:13 +00006347 static const struct {
6348 const char *zExtName;
6349 int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*);
6350 } aExtension[] = {
drh8416fc72013-04-25 16:42:55 +00006351 { "amatch", sqlite3_amatch_init },
6352 { "closure", sqlite3_closure_init },
drh1728bcb2014-11-10 16:49:56 +00006353 { "eval", sqlite3_eval_init },
drh51ed2982014-06-16 12:44:32 +00006354 { "fileio", sqlite3_fileio_init },
drhe50db1c2013-04-25 14:31:46 +00006355 { "fuzzer", sqlite3_fuzzer_init },
drh8416fc72013-04-25 16:42:55 +00006356 { "ieee754", sqlite3_ieee_init },
drhea41dc42013-04-25 19:31:33 +00006357 { "nextchar", sqlite3_nextchar_init },
drhdef33672013-05-28 20:25:54 +00006358 { "percentile", sqlite3_percentile_init },
drh24b64222013-04-25 11:58:36 +00006359 { "regexp", sqlite3_regexp_init },
drhb7045ab2013-04-25 14:59:01 +00006360 { "spellfix", sqlite3_spellfix_init },
drh5f8cdac2013-10-14 21:14:42 +00006361 { "totype", sqlite3_totype_init },
drh24b64222013-04-25 11:58:36 +00006362 { "wholenumber", sqlite3_wholenumber_init },
drh248f2be2013-04-23 20:10:13 +00006363 };
6364 sqlite3 *db;
6365 const char *zName;
drhea41dc42013-04-25 19:31:33 +00006366 int i, j, rc;
drh248f2be2013-04-23 20:10:13 +00006367 char *zErrMsg = 0;
drhea41dc42013-04-25 19:31:33 +00006368 if( objc<3 ){
6369 Tcl_WrongNumArgs(interp, 1, objv, "DB NAME ...");
drh248f2be2013-04-23 20:10:13 +00006370 return TCL_ERROR;
6371 }
6372 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
drhea41dc42013-04-25 19:31:33 +00006373 for(j=2; j<objc; j++){
6374 zName = Tcl_GetString(objv[j]);
6375 for(i=0; i<ArraySize(aExtension); i++){
6376 if( strcmp(zName, aExtension[i].zExtName)==0 ) break;
6377 }
6378 if( i>=ArraySize(aExtension) ){
6379 Tcl_AppendResult(interp, "no such extension: ", zName, (char*)0);
6380 return TCL_ERROR;
6381 }
6382 rc = aExtension[i].pInit(db, &zErrMsg, 0);
6383 if( rc!=SQLITE_OK || zErrMsg ){
6384 Tcl_AppendResult(interp, "initialization of ", zName, " failed: ", zErrMsg,
6385 (char*)0);
6386 sqlite3_free(zErrMsg);
6387 return TCL_ERROR;
6388 }
drh248f2be2013-04-23 20:10:13 +00006389 }
6390 return TCL_OK;
6391}
6392
dan0d51def2014-05-03 14:28:14 +00006393/*
6394** sorter_test_fakeheap BOOL
6395**
6396*/
6397static int sorter_test_fakeheap(
6398 void * clientData,
6399 Tcl_Interp *interp,
6400 int objc,
6401 Tcl_Obj *CONST objv[]
6402){
6403 int bArg;
6404 if( objc!=2 ){
6405 Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
6406 return TCL_ERROR;
6407 }
6408
6409 if( Tcl_GetBooleanFromObj(interp, objv[1], &bArg) ){
6410 return TCL_ERROR;
6411 }
6412
6413 if( bArg ){
6414 if( sqlite3GlobalConfig.pHeap==0 ){
6415 sqlite3GlobalConfig.pHeap = SQLITE_INT_TO_PTR(-1);
6416 }
6417 }else{
6418 if( sqlite3GlobalConfig.pHeap==SQLITE_INT_TO_PTR(-1) ){
6419 sqlite3GlobalConfig.pHeap = 0;
6420 }
6421 }
6422
6423 Tcl_ResetResult(interp);
6424 return TCL_OK;
6425}
6426
dandfea4532014-05-06 15:38:07 +00006427/*
6428** sorter_test_sort4_helper DB SQL1 NSTEP SQL2
6429**
6430** Compile SQL statement $SQL1 and step it $NSTEP times. For each row,
6431** check that the leftmost and rightmost columns returned are both integers,
6432** and that both contain the same value.
6433**
6434** Then execute statement $SQL2. Check that the statement returns the same
6435** set of integers in the same order as in the previous step (using $SQL1).
6436*/
6437static int sorter_test_sort4_helper(
6438 void * clientData,
6439 Tcl_Interp *interp,
6440 int objc,
6441 Tcl_Obj *CONST objv[]
6442){
6443 const char *zSql1;
6444 const char *zSql2;
6445 int nStep;
6446 int iStep;
6447 int iCksum1 = 0;
6448 int iCksum2 = 0;
6449 int rc;
6450 int iB;
6451 sqlite3 *db;
6452 sqlite3_stmt *pStmt;
6453
6454 if( objc!=5 ){
6455 Tcl_WrongNumArgs(interp, 1, objv, "DB SQL1 NSTEP SQL2");
6456 return TCL_ERROR;
6457 }
6458
6459 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
6460 zSql1 = Tcl_GetString(objv[2]);
6461 if( Tcl_GetIntFromObj(interp, objv[3], &nStep) ) return TCL_ERROR;
6462 zSql2 = Tcl_GetString(objv[4]);
6463
6464 rc = sqlite3_prepare_v2(db, zSql1, -1, &pStmt, 0);
6465 if( rc!=SQLITE_OK ) goto sql_error;
6466
6467 iB = sqlite3_column_count(pStmt)-1;
6468 for(iStep=0; iStep<nStep && SQLITE_ROW==sqlite3_step(pStmt); iStep++){
6469 int a = sqlite3_column_int(pStmt, 0);
6470 if( a!=sqlite3_column_int(pStmt, iB) ){
6471 Tcl_AppendResult(interp, "data error: (a!=b)", 0);
6472 return TCL_ERROR;
6473 }
6474
6475 iCksum1 += (iCksum1 << 3) + a;
6476 }
6477 rc = sqlite3_finalize(pStmt);
6478 if( rc!=SQLITE_OK ) goto sql_error;
6479
6480 rc = sqlite3_prepare_v2(db, zSql2, -1, &pStmt, 0);
6481 if( rc!=SQLITE_OK ) goto sql_error;
6482 for(iStep=0; SQLITE_ROW==sqlite3_step(pStmt); iStep++){
6483 int a = sqlite3_column_int(pStmt, 0);
6484 iCksum2 += (iCksum2 << 3) + a;
6485 }
6486 rc = sqlite3_finalize(pStmt);
6487 if( rc!=SQLITE_OK ) goto sql_error;
6488
6489 if( iCksum1!=iCksum2 ){
6490 Tcl_AppendResult(interp, "checksum mismatch", 0);
6491 return TCL_ERROR;
6492 }
6493
6494 return TCL_OK;
6495 sql_error:
6496 Tcl_AppendResult(interp, "sql error: ", sqlite3_errmsg(db), 0);
6497 return TCL_ERROR;
6498}
6499
drh248f2be2013-04-23 20:10:13 +00006500
drhd39c40f2014-09-11 00:27:53 +00006501#ifdef SQLITE_USER_AUTHENTICATION
6502#include "sqlite3userauth.h"
6503/*
6504** tclcmd: sqlite3_user_authenticate DB USERNAME PASSWORD
6505*/
6506static int test_user_authenticate(
6507 ClientData clientData, /* Unused */
6508 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6509 int objc, /* Number of arguments */
6510 Tcl_Obj *CONST objv[] /* Command arguments */
6511){
6512 char *zUser = 0;
6513 char *zPasswd = 0;
6514 int nPasswd = 0;
6515 sqlite3 *db;
6516 int rc;
6517
6518 if( objc!=4 ){
6519 Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD");
6520 return TCL_ERROR;
6521 }
6522 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6523 return TCL_ERROR;
6524 }
6525 zUser = Tcl_GetString(objv[2]);
6526 zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
6527 rc = sqlite3_user_authenticate(db, zUser, zPasswd, nPasswd);
6528 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
6529 return TCL_OK;
6530}
6531#endif /* SQLITE_USER_AUTHENTICATION */
6532
6533#ifdef SQLITE_USER_AUTHENTICATION
6534/*
6535** tclcmd: sqlite3_user_add DB USERNAME PASSWORD ISADMIN
6536*/
6537static int test_user_add(
6538 ClientData clientData, /* Unused */
6539 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6540 int objc, /* Number of arguments */
6541 Tcl_Obj *CONST objv[] /* Command arguments */
6542){
6543 char *zUser = 0;
6544 char *zPasswd = 0;
6545 int nPasswd = 0;
6546 int isAdmin = 0;
6547 sqlite3 *db;
6548 int rc;
6549
6550 if( objc!=5 ){
6551 Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
6552 return TCL_ERROR;
6553 }
6554 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6555 return TCL_ERROR;
6556 }
6557 zUser = Tcl_GetString(objv[2]);
6558 zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
6559 Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
6560 rc = sqlite3_user_add(db, zUser, zPasswd, nPasswd, isAdmin);
6561 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
6562 return TCL_OK;
6563}
6564#endif /* SQLITE_USER_AUTHENTICATION */
6565
6566#ifdef SQLITE_USER_AUTHENTICATION
6567/*
6568** tclcmd: sqlite3_user_change DB USERNAME PASSWORD ISADMIN
6569*/
6570static int test_user_change(
6571 ClientData clientData, /* Unused */
6572 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6573 int objc, /* Number of arguments */
6574 Tcl_Obj *CONST objv[] /* Command arguments */
6575){
6576 char *zUser = 0;
6577 char *zPasswd = 0;
6578 int nPasswd = 0;
6579 int isAdmin = 0;
6580 sqlite3 *db;
6581 int rc;
6582
6583 if( objc!=5 ){
6584 Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
6585 return TCL_ERROR;
6586 }
6587 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6588 return TCL_ERROR;
6589 }
6590 zUser = Tcl_GetString(objv[2]);
6591 zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
6592 Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
6593 rc = sqlite3_user_change(db, zUser, zPasswd, nPasswd, isAdmin);
6594 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
6595 return TCL_OK;
6596}
6597#endif /* SQLITE_USER_AUTHENTICATION */
6598
6599#ifdef SQLITE_USER_AUTHENTICATION
6600/*
6601** tclcmd: sqlite3_user_delete DB USERNAME
6602*/
6603static int test_user_delete(
6604 ClientData clientData, /* Unused */
6605 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6606 int objc, /* Number of arguments */
6607 Tcl_Obj *CONST objv[] /* Command arguments */
6608){
6609 char *zUser = 0;
6610 sqlite3 *db;
6611 int rc;
6612
6613 if( objc!=3 ){
6614 Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME");
6615 return TCL_ERROR;
6616 }
6617 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6618 return TCL_ERROR;
6619 }
6620 zUser = Tcl_GetString(objv[2]);
6621 rc = sqlite3_user_delete(db, zUser);
6622 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
6623 return TCL_OK;
6624}
6625#endif /* SQLITE_USER_AUTHENTICATION */
6626
drhf58ee7f2010-12-06 21:06:09 +00006627/*
drhedb31cd2015-01-08 02:15:11 +00006628** tclcmd: bad_behavior TYPE
6629**
6630** Do some things that should trigger a valgrind or -fsanitize=undefined
6631** warning. This is used to verify that errors and warnings output by those
6632** tools are detected by the test scripts.
6633**
6634** TYPE BEHAVIOR
6635** 1 Overflow a signed integer
6636** 2 Jump based on an uninitialized variable
6637** 3 Read after free
drhdb6bafa2015-01-09 21:54:58 +00006638** 4 Panic
drhedb31cd2015-01-08 02:15:11 +00006639*/
6640static int test_bad_behavior(
6641 ClientData clientData, /* Pointer to an integer containing zero */
6642 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6643 int objc, /* Number of arguments */
6644 Tcl_Obj *CONST objv[] /* Command arguments */
6645){
6646 int iType;
6647 int xyz;
6648 int i = *(int*)clientData;
6649 int j;
6650 int w[10];
6651 int *a;
6652 if( objc!=2 ){
6653 Tcl_WrongNumArgs(interp, 1, objv, "TYPE");
6654 return TCL_ERROR;
6655 }
6656 if( Tcl_GetIntFromObj(interp, objv[1], &iType) ) return TCL_ERROR;
6657 switch( iType ){
6658 case 1: {
6659 xyz = 0x7fffff00 - i;
6660 xyz += 0x100;
6661 Tcl_SetObjResult(interp, Tcl_NewIntObj(xyz));
6662 break;
6663 }
6664 case 2: {
6665 w[1] = 5;
6666 if( w[i]>0 ) w[1]++;
6667 Tcl_SetObjResult(interp, Tcl_NewIntObj(w[1]));
6668 break;
6669 }
6670 case 3: {
6671 a = malloc( sizeof(int)*10 );
6672 for(j=0; j<10; j++) a[j] = j;
6673 free(a);
6674 Tcl_SetObjResult(interp, Tcl_NewIntObj(a[i]));
6675 break;
6676 }
drhdb6bafa2015-01-09 21:54:58 +00006677 case 4: {
6678 Tcl_Panic("Deliberate panic");
6679 break;
6680 }
drhedb31cd2015-01-08 02:15:11 +00006681 }
6682 return TCL_OK;
6683}
6684
6685
6686/*
drhd1bf3512001-04-07 15:24:33 +00006687** Register commands with the TCL interpreter.
6688*/
6689int Sqlitetest1_Init(Tcl_Interp *interp){
danielk19776f8a5032004-05-10 10:34:51 +00006690 extern int sqlite3_search_count;
dan0ff297e2009-09-25 17:03:14 +00006691 extern int sqlite3_found_count;
danielk19776f8a5032004-05-10 10:34:51 +00006692 extern int sqlite3_interrupt_count;
6693 extern int sqlite3_open_file_count;
drh6bf89572004-11-03 16:27:01 +00006694 extern int sqlite3_sort_count;
danielk19776f8a5032004-05-10 10:34:51 +00006695 extern int sqlite3_current_time;
drh84a2bf62010-03-05 13:41:06 +00006696#if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
aswiftaebf4132008-11-21 00:10:35 +00006697 extern int sqlite3_hostid_num;
pweilbacheraabbed22008-11-21 23:35:02 +00006698#endif
drhae7e1512007-05-02 16:51:59 +00006699 extern int sqlite3_max_blobsize;
drh16a9b832007-05-05 18:39:25 +00006700 extern int sqlite3BtreeSharedCacheReport(void*,
6701 Tcl_Interp*,int,Tcl_Obj*CONST*);
drhedb31cd2015-01-08 02:15:11 +00006702 static int iZero = 0;
drhc2eef3b2002-08-31 18:53:06 +00006703 static struct {
6704 char *zName;
6705 Tcl_CmdProc *xProc;
6706 } aCmd[] = {
drh27641702007-08-22 02:56:42 +00006707 { "db_enter", (Tcl_CmdProc*)db_enter },
6708 { "db_leave", (Tcl_CmdProc*)db_leave },
drhd3d39e92004-05-20 22:16:29 +00006709 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int },
drhe9707672004-06-25 01:10:48 +00006710 { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 },
drhc5cad1e2009-02-01 00:21:09 +00006711 { "sqlite3_mprintf_long", (Tcl_CmdProc*)sqlite3_mprintf_long },
drhd3d39e92004-05-20 22:16:29 +00006712 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str },
drhb3738b62007-03-31 15:02:49 +00006713 { "sqlite3_snprintf_str", (Tcl_CmdProc*)sqlite3_snprintf_str },
drhe29b1a02004-07-17 21:56:09 +00006714 { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly},
drhd3d39e92004-05-20 22:16:29 +00006715 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double },
6716 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled },
drh63782852005-08-30 19:30:59 +00006717 { "sqlite3_mprintf_hexdouble", (Tcl_CmdProc*)sqlite3_mprintf_hexdouble},
drhd3d39e92004-05-20 22:16:29 +00006718 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z },
drh05a82982006-03-19 13:00:25 +00006719 { "sqlite3_mprintf_n_test", (Tcl_CmdProc*)test_mprintf_n },
drh68853902007-05-07 11:24:30 +00006720 { "sqlite3_snprintf_int", (Tcl_CmdProc*)test_snprintf_int },
drhd3d39e92004-05-20 22:16:29 +00006721 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid },
6722 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf },
drh5bd98ae2009-01-07 18:24:03 +00006723 { "sqlite3_exec_hex", (Tcl_CmdProc*)test_exec_hex },
drhb62c3352006-11-23 09:39:16 +00006724 { "sqlite3_exec", (Tcl_CmdProc*)test_exec },
6725 { "sqlite3_exec_nr", (Tcl_CmdProc*)test_exec_nr },
shane8225f5a2008-07-31 02:05:04 +00006726#ifndef SQLITE_OMIT_GET_TABLE
drhd3d39e92004-05-20 22:16:29 +00006727 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
shane8225f5a2008-07-31 02:05:04 +00006728#endif
drhd3d39e92004-05-20 22:16:29 +00006729 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close },
dan617dc862013-05-16 11:57:28 +00006730 { "sqlite3_close_v2", (Tcl_CmdProc*)sqlite_test_close_v2 },
drhd3d39e92004-05-20 22:16:29 +00006731 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
6732 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
6733 { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
6734 { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
drh25d65432004-07-22 15:02:25 +00006735 { "sqlite_bind", (Tcl_CmdProc*)test_bind },
6736 { "breakpoint", (Tcl_CmdProc*)test_breakpoint },
6737 { "sqlite3_key", (Tcl_CmdProc*)test_key },
6738 { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey },
drhcacb2082005-01-11 15:28:33 +00006739 { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic },
drhc5cdca62005-01-11 16:54:14 +00006740 { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt },
drh3e1d8e62005-05-26 16:23:34 +00006741 { "sqlite_delete_function", (Tcl_CmdProc*)delete_function },
6742 { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation },
6743 { "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit },
drh79158e12005-09-06 21:40:45 +00006744 { "sqlite3_stack_used", (Tcl_CmdProc*)test_stack_used },
drh30867652006-07-06 10:59:57 +00006745 { "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout },
drh3c23a882007-01-09 14:01:13 +00006746 { "printf", (Tcl_CmdProc*)test_printf },
mlcreech3a00f902008-03-04 17:45:01 +00006747 { "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace },
danafcf9bd2014-01-23 14:44:08 +00006748 { "clang_sanitize_address", (Tcl_CmdProc*)clang_sanitize_address },
drhc2eef3b2002-08-31 18:53:06 +00006749 };
danielk197751e3d8e2004-05-20 01:12:34 +00006750 static struct {
6751 char *zName;
6752 Tcl_ObjCmdProc *xProc;
danielk197704f2e682004-05-27 01:04:07 +00006753 void *clientData;
danielk197751e3d8e2004-05-20 01:12:34 +00006754 } aObjCmd[] = {
drhedb31cd2015-01-08 02:15:11 +00006755 { "bad_behavior", test_bad_behavior, (void*)&iZero },
drhdddca282006-01-03 00:33:50 +00006756 { "sqlite3_connection_pointer", get_sqlite_pointer, 0 },
drh241db312004-06-22 12:46:53 +00006757 { "sqlite3_bind_int", test_bind_int, 0 },
drhb026e052007-05-02 01:34:31 +00006758 { "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 },
drh241db312004-06-22 12:46:53 +00006759 { "sqlite3_bind_int64", test_bind_int64, 0 },
6760 { "sqlite3_bind_double", test_bind_double, 0 },
danielk197704f2e682004-05-27 01:04:07 +00006761 { "sqlite3_bind_null", test_bind_null ,0 },
6762 { "sqlite3_bind_text", test_bind_text ,0 },
6763 { "sqlite3_bind_text16", test_bind_text16 ,0 },
6764 { "sqlite3_bind_blob", test_bind_blob ,0 },
drh75f6a032004-07-15 14:15:00 +00006765 { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0},
drh895d7472004-08-20 16:02:39 +00006766 { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0},
drhfa6bc002004-09-07 16:19:52 +00006767 { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0},
danielk1977600dd0b2005-01-20 01:14:23 +00006768 { "sqlite3_clear_bindings", test_clear_bindings, 0},
drhf9cb7f52006-06-27 20:06:44 +00006769 { "sqlite3_sleep", test_sleep, 0},
danielk197704f2e682004-05-27 01:04:07 +00006770 { "sqlite3_errcode", test_errcode ,0 },
drh99dfe5e2008-10-30 15:03:15 +00006771 { "sqlite3_extended_errcode", test_ex_errcode ,0 },
danielk197704f2e682004-05-27 01:04:07 +00006772 { "sqlite3_errmsg", test_errmsg ,0 },
6773 { "sqlite3_errmsg16", test_errmsg16 ,0 },
6774 { "sqlite3_open", test_open ,0 },
6775 { "sqlite3_open16", test_open16 ,0 },
dan286ab7c2011-05-06 18:34:54 +00006776 { "sqlite3_open_v2", test_open_v2 ,0 },
danielk1977bc6ada42004-06-30 08:20:16 +00006777 { "sqlite3_complete16", test_complete16 ,0 },
danielk197704f2e682004-05-27 01:04:07 +00006778
6779 { "sqlite3_prepare", test_prepare ,0 },
6780 { "sqlite3_prepare16", test_prepare16 ,0 },
drhb900aaf2006-11-09 00:24:53 +00006781 { "sqlite3_prepare_v2", test_prepare_v2 ,0 },
drh4837f532008-05-23 14:49:49 +00006782 { "sqlite3_prepare_tkt3134", test_prepare_tkt3134, 0},
drhb900aaf2006-11-09 00:24:53 +00006783 { "sqlite3_prepare16_v2", test_prepare16_v2 ,0 },
danielk197704f2e682004-05-27 01:04:07 +00006784 { "sqlite3_finalize", test_finalize ,0 },
drhd1d38482008-10-07 23:46:38 +00006785 { "sqlite3_stmt_status", test_stmt_status ,0 },
danielk197704f2e682004-05-27 01:04:07 +00006786 { "sqlite3_reset", test_reset ,0 },
drhd89bd002005-01-22 03:03:54 +00006787 { "sqlite3_expired", test_expired ,0 },
drhf8db1bc2005-04-22 02:38:37 +00006788 { "sqlite3_transfer_bindings", test_transfer_bind ,0 },
danielk1977fbcd5852004-06-15 02:44:18 +00006789 { "sqlite3_changes", test_changes ,0 },
6790 { "sqlite3_step", test_step ,0 },
danielk1977404ca072009-03-16 13:19:36 +00006791 { "sqlite3_sql", test_sql ,0 },
drhbb5a9c32008-06-19 02:52:25 +00006792 { "sqlite3_next_stmt", test_next_stmt ,0 },
drhf03d9cc2010-11-16 23:10:25 +00006793 { "sqlite3_stmt_readonly", test_stmt_readonly ,0 },
drh2fb66932011-11-25 17:21:47 +00006794 { "sqlite3_stmt_busy", test_stmt_busy ,0 },
dand9495cd2011-04-27 12:08:04 +00006795 { "uses_stmt_journal", uses_stmt_journal ,0 },
danielk197704f2e682004-05-27 01:04:07 +00006796
drhb4bc7052006-01-11 23:40:33 +00006797 { "sqlite3_release_memory", test_release_memory, 0},
drh09419b42011-11-16 19:29:17 +00006798 { "sqlite3_db_release_memory", test_db_release_memory, 0},
drh283829c2011-11-17 00:56:20 +00006799 { "sqlite3_db_filename", test_db_filename, 0},
drh421377e2012-03-15 21:28:54 +00006800 { "sqlite3_db_readonly", test_db_readonly, 0},
drhb4bc7052006-01-11 23:40:33 +00006801 { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
drhb4bc7052006-01-11 23:40:33 +00006802 { "sqlite3_thread_cleanup", test_thread_cleanup, 0},
drhc6ba55f2007-04-05 17:36:18 +00006803 { "sqlite3_pager_refcounts", test_pager_refcounts, 0},
drh6aafc292006-01-05 15:50:06 +00006804
drhc2e87a32006-06-27 15:16:14 +00006805 { "sqlite3_load_extension", test_load_extension, 0},
6806 { "sqlite3_enable_load_extension", test_enable_load, 0},
drh4ac285a2006-09-15 07:28:50 +00006807 { "sqlite3_extended_result_codes", test_extended_result_codes, 0},
drhb1a6c3c2008-03-20 16:30:17 +00006808 { "sqlite3_limit", test_limit, 0},
drhc2e87a32006-06-27 15:16:14 +00006809
drh93aed5a2008-01-16 17:46:38 +00006810 { "save_prng_state", save_prng_state, 0 },
6811 { "restore_prng_state", restore_prng_state, 0 },
6812 { "reset_prng_state", reset_prng_state, 0 },
drh09fe6142013-11-29 15:06:27 +00006813 { "database_never_corrupt", database_never_corrupt, 0},
6814 { "database_may_be_corrupt", database_may_be_corrupt, 0},
drhf58ee7f2010-12-06 21:06:09 +00006815 { "optimization_control", optimization_control,0},
drh80084ca2011-07-11 23:45:44 +00006816#if SQLITE_OS_WIN
6817 { "lock_win32_file", win32_file_lock, 0 },
mistachkin37418272013-08-28 05:49:39 +00006818 { "exists_win32_path", win32_exists_path, 0 },
6819 { "find_win32_file", win32_find_file, 0 },
6820 { "delete_win32_file", win32_delete_file, 0 },
6821 { "make_win32_dir", win32_mkdir, 0 },
6822 { "remove_win32_dir", win32_rmdir, 0 },
drh80084ca2011-07-11 23:45:44 +00006823#endif
drha2c8a952009-10-13 18:38:34 +00006824 { "tcl_objproc", runAsObjProc, 0 },
drh93aed5a2008-01-16 17:46:38 +00006825
danielk197704f2e682004-05-27 01:04:07 +00006826 /* sqlite3_column_*() API */
6827 { "sqlite3_column_count", test_column_count ,0 },
6828 { "sqlite3_data_count", test_data_count ,0 },
6829 { "sqlite3_column_type", test_column_type ,0 },
danielk1977ea61b2c2004-05-27 01:49:51 +00006830 { "sqlite3_column_blob", test_column_blob ,0 },
danielk197704f2e682004-05-27 01:04:07 +00006831 { "sqlite3_column_double", test_column_double ,0 },
6832 { "sqlite3_column_int64", test_column_int64 ,0 },
danielk197744a376f2008-08-12 15:04:58 +00006833 { "sqlite3_column_text", test_stmt_utf8, (void*)sqlite3_column_text },
6834 { "sqlite3_column_name", test_stmt_utf8, (void*)sqlite3_column_name },
6835 { "sqlite3_column_int", test_stmt_int, (void*)sqlite3_column_int },
6836 { "sqlite3_column_bytes", test_stmt_int, (void*)sqlite3_column_bytes},
drh3f913572008-03-22 01:07:17 +00006837#ifndef SQLITE_OMIT_DECLTYPE
danielk197744a376f2008-08-12 15:04:58 +00006838 { "sqlite3_column_decltype",test_stmt_utf8,(void*)sqlite3_column_decltype},
drh3f913572008-03-22 01:07:17 +00006839#endif
danielk19774b1ae992006-02-10 03:06:10 +00006840#ifdef SQLITE_ENABLE_COLUMN_METADATA
danielk197744a376f2008-08-12 15:04:58 +00006841{ "sqlite3_column_database_name",test_stmt_utf8,(void*)sqlite3_column_database_name},
6842{ "sqlite3_column_table_name",test_stmt_utf8,(void*)sqlite3_column_table_name},
6843{ "sqlite3_column_origin_name",test_stmt_utf8,(void*)sqlite3_column_origin_name},
danielk19774b1ae992006-02-10 03:06:10 +00006844#endif
danielk1977955de522006-02-10 02:27:42 +00006845
drh6c626082004-11-14 21:56:29 +00006846#ifndef SQLITE_OMIT_UTF16
danielk197744a376f2008-08-12 15:04:58 +00006847 { "sqlite3_column_bytes16", test_stmt_int, (void*)sqlite3_column_bytes16 },
6848 { "sqlite3_column_text16", test_stmt_utf16, (void*)sqlite3_column_text16},
6849 { "sqlite3_column_name16", test_stmt_utf16, (void*)sqlite3_column_name16},
drh7d9bd4e2006-02-16 18:16:36 +00006850 { "add_alignment_test_collations", add_alignment_test_collations, 0 },
drh3f913572008-03-22 01:07:17 +00006851#ifndef SQLITE_OMIT_DECLTYPE
danielk197744a376f2008-08-12 15:04:58 +00006852 { "sqlite3_column_decltype16",test_stmt_utf16,(void*)sqlite3_column_decltype16},
drh3f913572008-03-22 01:07:17 +00006853#endif
danielk19774b1ae992006-02-10 03:06:10 +00006854#ifdef SQLITE_ENABLE_COLUMN_METADATA
danielk1977955de522006-02-10 02:27:42 +00006855{"sqlite3_column_database_name16",
drh7da5fcb2012-03-30 14:59:43 +00006856 test_stmt_utf16, (void*)sqlite3_column_database_name16},
danielk197744a376f2008-08-12 15:04:58 +00006857{"sqlite3_column_table_name16", test_stmt_utf16, (void*)sqlite3_column_table_name16},
6858{"sqlite3_column_origin_name16", test_stmt_utf16, (void*)sqlite3_column_origin_name16},
drh6c626082004-11-14 21:56:29 +00006859#endif
danielk19774b1ae992006-02-10 03:06:10 +00006860#endif
danielk1977a393c032007-05-07 14:58:53 +00006861 { "sqlite3_create_collation_v2", test_create_collation_v2, 0 },
danielk1977a9808b32007-05-07 09:32:45 +00006862 { "sqlite3_global_recover", test_global_recover, 0 },
6863 { "working_64bit_int", working_64bit_int, 0 },
drh9bc54492007-10-23 14:49:59 +00006864 { "vfs_unlink_test", vfs_unlink_test, 0 },
drhc8d75672008-07-08 02:12:37 +00006865 { "vfs_initfail_test", vfs_initfail_test, 0 },
drha2820972008-07-07 13:31:58 +00006866 { "vfs_unregister_all", vfs_unregister_all, 0 },
6867 { "vfs_reregister_all", vfs_reregister_all, 0 },
drh55176252008-01-22 14:50:16 +00006868 { "file_control_test", file_control_test, 0 },
aswiftaebf4132008-11-21 00:10:35 +00006869 { "file_control_lasterrno_test", file_control_lasterrno_test, 0 },
6870 { "file_control_lockproxy_test", file_control_lockproxy_test, 0 },
dan6e09d692010-07-27 18:34:15 +00006871 { "file_control_chunksize_test", file_control_chunksize_test, 0 },
drhd0cdf012011-07-13 16:03:46 +00006872 { "file_control_sizehint_test", file_control_sizehint_test, 0 },
mistachkin6b98d672014-05-30 16:42:35 +00006873#if SQLITE_OS_WIN
drhd0cdf012011-07-13 16:03:46 +00006874 { "file_control_win32_av_retry", file_control_win32_av_retry, 0 },
mistachkin6b98d672014-05-30 16:42:35 +00006875 { "file_control_win32_set_handle", file_control_win32_set_handle, 0 },
6876#endif
drh253cea52011-07-26 16:23:25 +00006877 { "file_control_persist_wal", file_control_persist_wal, 0 },
drhcb15f352011-12-23 01:04:17 +00006878 { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
drhde60fc22011-12-14 17:53:36 +00006879 { "file_control_vfsname", file_control_vfsname, 0 },
drh696b33e2012-12-06 19:01:42 +00006880 { "file_control_tempfilename", file_control_tempfilename, 0 },
danielk1977e339d652008-06-28 11:23:00 +00006881 { "sqlite3_vfs_list", vfs_list, 0 },
dand2199f02010-08-27 17:48:52 +00006882 { "sqlite3_create_function_v2", test_create_function_v2, 0 },
danielk197704f2e682004-05-27 01:04:07 +00006883
danielk19779a1d0ab2004-06-01 14:09:28 +00006884 /* Functions from os.h */
drh5436dc22004-11-14 04:04:17 +00006885#ifndef SQLITE_OMIT_UTF16
danielk1977312d6b32004-06-29 13:18:23 +00006886 { "add_test_collate", test_collate, 0 },
6887 { "add_test_collate_needed", test_collate_needed, 0 },
6888 { "add_test_function", test_function, 0 },
dan38fdead2014-04-01 10:19:02 +00006889 { "add_test_utf16bin_collate", test_utf16bin_collate, 0 },
drh5436dc22004-11-14 04:04:17 +00006890#endif
danielk1977312d6b32004-06-29 13:18:23 +00006891 { "sqlite3_test_errstr", test_errstr, 0 },
drh92febd92004-08-20 18:34:20 +00006892 { "tcl_variable_type", tcl_variable_type, 0 },
danielk1977aef0bf62005-12-30 16:28:01 +00006893#ifndef SQLITE_OMIT_SHARED_CACHE
drh6f7adc82006-01-11 21:41:20 +00006894 { "sqlite3_enable_shared_cache", test_enable_shared, 0 },
drh16a9b832007-05-05 18:39:25 +00006895 { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0},
danielk1977aef0bf62005-12-30 16:28:01 +00006896#endif
danielk1977161fb792006-01-24 10:58:21 +00006897 { "sqlite3_libversion_number", test_libversion_number, 0 },
danielk1977deb802c2006-02-09 13:43:28 +00006898 { "sqlite3_table_column_metadata", test_table_column_metadata, 0 },
danielk1977dcbb5d32007-05-04 18:36:44 +00006899#ifndef SQLITE_OMIT_INCRBLOB
dan4e76cc32010-10-20 18:56:04 +00006900 { "sqlite3_blob_reopen", test_blob_reopen, 0 },
danielk1977dcbb5d32007-05-04 18:36:44 +00006901#endif
danielk1977062d4cb2008-08-29 09:10:02 +00006902 { "pcache_stats", test_pcache_stats, 0 },
danielk1977404ca072009-03-16 13:19:36 +00006903#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
6904 { "sqlite3_unlock_notify", test_unlock_notify, 0 },
6905#endif
dan91da6b82010-11-15 14:51:33 +00006906 { "sqlite3_wal_checkpoint", test_wal_checkpoint, 0 },
dan9c5e3682011-02-07 15:12:12 +00006907 { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0 },
dan9af10622014-12-15 16:27:12 +00006908 { "sqlite3_wal_autocheckpoint",test_wal_autocheckpoint, 0 },
dan91da6b82010-11-15 14:51:33 +00006909 { "test_sqlite3_log", test_sqlite3_log, 0 },
shanehbb201342011-02-09 19:55:20 +00006910#ifndef SQLITE_OMIT_EXPLAIN
dan91da6b82010-11-15 14:51:33 +00006911 { "print_explain_query_plan", test_print_eqp, 0 },
shanehbb201342011-02-09 19:55:20 +00006912#endif
danc17d6962011-06-21 12:47:30 +00006913 { "sqlite3_test_control", test_test_control },
mistachkindaf9a5a2013-03-23 09:56:39 +00006914#if SQLITE_OS_UNIX
dana72014f2013-03-16 20:19:21 +00006915 { "getrusage", test_getrusage },
mistachkindaf9a5a2013-03-23 09:56:39 +00006916#endif
drh248f2be2013-04-23 20:10:13 +00006917 { "load_static_extension", tclLoadStaticExtensionCmd },
dan0d51def2014-05-03 14:28:14 +00006918 { "sorter_test_fakeheap", sorter_test_fakeheap },
dandfea4532014-05-06 15:38:07 +00006919 { "sorter_test_sort4_helper", sorter_test_sort4_helper },
drhd39c40f2014-09-11 00:27:53 +00006920#ifdef SQLITE_USER_AUTHENTICATION
6921 { "sqlite3_user_authenticate", test_user_authenticate, 0 },
6922 { "sqlite3_user_add", test_user_add, 0 },
6923 { "sqlite3_user_change", test_user_change, 0 },
6924 { "sqlite3_user_delete", test_user_delete, 0 },
6925#endif
dan04489b62014-10-31 20:11:32 +00006926#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
6927 { "sqlite3_stmt_scanstatus", test_stmt_scanstatus, 0 },
6928 { "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset, 0 },
6929#endif
drhd39c40f2014-09-11 00:27:53 +00006930
danielk197751e3d8e2004-05-20 01:12:34 +00006931 };
drh1398ad32005-01-19 23:24:50 +00006932 static int bitmask_size = sizeof(Bitmask)*8;
drhc2eef3b2002-08-31 18:53:06 +00006933 int i;
drhb851b2c2005-03-10 14:11:12 +00006934 extern int sqlite3_sync_count, sqlite3_fullsync_count;
drhaf6df112005-06-07 02:12:30 +00006935 extern int sqlite3_opentemp_count;
drh55ef4d92005-08-14 01:20:37 +00006936 extern int sqlite3_like_count;
drhdd735212007-02-24 13:53:05 +00006937 extern int sqlite3_xferopt_count;
drh538f5702007-04-13 02:14:30 +00006938 extern int sqlite3_pager_readdb_count;
6939 extern int sqlite3_pager_writedb_count;
6940 extern int sqlite3_pager_writej_count;
danielk197729bafea2008-06-26 10:41:19 +00006941#if SQLITE_OS_WIN
mistachkin202cb642014-07-31 18:54:01 +00006942 extern LONG volatile sqlite3_os_type;
drhc0929982005-09-05 19:08:29 +00006943#endif
drh8b3d9902005-08-19 00:14:42 +00006944#ifdef SQLITE_DEBUG
mlcreech3a00f902008-03-04 17:45:01 +00006945 extern int sqlite3WhereTrace;
6946 extern int sqlite3OSTrace;
drhc74c3332010-05-31 12:15:19 +00006947 extern int sqlite3WalTrace;
drh549c8b62005-09-19 13:15:23 +00006948#endif
6949#ifdef SQLITE_TEST
danielk197733e89032008-12-17 15:18:17 +00006950#ifdef SQLITE_ENABLE_FTS3
6951 extern int sqlite3_fts3_enable_parentheses;
6952#endif
drh48083ce2005-09-19 12:37:27 +00006953#endif
drhc2eef3b2002-08-31 18:53:06 +00006954
6955 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
6956 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
6957 }
danielk197751e3d8e2004-05-20 01:12:34 +00006958 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
danielk1977c572ef72004-05-27 09:28:41 +00006959 Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
6960 aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
danielk197751e3d8e2004-05-20 01:12:34 +00006961 }
danielk19776490beb2004-05-11 06:17:21 +00006962 Tcl_LinkVar(interp, "sqlite_search_count",
danielk19776f8a5032004-05-10 10:34:51 +00006963 (char*)&sqlite3_search_count, TCL_LINK_INT);
dan0ff297e2009-09-25 17:03:14 +00006964 Tcl_LinkVar(interp, "sqlite_found_count",
6965 (char*)&sqlite3_found_count, TCL_LINK_INT);
drh6bf89572004-11-03 16:27:01 +00006966 Tcl_LinkVar(interp, "sqlite_sort_count",
6967 (char*)&sqlite3_sort_count, TCL_LINK_INT);
drhae7e1512007-05-02 16:51:59 +00006968 Tcl_LinkVar(interp, "sqlite3_max_blobsize",
6969 (char*)&sqlite3_max_blobsize, TCL_LINK_INT);
drh55ef4d92005-08-14 01:20:37 +00006970 Tcl_LinkVar(interp, "sqlite_like_count",
6971 (char*)&sqlite3_like_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00006972 Tcl_LinkVar(interp, "sqlite_interrupt_count",
danielk19776f8a5032004-05-10 10:34:51 +00006973 (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00006974 Tcl_LinkVar(interp, "sqlite_open_file_count",
danielk19776f8a5032004-05-10 10:34:51 +00006975 (char*)&sqlite3_open_file_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00006976 Tcl_LinkVar(interp, "sqlite_current_time",
danielk19776f8a5032004-05-10 10:34:51 +00006977 (char*)&sqlite3_current_time, TCL_LINK_INT);
drh84a2bf62010-03-05 13:41:06 +00006978#if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
aswiftaebf4132008-11-21 00:10:35 +00006979 Tcl_LinkVar(interp, "sqlite_hostid_num",
6980 (char*)&sqlite3_hostid_num, TCL_LINK_INT);
pweilbacheraabbed22008-11-21 23:35:02 +00006981#endif
drhdd735212007-02-24 13:53:05 +00006982 Tcl_LinkVar(interp, "sqlite3_xferopt_count",
6983 (char*)&sqlite3_xferopt_count, TCL_LINK_INT);
drh538f5702007-04-13 02:14:30 +00006984 Tcl_LinkVar(interp, "sqlite3_pager_readdb_count",
6985 (char*)&sqlite3_pager_readdb_count, TCL_LINK_INT);
6986 Tcl_LinkVar(interp, "sqlite3_pager_writedb_count",
6987 (char*)&sqlite3_pager_writedb_count, TCL_LINK_INT);
6988 Tcl_LinkVar(interp, "sqlite3_pager_writej_count",
6989 (char*)&sqlite3_pager_writej_count, TCL_LINK_INT);
danielk19774b2688a2006-06-20 11:01:07 +00006990#ifndef SQLITE_OMIT_UTF16
drh7d9bd4e2006-02-16 18:16:36 +00006991 Tcl_LinkVar(interp, "unaligned_string_counter",
6992 (char*)&unaligned_string_counter, TCL_LINK_INT);
danielk19774b2688a2006-06-20 11:01:07 +00006993#endif
drh268803a2005-12-14 20:11:30 +00006994#ifndef SQLITE_OMIT_UTF16
6995 Tcl_LinkVar(interp, "sqlite_last_needed_collation",
6996 (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
6997#endif
danielk197729bafea2008-06-26 10:41:19 +00006998#if SQLITE_OS_WIN
drhc0929982005-09-05 19:08:29 +00006999 Tcl_LinkVar(interp, "sqlite_os_type",
mistachkin202cb642014-07-31 18:54:01 +00007000 (char*)&sqlite3_os_type, TCL_LINK_LONG);
drhc0929982005-09-05 19:08:29 +00007001#endif
drh549c8b62005-09-19 13:15:23 +00007002#ifdef SQLITE_TEST
drh6fa978d2013-05-30 19:29:19 +00007003 {
7004 static const char *query_plan = "*** OBSOLETE VARIABLE ***";
7005 Tcl_LinkVar(interp, "sqlite_query_plan",
7006 (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
7007 }
drh549c8b62005-09-19 13:15:23 +00007008#endif
drh8b3d9902005-08-19 00:14:42 +00007009#ifdef SQLITE_DEBUG
drh48083ce2005-09-19 12:37:27 +00007010 Tcl_LinkVar(interp, "sqlite_where_trace",
mlcreech3a00f902008-03-04 17:45:01 +00007011 (char*)&sqlite3WhereTrace, TCL_LINK_INT);
drh73be5012007-08-08 12:11:21 +00007012 Tcl_LinkVar(interp, "sqlite_os_trace",
mlcreech3a00f902008-03-04 17:45:01 +00007013 (char*)&sqlite3OSTrace, TCL_LINK_INT);
dan38e1a272010-06-28 11:23:09 +00007014#ifndef SQLITE_OMIT_WAL
drhc74c3332010-05-31 12:15:19 +00007015 Tcl_LinkVar(interp, "sqlite_wal_trace",
7016 (char*)&sqlite3WalTrace, TCL_LINK_INT);
drh8b3d9902005-08-19 00:14:42 +00007017#endif
dan38e1a272010-06-28 11:23:09 +00007018#endif
danielk1977cbe21be2005-06-07 07:58:48 +00007019#ifndef SQLITE_OMIT_DISKIO
drhaf6df112005-06-07 02:12:30 +00007020 Tcl_LinkVar(interp, "sqlite_opentemp_count",
7021 (char*)&sqlite3_opentemp_count, TCL_LINK_INT);
danielk1977cbe21be2005-06-07 07:58:48 +00007022#endif
drh7c972de2003-09-06 22:18:07 +00007023 Tcl_LinkVar(interp, "sqlite_static_bind_value",
7024 (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
drhf0313812006-09-04 15:53:53 +00007025 Tcl_LinkVar(interp, "sqlite_static_bind_nbyte",
7026 (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT);
drhab3f9fe2004-08-14 17:10:10 +00007027 Tcl_LinkVar(interp, "sqlite_temp_directory",
drheffd02b2004-08-29 23:42:13 +00007028 (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
mistachkina112d142012-03-14 00:44:01 +00007029 Tcl_LinkVar(interp, "sqlite_data_directory",
7030 (char*)&sqlite3_data_directory, TCL_LINK_STRING);
drh1398ad32005-01-19 23:24:50 +00007031 Tcl_LinkVar(interp, "bitmask_size",
7032 (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
drhb851b2c2005-03-10 14:11:12 +00007033 Tcl_LinkVar(interp, "sqlite_sync_count",
7034 (char*)&sqlite3_sync_count, TCL_LINK_INT);
7035 Tcl_LinkVar(interp, "sqlite_fullsync_count",
7036 (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
drhd1fa7bc2009-01-10 13:24:50 +00007037#if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST)
danielk197733e89032008-12-17 15:18:17 +00007038 Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses",
7039 (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT);
7040#endif
drhd1bf3512001-04-07 15:24:33 +00007041 return TCL_OK;
7042}