blob: 032e3f338c462489dafa0bdbbb24a1a22e3547a9 [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;
97 sprintf(zBuf, "%p", p->db);
98 if( strncmp(zBuf,"0x",2) ){
99 sprintf(zBuf, "0x%p", p->db);
100 }
101 Tcl_AppendResult(interp, zBuf, 0);
102 return TCL_OK;
103}
104
drhb62c3352006-11-23 09:39:16 +0000105/*
106** Decode a pointer to an sqlite3 object.
107*/
drh24b58dd2008-07-07 14:50:14 +0000108int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
drhb62c3352006-11-23 09:39:16 +0000109 struct SqliteDb *p;
110 Tcl_CmdInfo cmdInfo;
111 if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){
112 p = (struct SqliteDb*)cmdInfo.objClientData;
113 *ppDb = p->db;
114 }else{
drhe8f52c52008-07-12 14:52:20 +0000115 *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA);
drhb62c3352006-11-23 09:39:16 +0000116 }
117 return TCL_OK;
118}
119
mistachkin6b98d672014-05-30 16:42:35 +0000120#if SQLITE_OS_WIN
121/*
122** Decode a Win32 HANDLE object.
123*/
124int getWin32Handle(Tcl_Interp *interp, const char *zA, LPHANDLE phFile){
125 *phFile = (HANDLE)sqlite3TestTextToPtr(zA);
126 return TCL_OK;
127}
128#endif
129
mistachkine84d8d32013-04-29 03:09:10 +0000130extern const char *sqlite3ErrName(int);
131#define t1ErrorName sqlite3ErrName
danielk19776622cce2004-05-20 11:00:52 +0000132
drhd1bf3512001-04-07 15:24:33 +0000133/*
drhc60d0442004-09-30 13:43:13 +0000134** Convert an sqlite3_stmt* into an sqlite3*. This depends on the
135** fact that the sqlite3* is the first field in the Vdbe structure.
136*/
drh51942bc2005-06-12 22:01:42 +0000137#define StmtToDb(X) sqlite3_db_handle(X)
drhc60d0442004-09-30 13:43:13 +0000138
139/*
140** Check a return value to make sure it agrees with the results
141** from sqlite3_errcode.
142*/
143int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
drhb8613ab2009-01-19 17:40:12 +0000144 if( sqlite3_threadsafe()==0 && rc!=SQLITE_MISUSE && rc!=SQLITE_OK
145 && sqlite3_errcode(db)!=rc ){
drhc60d0442004-09-30 13:43:13 +0000146 char zBuf[200];
147 int r2 = sqlite3_errcode(db);
148 sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)",
drh4f0c5872007-03-26 22:05:01 +0000149 t1ErrorName(rc), rc, t1ErrorName(r2), r2);
drhc60d0442004-09-30 13:43:13 +0000150 Tcl_ResetResult(interp);
151 Tcl_AppendResult(interp, zBuf, 0);
152 return 1;
153 }
154 return 0;
155}
156
157/*
danielk197751e3d8e2004-05-20 01:12:34 +0000158** Decode a pointer to an sqlite3_stmt object.
159*/
160static int getStmtPointer(
161 Tcl_Interp *interp,
162 const char *zArg,
163 sqlite3_stmt **ppStmt
164){
drhe8f52c52008-07-12 14:52:20 +0000165 *ppStmt = (sqlite3_stmt*)sqlite3TestTextToPtr(zArg);
danielk197751e3d8e2004-05-20 01:12:34 +0000166 return TCL_OK;
167}
168
169/*
drh7d8085a2003-04-26 13:19:38 +0000170** Generate a text representation of a pointer that can be understood
171** by the getDbPointer and getVmPointer routines above.
172**
173** The problem is, on some machines (Solaris) if you do a printf with
174** "%p" you cannot turn around and do a scanf with the same "%p" and
175** get your pointer back. You have to prepend a "0x" before it will
176** work. Or at least that is what is reported to me (drh). But this
177** behavior varies from machine to machine. The solution used her is
178** to test the string right after it is generated to see if it can be
179** understood by scanf, and if not, try prepending an "0x" to see if
180** that helps. If nothing works, a fatal error is generated.
181*/
drh64b1bea2006-01-15 02:30:57 +0000182int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
drhfe63d1c2004-09-08 20:13:04 +0000183 sqlite3_snprintf(100, zPtr, "%p", p);
drh7d8085a2003-04-26 13:19:38 +0000184 return TCL_OK;
185}
186
187/*
danielk19776f8a5032004-05-10 10:34:51 +0000188** The callback routine for sqlite3_exec_printf().
drhd1bf3512001-04-07 15:24:33 +0000189*/
190static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
191 Tcl_DString *str = (Tcl_DString*)pArg;
192 int i;
193
194 if( Tcl_DStringLength(str)==0 ){
195 for(i=0; i<argc; i++){
196 Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
197 }
198 }
199 for(i=0; i<argc; i++){
200 Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
201 }
202 return 0;
203}
204
205/*
drh538f5702007-04-13 02:14:30 +0000206** The I/O tracing callback.
207*/
shaneafdd23a2008-05-29 02:57:47 +0000208#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
drh538f5702007-04-13 02:14:30 +0000209static FILE *iotrace_file = 0;
210static void io_trace_callback(const char *zFormat, ...){
211 va_list ap;
212 va_start(ap, zFormat);
213 vfprintf(iotrace_file, zFormat, ap);
214 va_end(ap);
215 fflush(iotrace_file);
216}
shaneafdd23a2008-05-29 02:57:47 +0000217#endif
drh538f5702007-04-13 02:14:30 +0000218
219/*
220** Usage: io_trace FILENAME
221**
222** Turn I/O tracing on or off. If FILENAME is not an empty string,
223** I/O tracing begins going into FILENAME. If FILENAME is an empty
224** string, I/O tracing is turned off.
225*/
226static int test_io_trace(
227 void *NotUsed,
228 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
229 int argc, /* Number of arguments */
230 char **argv /* Text of each argument */
231){
danielk1977286d2f42008-05-05 11:33:47 +0000232#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
drh538f5702007-04-13 02:14:30 +0000233 if( argc!=2 ){
234 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
235 " FILENAME\"", 0);
236 return TCL_ERROR;
237 }
238 if( iotrace_file ){
239 if( iotrace_file!=stdout && iotrace_file!=stderr ){
240 fclose(iotrace_file);
241 }
242 iotrace_file = 0;
mlcreech3a00f902008-03-04 17:45:01 +0000243 sqlite3IoTrace = 0;
drh538f5702007-04-13 02:14:30 +0000244 }
245 if( argv[1][0] ){
246 if( strcmp(argv[1],"stdout")==0 ){
247 iotrace_file = stdout;
248 }else if( strcmp(argv[1],"stderr")==0 ){
249 iotrace_file = stderr;
250 }else{
251 iotrace_file = fopen(argv[1], "w");
252 }
mlcreech3a00f902008-03-04 17:45:01 +0000253 sqlite3IoTrace = io_trace_callback;
drh538f5702007-04-13 02:14:30 +0000254 }
danielk1977286d2f42008-05-05 11:33:47 +0000255#endif
256 return TCL_OK;
drh538f5702007-04-13 02:14:30 +0000257}
258
danafcf9bd2014-01-23 14:44:08 +0000259/*
260** Usage: clang_sanitize_address
261**
262** Returns true if the program was compiled using clang with the
263** -fsanitize=address switch on the command line. False otherwise.
264*/
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
277 Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
278 return TCL_OK;
279}
280
drh538f5702007-04-13 02:14:30 +0000281/*
danielk19776f8a5032004-05-10 10:34:51 +0000282** Usage: sqlite3_exec_printf DB FORMAT STRING
drhd1bf3512001-04-07 15:24:33 +0000283**
danielk19776f8a5032004-05-10 10:34:51 +0000284** Invoke the sqlite3_exec_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000285** DB. The SQL is the string FORMAT. The format string should contain
286** one %s or %q. STRING is the value inserted into %s or %q.
287*/
288static int test_exec_printf(
289 void *NotUsed,
290 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
291 int argc, /* Number of arguments */
292 char **argv /* Text of each argument */
293){
drh9bb575f2004-09-06 17:24:11 +0000294 sqlite3 *db;
drhd1bf3512001-04-07 15:24:33 +0000295 Tcl_DString str;
296 int rc;
297 char *zErr = 0;
drh1211de32004-07-26 12:24:22 +0000298 char *zSql;
drhd1bf3512001-04-07 15:24:33 +0000299 char zBuf[30];
300 if( argc!=4 ){
301 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
302 " DB FORMAT STRING", 0);
303 return TCL_ERROR;
304 }
drhb86ccfb2003-01-28 23:13:10 +0000305 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000306 Tcl_DStringInit(&str);
drh1211de32004-07-26 12:24:22 +0000307 zSql = sqlite3_mprintf(argv[2], argv[3]);
308 rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
309 sqlite3_free(zSql);
drhd1bf3512001-04-07 15:24:33 +0000310 sprintf(zBuf, "%d", rc);
311 Tcl_AppendElement(interp, zBuf);
312 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
313 Tcl_DStringFree(&str);
danielk1977926aab22006-06-27 07:34:40 +0000314 if( zErr ) sqlite3_free(zErr);
drhc60d0442004-09-30 13:43:13 +0000315 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000316 return TCL_OK;
317}
318
319/*
drh5bd98ae2009-01-07 18:24:03 +0000320** Usage: sqlite3_exec_hex DB HEX
321**
322** Invoke the sqlite3_exec() on a string that is obtained by translating
323** HEX into ASCII. Most characters are translated as is. %HH becomes
324** a hex character.
325*/
326static int test_exec_hex(
327 void *NotUsed,
328 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
329 int argc, /* Number of arguments */
330 char **argv /* Text of each argument */
331){
332 sqlite3 *db;
333 Tcl_DString str;
334 int rc, i, j;
335 char *zErr = 0;
336 char *zHex;
337 char zSql[500];
338 char zBuf[30];
339 if( argc!=3 ){
340 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
341 " DB HEX", 0);
342 return TCL_ERROR;
343 }
344 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
345 zHex = argv[2];
346 for(i=j=0; i<sizeof(zSql) && zHex[j]; i++, j++){
347 if( zHex[j]=='%' && zHex[j+2] && zHex[j+2] ){
348 zSql[i] = (testHexToInt(zHex[j+1])<<4) + testHexToInt(zHex[j+2]);
349 j += 2;
350 }else{
351 zSql[i] = zHex[j];
352 }
353 }
354 zSql[i] = 0;
355 Tcl_DStringInit(&str);
356 rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
357 sprintf(zBuf, "%d", rc);
358 Tcl_AppendElement(interp, zBuf);
359 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
360 Tcl_DStringFree(&str);
361 if( zErr ) sqlite3_free(zErr);
362 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
363 return TCL_OK;
364}
365
366/*
drh27641702007-08-22 02:56:42 +0000367** Usage: db_enter DB
368** db_leave DB
369**
370** Enter or leave the mutex on a database connection.
371*/
372static int db_enter(
373 void *NotUsed,
374 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
375 int argc, /* Number of arguments */
376 char **argv /* Text of each argument */
377){
378 sqlite3 *db;
379 if( argc!=2 ){
380 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
381 " DB", 0);
382 return TCL_ERROR;
383 }
384 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
385 sqlite3_mutex_enter(db->mutex);
386 return TCL_OK;
387}
388static int db_leave(
389 void *NotUsed,
390 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
391 int argc, /* Number of arguments */
392 char **argv /* Text of each argument */
393){
394 sqlite3 *db;
395 if( argc!=2 ){
396 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
397 " DB", 0);
398 return TCL_ERROR;
399 }
400 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
401 sqlite3_mutex_leave(db->mutex);
402 return TCL_OK;
403}
404
405/*
drhb62c3352006-11-23 09:39:16 +0000406** Usage: sqlite3_exec DB SQL
407**
408** Invoke the sqlite3_exec interface using the open database DB
409*/
410static int test_exec(
411 void *NotUsed,
412 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
413 int argc, /* Number of arguments */
414 char **argv /* Text of each argument */
415){
416 sqlite3 *db;
417 Tcl_DString str;
418 int rc;
419 char *zErr = 0;
drh4e5dd852007-05-15 03:56:49 +0000420 char *zSql;
421 int i, j;
drhb62c3352006-11-23 09:39:16 +0000422 char zBuf[30];
423 if( argc!=3 ){
424 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
425 " DB SQL", 0);
426 return TCL_ERROR;
427 }
428 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
429 Tcl_DStringInit(&str);
drh4e5dd852007-05-15 03:56:49 +0000430 zSql = sqlite3_mprintf("%s", argv[2]);
431 for(i=j=0; zSql[i];){
432 if( zSql[i]=='%' ){
433 zSql[j++] = (testHexToInt(zSql[i+1])<<4) + testHexToInt(zSql[i+2]);
434 i += 3;
435 }else{
436 zSql[j++] = zSql[i++];
437 }
438 }
439 zSql[j] = 0;
440 rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
441 sqlite3_free(zSql);
drhb62c3352006-11-23 09:39:16 +0000442 sprintf(zBuf, "%d", rc);
443 Tcl_AppendElement(interp, zBuf);
444 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
445 Tcl_DStringFree(&str);
446 if( zErr ) sqlite3_free(zErr);
447 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
448 return TCL_OK;
449}
450
451/*
452** Usage: sqlite3_exec_nr DB SQL
453**
454** Invoke the sqlite3_exec interface using the open database DB. Discard
455** all results
456*/
457static int test_exec_nr(
458 void *NotUsed,
459 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
460 int argc, /* Number of arguments */
461 char **argv /* Text of each argument */
462){
463 sqlite3 *db;
464 int rc;
465 char *zErr = 0;
466 if( argc!=3 ){
467 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
468 " DB SQL", 0);
469 return TCL_ERROR;
470 }
471 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
472 rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
473 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
474 return TCL_OK;
475}
476
477/*
danielk19776f8a5032004-05-10 10:34:51 +0000478** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ...
drhd93d8a82003-06-16 03:08:18 +0000479**
drhbc6160b2009-04-08 15:45:31 +0000480** Test the %z format of sqlite_mprintf(). Use multiple mprintf() calls to
drhd93d8a82003-06-16 03:08:18 +0000481** concatenate arg0 through argn using separator as the separator.
482** Return the result.
483*/
484static int test_mprintf_z(
485 void *NotUsed,
486 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
487 int argc, /* Number of arguments */
488 char **argv /* Text of each argument */
489){
490 char *zResult = 0;
491 int i;
492
danielk1977ca0c8972007-09-01 09:02:53 +0000493 for(i=2; i<argc && (i==2 || zResult); i++){
drhbc6160b2009-04-08 15:45:31 +0000494 zResult = sqlite3_mprintf("%z%s%s", zResult, argv[1], argv[i]);
drhd93d8a82003-06-16 03:08:18 +0000495 }
496 Tcl_AppendResult(interp, zResult, 0);
drh17435752007-08-16 04:30:38 +0000497 sqlite3_free(zResult);
drhd93d8a82003-06-16 03:08:18 +0000498 return TCL_OK;
499}
500
501/*
drh05a82982006-03-19 13:00:25 +0000502** Usage: sqlite3_mprintf_n_test STRING
503**
drhbc6160b2009-04-08 15:45:31 +0000504** Test the %n format of sqlite_mprintf(). Return the length of the
drh05a82982006-03-19 13:00:25 +0000505** input string.
506*/
507static int test_mprintf_n(
508 void *NotUsed,
509 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
510 int argc, /* Number of arguments */
511 char **argv /* Text of each argument */
512){
513 char *zStr;
514 int n = 0;
drhbc6160b2009-04-08 15:45:31 +0000515 zStr = sqlite3_mprintf("%s%n", argv[1], &n);
drh17435752007-08-16 04:30:38 +0000516 sqlite3_free(zStr);
drh05a82982006-03-19 13:00:25 +0000517 Tcl_SetObjResult(interp, Tcl_NewIntObj(n));
518 return TCL_OK;
519}
520
521/*
drh68853902007-05-07 11:24:30 +0000522** Usage: sqlite3_snprintf_int SIZE FORMAT INT
523**
524** Test the of sqlite3_snprintf() routine. SIZE is the size of the
525** output buffer in bytes. The maximum size is 100. FORMAT is the
526** format string. INT is a single integer argument. The FORMAT
527** string must require no more than this one integer argument. If
528** You pass in a format string that requires more than one argument,
529** bad things will happen.
530*/
531static int test_snprintf_int(
532 void *NotUsed,
533 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
534 int argc, /* Number of arguments */
535 char **argv /* Text of each argument */
536){
537 char zStr[100];
538 int n = atoi(argv[1]);
drh68853902007-05-07 11:24:30 +0000539 const char *zFormat = argv[2];
540 int a1 = atoi(argv[3]);
drhdaf276d2007-06-15 18:53:14 +0000541 if( n>sizeof(zStr) ) n = sizeof(zStr);
drh76945742008-02-19 18:29:07 +0000542 sqlite3_snprintf(sizeof(zStr), zStr, "abcdefghijklmnopqrstuvwxyz");
drh68853902007-05-07 11:24:30 +0000543 sqlite3_snprintf(n, zStr, zFormat, a1);
544 Tcl_AppendResult(interp, zStr, 0);
545 return TCL_OK;
546}
547
shane8225f5a2008-07-31 02:05:04 +0000548#ifndef SQLITE_OMIT_GET_TABLE
549
drh68853902007-05-07 11:24:30 +0000550/*
drhd2b3e232008-01-23 14:51:49 +0000551** Usage: sqlite3_get_table_printf DB FORMAT STRING ?--no-counts?
drhd1bf3512001-04-07 15:24:33 +0000552**
danielk19776f8a5032004-05-10 10:34:51 +0000553** Invoke the sqlite3_get_table_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000554** DB. The SQL is the string FORMAT. The format string should contain
555** one %s or %q. STRING is the value inserted into %s or %q.
556*/
557static int test_get_table_printf(
558 void *NotUsed,
559 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
560 int argc, /* Number of arguments */
561 char **argv /* Text of each argument */
562){
drh9bb575f2004-09-06 17:24:11 +0000563 sqlite3 *db;
drhd1bf3512001-04-07 15:24:33 +0000564 Tcl_DString str;
565 int rc;
566 char *zErr = 0;
567 int nRow, nCol;
568 char **aResult;
569 int i;
570 char zBuf[30];
drh1211de32004-07-26 12:24:22 +0000571 char *zSql;
drhd2b3e232008-01-23 14:51:49 +0000572 int resCount = -1;
573 if( argc==5 ){
574 if( Tcl_GetInt(interp, argv[4], &resCount) ) return TCL_ERROR;
575 }
576 if( argc!=4 && argc!=5 ){
drhd1bf3512001-04-07 15:24:33 +0000577 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drhd2b3e232008-01-23 14:51:49 +0000578 " DB FORMAT STRING ?COUNT?", 0);
drhd1bf3512001-04-07 15:24:33 +0000579 return TCL_ERROR;
580 }
drhb86ccfb2003-01-28 23:13:10 +0000581 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000582 Tcl_DStringInit(&str);
drh1211de32004-07-26 12:24:22 +0000583 zSql = sqlite3_mprintf(argv[2],argv[3]);
drhd2b3e232008-01-23 14:51:49 +0000584 if( argc==5 ){
585 rc = sqlite3_get_table(db, zSql, &aResult, 0, 0, &zErr);
586 }else{
587 rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
588 resCount = (nRow+1)*nCol;
589 }
drh1211de32004-07-26 12:24:22 +0000590 sqlite3_free(zSql);
drhd1bf3512001-04-07 15:24:33 +0000591 sprintf(zBuf, "%d", rc);
592 Tcl_AppendElement(interp, zBuf);
593 if( rc==SQLITE_OK ){
drhd2b3e232008-01-23 14:51:49 +0000594 if( argc==4 ){
595 sprintf(zBuf, "%d", nRow);
596 Tcl_AppendElement(interp, zBuf);
597 sprintf(zBuf, "%d", nCol);
598 Tcl_AppendElement(interp, zBuf);
599 }
600 for(i=0; i<resCount; i++){
drhd1bf3512001-04-07 15:24:33 +0000601 Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
602 }
603 }else{
604 Tcl_AppendElement(interp, zErr);
605 }
danielk19776f8a5032004-05-10 10:34:51 +0000606 sqlite3_free_table(aResult);
danielk1977926aab22006-06-27 07:34:40 +0000607 if( zErr ) sqlite3_free(zErr);
drhc60d0442004-09-30 13:43:13 +0000608 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000609 return TCL_OK;
610}
611
shane8225f5a2008-07-31 02:05:04 +0000612#endif /* SQLITE_OMIT_GET_TABLE */
613
drhaf9ff332002-01-16 21:00:27 +0000614
615/*
danielk19776f8a5032004-05-10 10:34:51 +0000616** Usage: sqlite3_last_insert_rowid DB
drhaf9ff332002-01-16 21:00:27 +0000617**
618** Returns the integer ROWID of the most recent insert.
619*/
620static int test_last_rowid(
621 void *NotUsed,
622 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
623 int argc, /* Number of arguments */
624 char **argv /* Text of each argument */
625){
drh9bb575f2004-09-06 17:24:11 +0000626 sqlite3 *db;
drhaf9ff332002-01-16 21:00:27 +0000627 char zBuf[30];
628
629 if( argc!=2 ){
630 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
631 return TCL_ERROR;
632 }
drhb86ccfb2003-01-28 23:13:10 +0000633 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977c572ef72004-05-27 09:28:41 +0000634 sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db));
drhaf9ff332002-01-16 21:00:27 +0000635 Tcl_AppendResult(interp, zBuf, 0);
636 return SQLITE_OK;
637}
638
drhd1bf3512001-04-07 15:24:33 +0000639/*
drh25d65432004-07-22 15:02:25 +0000640** Usage: sqlite3_key DB KEY
641**
642** Set the codec key.
643*/
644static int test_key(
645 void *NotUsed,
646 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
647 int argc, /* Number of arguments */
648 char **argv /* Text of each argument */
649){
drhcaffb1a2012-01-30 18:00:31 +0000650#ifdef SQLITE_HAS_CODEC
drh9bb575f2004-09-06 17:24:11 +0000651 sqlite3 *db;
drh25d65432004-07-22 15:02:25 +0000652 const char *zKey;
653 int nKey;
654 if( argc!=3 ){
655 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
656 " FILENAME\"", 0);
657 return TCL_ERROR;
658 }
659 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
660 zKey = argv[2];
661 nKey = strlen(zKey);
drh25d65432004-07-22 15:02:25 +0000662 sqlite3_key(db, zKey, nKey);
663#endif
664 return TCL_OK;
665}
666
667/*
668** Usage: sqlite3_rekey DB KEY
669**
670** Change the codec key.
671*/
672static int test_rekey(
673 void *NotUsed,
674 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
675 int argc, /* Number of arguments */
676 char **argv /* Text of each argument */
677){
drhcaffb1a2012-01-30 18:00:31 +0000678#ifdef SQLITE_HAS_CODEC
drh9bb575f2004-09-06 17:24:11 +0000679 sqlite3 *db;
drh25d65432004-07-22 15:02:25 +0000680 const char *zKey;
681 int nKey;
682 if( argc!=3 ){
683 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
684 " FILENAME\"", 0);
685 return TCL_ERROR;
686 }
687 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
688 zKey = argv[2];
689 nKey = strlen(zKey);
drh25d65432004-07-22 15:02:25 +0000690 sqlite3_rekey(db, zKey, nKey);
691#endif
692 return TCL_OK;
693}
694
695/*
danielk19776f8a5032004-05-10 10:34:51 +0000696** Usage: sqlite3_close DB
drhd1bf3512001-04-07 15:24:33 +0000697**
danielk19776f8a5032004-05-10 10:34:51 +0000698** Closes the database opened by sqlite3_open.
drhd1bf3512001-04-07 15:24:33 +0000699*/
700static int sqlite_test_close(
701 void *NotUsed,
702 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
703 int argc, /* Number of arguments */
704 char **argv /* Text of each argument */
705){
drh9bb575f2004-09-06 17:24:11 +0000706 sqlite3 *db;
danielk197796d81f92004-06-19 03:33:57 +0000707 int rc;
drhd1bf3512001-04-07 15:24:33 +0000708 if( argc!=2 ){
709 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
710 " FILENAME\"", 0);
711 return TCL_ERROR;
712 }
drhb86ccfb2003-01-28 23:13:10 +0000713 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk197796d81f92004-06-19 03:33:57 +0000714 rc = sqlite3_close(db);
drh4f0c5872007-03-26 22:05:01 +0000715 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
drhd1bf3512001-04-07 15:24:33 +0000716 return TCL_OK;
717}
718
719/*
dan617dc862013-05-16 11:57:28 +0000720** Usage: sqlite3_close_v2 DB
721**
722** Closes the database opened by sqlite3_open.
723*/
724static int sqlite_test_close_v2(
725 void *NotUsed,
726 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
727 int argc, /* Number of arguments */
728 char **argv /* Text of each argument */
729){
730 sqlite3 *db;
731 int rc;
732 if( argc!=2 ){
733 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
734 " FILENAME\"", 0);
735 return TCL_ERROR;
736 }
737 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
738 rc = sqlite3_close_v2(db);
739 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
740 return TCL_OK;
741}
742
743/*
drhc22bd472002-05-10 13:14:07 +0000744** Implementation of the x_coalesce() function.
745** Return the first argument non-NULL argument.
746*/
drh4f0c5872007-03-26 22:05:01 +0000747static void t1_ifnullFunc(
748 sqlite3_context *context,
749 int argc,
750 sqlite3_value **argv
751){
drhc22bd472002-05-10 13:14:07 +0000752 int i;
753 for(i=0; i<argc; i++){
drh9c054832004-05-31 18:51:57 +0000754 if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
drh9310ef22007-04-27 17:16:20 +0000755 int n = sqlite3_value_bytes(argv[i]);
drh03d847e2005-12-09 20:21:58 +0000756 sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]),
drh9310ef22007-04-27 17:16:20 +0000757 n, SQLITE_TRANSIENT);
drhc22bd472002-05-10 13:14:07 +0000758 break;
759 }
760 }
761}
762
763/*
drhf0313812006-09-04 15:53:53 +0000764** These are test functions. hex8() interprets its argument as
765** UTF8 and returns a hex encoding. hex16le() interprets its argument
766** as UTF16le and returns a hex encoding.
767*/
768static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){
769 const unsigned char *z;
770 int i;
771 char zBuf[200];
772 z = sqlite3_value_text(argv[0]);
773 for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){
774 sprintf(&zBuf[i*2], "%02x", z[i]&0xff);
775 }
776 zBuf[i*2] = 0;
777 sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
778}
drhaf304692007-04-23 23:56:31 +0000779#ifndef SQLITE_OMIT_UTF16
drhf0313812006-09-04 15:53:53 +0000780static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){
781 const unsigned short int *z;
782 int i;
783 char zBuf[400];
784 z = sqlite3_value_text16(argv[0]);
785 for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){
786 sprintf(&zBuf[i*4], "%04x", z[i]&0xff);
787 }
788 zBuf[i*4] = 0;
789 sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
790}
drhaf304692007-04-23 23:56:31 +0000791#endif
drhf0313812006-09-04 15:53:53 +0000792
793/*
drhd1d9fc32004-01-07 19:24:48 +0000794** A structure into which to accumulate text.
795*/
796struct dstr {
797 int nAlloc; /* Space allocated */
798 int nUsed; /* Space used */
799 char *z; /* The space */
800};
801
802/*
803** Append text to a dstr
804*/
805static void dstrAppend(struct dstr *p, const char *z, int divider){
drh83cc1392012-04-19 18:04:28 +0000806 int n = (int)strlen(z);
drhd1d9fc32004-01-07 19:24:48 +0000807 if( p->nUsed + n + 2 > p->nAlloc ){
808 char *zNew;
809 p->nAlloc = p->nAlloc*2 + n + 200;
drh17435752007-08-16 04:30:38 +0000810 zNew = sqlite3_realloc(p->z, p->nAlloc);
drhd1d9fc32004-01-07 19:24:48 +0000811 if( zNew==0 ){
drh17435752007-08-16 04:30:38 +0000812 sqlite3_free(p->z);
drhd1d9fc32004-01-07 19:24:48 +0000813 memset(p, 0, sizeof(*p));
814 return;
815 }
816 p->z = zNew;
817 }
818 if( divider && p->nUsed>0 ){
819 p->z[p->nUsed++] = divider;
820 }
821 memcpy(&p->z[p->nUsed], z, n+1);
822 p->nUsed += n;
823}
824
825/*
danielk19774adee202004-05-08 08:23:19 +0000826** Invoked for each callback from sqlite3ExecFunc
drhd1d9fc32004-01-07 19:24:48 +0000827*/
828static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
829 struct dstr *p = (struct dstr*)pData;
830 int i;
831 for(i=0; i<argc; i++){
832 if( argv[i]==0 ){
833 dstrAppend(p, "NULL", ' ');
834 }else{
835 dstrAppend(p, argv[i], ' ');
836 }
837 }
838 return 0;
839}
840
841/*
danielk1977e35ee192004-06-26 09:50:11 +0000842** Implementation of the x_sqlite_exec() function. This function takes
drhc22bd472002-05-10 13:14:07 +0000843** a single argument and attempts to execute that argument as SQL code.
drh6cbe1f12002-07-01 00:31:36 +0000844** This is illegal and should set the SQLITE_MISUSE flag on the database.
drhd1d9fc32004-01-07 19:24:48 +0000845**
danielk19776f8a5032004-05-10 10:34:51 +0000846** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec()
drhd1d9fc32004-01-07 19:24:48 +0000847** from within a function call.
drhc22bd472002-05-10 13:14:07 +0000848**
849** This routine simulates the effect of having two threads attempt to
850** use the same database at the same time.
851*/
danielk197751ad0ec2004-05-24 12:39:02 +0000852static void sqlite3ExecFunc(
danielk19770ae8b832004-05-25 12:05:56 +0000853 sqlite3_context *context,
danielk197751ad0ec2004-05-24 12:39:02 +0000854 int argc,
855 sqlite3_value **argv
856){
drhd1d9fc32004-01-07 19:24:48 +0000857 struct dstr x;
858 memset(&x, 0, sizeof(x));
drh37527852006-03-16 16:19:56 +0000859 (void)sqlite3_exec((sqlite3*)sqlite3_user_data(context),
drh03d847e2005-12-09 20:21:58 +0000860 (char*)sqlite3_value_text(argv[0]),
drhd1d9fc32004-01-07 19:24:48 +0000861 execFuncCallback, &x, 0);
danielk1977d8123362004-06-12 09:25:12 +0000862 sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
drh17435752007-08-16 04:30:38 +0000863 sqlite3_free(x.z);
drhc22bd472002-05-10 13:14:07 +0000864}
865
866/*
danielk1977d7263922007-02-05 14:21:47 +0000867** Implementation of tkt2213func(), a scalar function that takes exactly
868** one argument. It has two interesting features:
869**
870** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*.
871** If the three pointers returned are not the same an SQL error is raised.
872**
drh85b623f2007-12-13 21:54:09 +0000873** * Otherwise it returns a copy of the text representation of its
danielk1977d7263922007-02-05 14:21:47 +0000874** argument in such a way as the VDBE representation is a Mem* cell
875** with the MEM_Term flag clear.
876**
877** Ticket #2213 can therefore be tested by evaluating the following
878** SQL expression:
879**
880** tkt2213func(tkt2213func('a string'));
881*/
882static void tkt2213Function(
883 sqlite3_context *context,
884 int argc,
885 sqlite3_value **argv
886){
887 int nText;
888 unsigned char const *zText1;
889 unsigned char const *zText2;
890 unsigned char const *zText3;
891
892 nText = sqlite3_value_bytes(argv[0]);
893 zText1 = sqlite3_value_text(argv[0]);
894 zText2 = sqlite3_value_text(argv[0]);
895 zText3 = sqlite3_value_text(argv[0]);
896
897 if( zText1!=zText2 || zText2!=zText3 ){
898 sqlite3_result_error(context, "tkt2213 is not fixed", -1);
899 }else{
900 char *zCopy = (char *)sqlite3_malloc(nText);
901 memcpy(zCopy, zText1, nText);
902 sqlite3_result_text(context, zCopy, nText, sqlite3_free);
903 }
904}
905
906/*
drh9310ef22007-04-27 17:16:20 +0000907** The following SQL function takes 4 arguments. The 2nd and
908** 4th argument must be one of these strings: 'text', 'text16',
909** or 'blob' corresponding to API functions
910**
911** sqlite3_value_text()
912** sqlite3_value_text16()
913** sqlite3_value_blob()
914**
915** The third argument is a string, either 'bytes' or 'bytes16' or 'noop',
916** corresponding to APIs:
917**
918** sqlite3_value_bytes()
919** sqlite3_value_bytes16()
920** noop
921**
922** The APIs designated by the 2nd through 4th arguments are applied
923** to the first argument in order. If the pointers returned by the
924** second and fourth are different, this routine returns 1. Otherwise,
925** this routine returns 0.
926**
927** This function is used to test to see when returned pointers from
928** the _text(), _text16() and _blob() APIs become invalidated.
929*/
930static void ptrChngFunction(
931 sqlite3_context *context,
932 int argc,
933 sqlite3_value **argv
934){
935 const void *p1, *p2;
936 const char *zCmd;
937 if( argc!=4 ) return;
938 zCmd = (const char*)sqlite3_value_text(argv[1]);
939 if( zCmd==0 ) return;
940 if( strcmp(zCmd,"text")==0 ){
941 p1 = (const void*)sqlite3_value_text(argv[0]);
942#ifndef SQLITE_OMIT_UTF16
943 }else if( strcmp(zCmd, "text16")==0 ){
944 p1 = (const void*)sqlite3_value_text16(argv[0]);
945#endif
946 }else if( strcmp(zCmd, "blob")==0 ){
947 p1 = (const void*)sqlite3_value_blob(argv[0]);
948 }else{
949 return;
950 }
951 zCmd = (const char*)sqlite3_value_text(argv[2]);
952 if( zCmd==0 ) return;
953 if( strcmp(zCmd,"bytes")==0 ){
954 sqlite3_value_bytes(argv[0]);
955#ifndef SQLITE_OMIT_UTF16
956 }else if( strcmp(zCmd, "bytes16")==0 ){
957 sqlite3_value_bytes16(argv[0]);
958#endif
959 }else if( strcmp(zCmd, "noop")==0 ){
960 /* do nothing */
961 }else{
962 return;
963 }
964 zCmd = (const char*)sqlite3_value_text(argv[3]);
965 if( zCmd==0 ) return;
966 if( strcmp(zCmd,"text")==0 ){
967 p2 = (const void*)sqlite3_value_text(argv[0]);
968#ifndef SQLITE_OMIT_UTF16
969 }else if( strcmp(zCmd, "text16")==0 ){
970 p2 = (const void*)sqlite3_value_text16(argv[0]);
971#endif
972 }else if( strcmp(zCmd, "blob")==0 ){
973 p2 = (const void*)sqlite3_value_blob(argv[0]);
974 }else{
975 return;
976 }
977 sqlite3_result_int(context, p1!=p2);
978}
979
drh4a8ee3d2013-12-14 13:44:22 +0000980/*
981** This SQL function returns a different answer each time it is called, even if
982** the arguments are the same.
983*/
984static void nondeterministicFunction(
985 sqlite3_context *context,
986 int argc,
987 sqlite3_value **argv
988){
989 static int cnt = 0;
990 sqlite3_result_int(context, cnt++);
991}
drh9310ef22007-04-27 17:16:20 +0000992
993/*
drh4a8ee3d2013-12-14 13:44:22 +0000994** Usage: sqlite3_create_function DB
drhc22bd472002-05-10 13:14:07 +0000995**
danielk19776f8a5032004-05-10 10:34:51 +0000996** Call the sqlite3_create_function API on the given database in order
drhc22bd472002-05-10 13:14:07 +0000997** to create a function named "x_coalesce". This function does the same thing
998** as the "coalesce" function. This function also registers an SQL function
danielk1977e35ee192004-06-26 09:50:11 +0000999** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec()
drhc22bd472002-05-10 13:14:07 +00001000** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
1001** The effect is similar to trying to use the same database connection from
1002** two threads at the same time.
1003**
1004** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +00001005** sqlite3_create_function function while a query is in progress in order
drhc22bd472002-05-10 13:14:07 +00001006** to test the SQLITE_MISUSE detection logic.
1007*/
drhc2eef3b2002-08-31 18:53:06 +00001008static int test_create_function(
drhc22bd472002-05-10 13:14:07 +00001009 void *NotUsed,
1010 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1011 int argc, /* Number of arguments */
1012 char **argv /* Text of each argument */
1013){
drhc60d0442004-09-30 13:43:13 +00001014 int rc;
drh9bb575f2004-09-06 17:24:11 +00001015 sqlite3 *db;
danielk1977312d6b32004-06-29 13:18:23 +00001016
drhc22bd472002-05-10 13:14:07 +00001017 if( argc!=2 ){
1018 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
danielk19774397de52005-01-12 12:44:03 +00001019 " DB\"", 0);
drhc22bd472002-05-10 13:14:07 +00001020 return TCL_ERROR;
1021 }
drhb86ccfb2003-01-28 23:13:10 +00001022 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drh4a8ee3d2013-12-14 13:44:22 +00001023 rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_UTF8, 0,
drh4f0c5872007-03-26 22:05:01 +00001024 t1_ifnullFunc, 0, 0);
drh235a8182006-09-13 19:21:28 +00001025 if( rc==SQLITE_OK ){
drh4a8ee3d2013-12-14 13:44:22 +00001026 rc = sqlite3_create_function(db, "hex8", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
1027 0, hex8Func, 0, 0);
drh235a8182006-09-13 19:21:28 +00001028 }
drhaf304692007-04-23 23:56:31 +00001029#ifndef SQLITE_OMIT_UTF16
drh235a8182006-09-13 19:21:28 +00001030 if( rc==SQLITE_OK ){
drh4a8ee3d2013-12-14 13:44:22 +00001031 rc = sqlite3_create_function(db, "hex16", 1, SQLITE_UTF16 | SQLITE_DETERMINISTIC,
1032 0, hex16Func, 0, 0);
drh235a8182006-09-13 19:21:28 +00001033 }
drhaf304692007-04-23 23:56:31 +00001034#endif
danielk1977d7263922007-02-05 14:21:47 +00001035 if( rc==SQLITE_OK ){
1036 rc = sqlite3_create_function(db, "tkt2213func", 1, SQLITE_ANY, 0,
1037 tkt2213Function, 0, 0);
1038 }
drh9310ef22007-04-27 17:16:20 +00001039 if( rc==SQLITE_OK ){
1040 rc = sqlite3_create_function(db, "pointer_change", 4, SQLITE_ANY, 0,
1041 ptrChngFunction, 0, 0);
1042 }
danielk1977312d6b32004-06-29 13:18:23 +00001043
drh4a8ee3d2013-12-14 13:44:22 +00001044 /* Functions counter1() and counter2() have the same implementation - they
1045 ** both return an ascending integer with each call. But counter1() is marked
1046 ** as non-deterministic and counter2() is marked as deterministic.
1047 */
1048 if( rc==SQLITE_OK ){
1049 rc = sqlite3_create_function(db, "counter1", -1, SQLITE_UTF8,
1050 0, nondeterministicFunction, 0, 0);
1051 }
1052 if( rc==SQLITE_OK ){
1053 rc = sqlite3_create_function(db, "counter2", -1, SQLITE_UTF8|SQLITE_DETERMINISTIC,
1054 0, nondeterministicFunction, 0, 0);
1055 }
1056
drh5436dc22004-11-14 04:04:17 +00001057#ifndef SQLITE_OMIT_UTF16
danielk1977312d6b32004-06-29 13:18:23 +00001058 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
1059 ** because it is not tested anywhere else. */
drhc60d0442004-09-30 13:43:13 +00001060 if( rc==SQLITE_OK ){
drheee4c8c2008-02-18 22:24:57 +00001061 const void *zUtf16;
danielk1977576ec6b2005-01-21 11:55:25 +00001062 sqlite3_value *pVal;
drhf3a65f72007-08-22 20:18:21 +00001063 sqlite3_mutex_enter(db->mutex);
1064 pVal = sqlite3ValueNew(db);
drhb21c8cd2007-08-21 19:33:56 +00001065 sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
danielk1977a7a8e142008-02-13 18:25:27 +00001066 zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
drhf3a65f72007-08-22 20:18:21 +00001067 if( db->mallocFailed ){
1068 rc = SQLITE_NOMEM;
1069 }else{
danielk1977a7a8e142008-02-13 18:25:27 +00001070 rc = sqlite3_create_function16(db, zUtf16,
1071 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
drhf3a65f72007-08-22 20:18:21 +00001072 }
drhc60d0442004-09-30 13:43:13 +00001073 sqlite3ValueFree(pVal);
drhf3a65f72007-08-22 20:18:21 +00001074 sqlite3_mutex_leave(db->mutex);
drhc60d0442004-09-30 13:43:13 +00001075 }
drh5436dc22004-11-14 04:04:17 +00001076#endif
1077
drhc60d0442004-09-30 13:43:13 +00001078 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drh4f0c5872007-03-26 22:05:01 +00001079 Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
drhc22bd472002-05-10 13:14:07 +00001080 return TCL_OK;
1081}
1082
1083/*
1084** Routines to implement the x_count() aggregate function.
drh90669c12006-01-20 15:45:36 +00001085**
1086** x_count() counts the number of non-null arguments. But there are
1087** some twists for testing purposes.
1088**
1089** If the argument to x_count() is 40 then a UTF-8 error is reported
1090** on the step function. If x_count(41) is seen, then a UTF-16 error
1091** is reported on the step function. If the total count is 42, then
1092** a UTF-8 error is reported on the finalize function.
drhc22bd472002-05-10 13:14:07 +00001093*/
drh4f0c5872007-03-26 22:05:01 +00001094typedef struct t1CountCtx t1CountCtx;
1095struct t1CountCtx {
drhc22bd472002-05-10 13:14:07 +00001096 int n;
1097};
drh4f0c5872007-03-26 22:05:01 +00001098static void t1CountStep(
1099 sqlite3_context *context,
1100 int argc,
1101 sqlite3_value **argv
1102){
1103 t1CountCtx *p;
drh4f26d6c2004-05-26 23:25:30 +00001104 p = sqlite3_aggregate_context(context, sizeof(*p));
drh9c054832004-05-31 18:51:57 +00001105 if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
drhc22bd472002-05-10 13:14:07 +00001106 p->n++;
1107 }
drh90669c12006-01-20 15:45:36 +00001108 if( argc>0 ){
1109 int v = sqlite3_value_int(argv[0]);
1110 if( v==40 ){
1111 sqlite3_result_error(context, "value of 40 handed to x_count", -1);
danielk1977a1686c92006-01-23 07:52:37 +00001112#ifndef SQLITE_OMIT_UTF16
drh90669c12006-01-20 15:45:36 +00001113 }else if( v==41 ){
1114 const char zUtf16ErrMsg[] = { 0, 0x61, 0, 0x62, 0, 0x63, 0, 0, 0};
1115 sqlite3_result_error16(context, &zUtf16ErrMsg[1-SQLITE_BIGENDIAN], -1);
danielk1977a1686c92006-01-23 07:52:37 +00001116#endif
drh90669c12006-01-20 15:45:36 +00001117 }
1118 }
drhc22bd472002-05-10 13:14:07 +00001119}
drh4f0c5872007-03-26 22:05:01 +00001120static void t1CountFinalize(sqlite3_context *context){
1121 t1CountCtx *p;
drh4f26d6c2004-05-26 23:25:30 +00001122 p = sqlite3_aggregate_context(context, sizeof(*p));
drh90669c12006-01-20 15:45:36 +00001123 if( p ){
1124 if( p->n==42 ){
1125 sqlite3_result_error(context, "x_count totals to 42", -1);
1126 }else{
1127 sqlite3_result_int(context, p ? p->n : 0);
1128 }
1129 }
drhc22bd472002-05-10 13:14:07 +00001130}
1131
danielk1977c5512882009-08-10 04:37:49 +00001132#ifndef SQLITE_OMIT_DEPRECATED
danielk1977fa18bec2007-09-03 11:04:22 +00001133static void legacyCountStep(
1134 sqlite3_context *context,
1135 int argc,
1136 sqlite3_value **argv
1137){
1138 /* no-op */
1139}
shaneeec556d2008-10-12 00:27:53 +00001140
danielk1977fa18bec2007-09-03 11:04:22 +00001141static void legacyCountFinalize(sqlite3_context *context){
1142 sqlite3_result_int(context, sqlite3_aggregate_count(context));
1143}
shaneeec556d2008-10-12 00:27:53 +00001144#endif
danielk1977fa18bec2007-09-03 11:04:22 +00001145
drhc22bd472002-05-10 13:14:07 +00001146/*
danielk1977fa18bec2007-09-03 11:04:22 +00001147** Usage: sqlite3_create_aggregate DB
drhc22bd472002-05-10 13:14:07 +00001148**
danielk19776f8a5032004-05-10 10:34:51 +00001149** Call the sqlite3_create_function API on the given database in order
danielk1977fa18bec2007-09-03 11:04:22 +00001150** to create a function named "x_count". This function is similar
1151** to the built-in count() function, with a few special quirks
1152** for testing the sqlite3_result_error() APIs.
drhc22bd472002-05-10 13:14:07 +00001153**
1154** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +00001155** sqlite3_create_aggregate function while a query is in progress in order
drh90669c12006-01-20 15:45:36 +00001156** to test the SQLITE_MISUSE detection logic. See misuse.test.
1157**
1158** This routine was later extended to test the use of sqlite3_result_error()
1159** within aggregate functions.
danielk1977fa18bec2007-09-03 11:04:22 +00001160**
1161** Later: It is now also extended to register the aggregate function
1162** "legacy_count()" with the supplied database handle. This is used
1163** to test the deprecated sqlite3_aggregate_count() API.
drhc22bd472002-05-10 13:14:07 +00001164*/
drhc2eef3b2002-08-31 18:53:06 +00001165static int test_create_aggregate(
drhc22bd472002-05-10 13:14:07 +00001166 void *NotUsed,
1167 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1168 int argc, /* Number of arguments */
1169 char **argv /* Text of each argument */
1170){
drh9bb575f2004-09-06 17:24:11 +00001171 sqlite3 *db;
drhc60d0442004-09-30 13:43:13 +00001172 int rc;
drhc22bd472002-05-10 13:14:07 +00001173 if( argc!=2 ){
1174 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1175 " FILENAME\"", 0);
1176 return TCL_ERROR;
1177 }
drhb86ccfb2003-01-28 23:13:10 +00001178 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +00001179 rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
drh4f0c5872007-03-26 22:05:01 +00001180 t1CountStep,t1CountFinalize);
drhc60d0442004-09-30 13:43:13 +00001181 if( rc==SQLITE_OK ){
danielk1977fa18bec2007-09-03 11:04:22 +00001182 rc = sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
drh4f0c5872007-03-26 22:05:01 +00001183 t1CountStep,t1CountFinalize);
drhc60d0442004-09-30 13:43:13 +00001184 }
shaneeec556d2008-10-12 00:27:53 +00001185#ifndef SQLITE_OMIT_DEPRECATED
danielk1977fa18bec2007-09-03 11:04:22 +00001186 if( rc==SQLITE_OK ){
1187 rc = sqlite3_create_function(db, "legacy_count", 0, SQLITE_ANY, 0, 0,
1188 legacyCountStep, legacyCountFinalize
1189 );
1190 }
shaneeec556d2008-10-12 00:27:53 +00001191#endif
drhc60d0442004-09-30 13:43:13 +00001192 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk1977fa18bec2007-09-03 11:04:22 +00001193 Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
drhc22bd472002-05-10 13:14:07 +00001194 return TCL_OK;
1195}
1196
1197
drh3c23a882007-01-09 14:01:13 +00001198/*
1199** Usage: printf TEXT
1200**
1201** Send output to printf. Use this rather than puts to merge the output
1202** in the correct sequence with debugging printfs inserted into C code.
1203** Puts uses a separate buffer and debugging statements will be out of
1204** sequence if it is used.
1205*/
1206static int test_printf(
1207 void *NotUsed,
1208 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1209 int argc, /* Number of arguments */
1210 char **argv /* Text of each argument */
1211){
1212 if( argc!=2 ){
1213 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1214 " TEXT\"", 0);
1215 return TCL_ERROR;
1216 }
1217 printf("%s\n", argv[1]);
1218 return TCL_OK;
1219}
1220
1221
drhc22bd472002-05-10 13:14:07 +00001222
1223/*
danielk19776f8a5032004-05-10 10:34:51 +00001224** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
drhd1bf3512001-04-07 15:24:33 +00001225**
1226** Call mprintf with three integer arguments
1227*/
danielk19776f8a5032004-05-10 10:34:51 +00001228static int sqlite3_mprintf_int(
drhd1bf3512001-04-07 15:24:33 +00001229 void *NotUsed,
1230 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1231 int argc, /* Number of arguments */
1232 char **argv /* Text of each argument */
1233){
1234 int a[3], i;
1235 char *z;
1236 if( argc!=5 ){
1237 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1238 " FORMAT INT INT INT\"", 0);
1239 return TCL_ERROR;
1240 }
1241 for(i=2; i<5; i++){
1242 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
1243 }
danielk19776f8a5032004-05-10 10:34:51 +00001244 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
drhd1bf3512001-04-07 15:24:33 +00001245 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +00001246 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +00001247 return TCL_OK;
1248}
1249
1250/*
drhe9707672004-06-25 01:10:48 +00001251** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
1252**
1253** Call mprintf with three 64-bit integer arguments
1254*/
1255static int sqlite3_mprintf_int64(
1256 void *NotUsed,
1257 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1258 int argc, /* Number of arguments */
1259 char **argv /* Text of each argument */
1260){
1261 int i;
1262 sqlite_int64 a[3];
1263 char *z;
1264 if( argc!=5 ){
1265 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1266 " FORMAT INT INT INT\"", 0);
1267 return TCL_ERROR;
1268 }
1269 for(i=2; i<5; i++){
shaneh5f1d6b62010-09-30 16:51:25 +00001270 if( sqlite3Atoi64(argv[i], &a[i-2], 1000000, SQLITE_UTF8) ){
drhe9707672004-06-25 01:10:48 +00001271 Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
1272 return TCL_ERROR;
1273 }
1274 }
1275 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
1276 Tcl_AppendResult(interp, z, 0);
1277 sqlite3_free(z);
1278 return TCL_OK;
1279}
1280
1281/*
drhc5cad1e2009-02-01 00:21:09 +00001282** Usage: sqlite3_mprintf_long FORMAT INTEGER INTEGER INTEGER
1283**
1284** Call mprintf with three long integer arguments. This might be the
1285** same as sqlite3_mprintf_int or sqlite3_mprintf_int64, depending on
1286** platform.
1287*/
1288static int sqlite3_mprintf_long(
1289 void *NotUsed,
1290 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1291 int argc, /* Number of arguments */
1292 char **argv /* Text of each argument */
1293){
1294 int i;
1295 long int a[3];
1296 int b[3];
1297 char *z;
1298 if( argc!=5 ){
1299 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1300 " FORMAT INT INT INT\"", 0);
1301 return TCL_ERROR;
1302 }
1303 for(i=2; i<5; i++){
1304 if( Tcl_GetInt(interp, argv[i], &b[i-2]) ) return TCL_ERROR;
1305 a[i-2] = (long int)b[i-2];
drh7ed0cae2009-02-03 16:25:47 +00001306 a[i-2] &= (((u64)1)<<(sizeof(int)*8))-1;
drhc5cad1e2009-02-01 00:21:09 +00001307 }
1308 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
1309 Tcl_AppendResult(interp, z, 0);
1310 sqlite3_free(z);
1311 return TCL_OK;
1312}
1313
1314/*
danielk19776f8a5032004-05-10 10:34:51 +00001315** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
drhd1bf3512001-04-07 15:24:33 +00001316**
1317** Call mprintf with two integer arguments and one string argument
1318*/
danielk19776f8a5032004-05-10 10:34:51 +00001319static int sqlite3_mprintf_str(
drhd1bf3512001-04-07 15:24:33 +00001320 void *NotUsed,
1321 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1322 int argc, /* Number of arguments */
1323 char **argv /* Text of each argument */
1324){
1325 int a[3], i;
1326 char *z;
chwf220b242002-06-16 04:54:28 +00001327 if( argc<4 || argc>5 ){
drhd1bf3512001-04-07 15:24:33 +00001328 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
chwf220b242002-06-16 04:54:28 +00001329 " FORMAT INT INT ?STRING?\"", 0);
drhd1bf3512001-04-07 15:24:33 +00001330 return TCL_ERROR;
1331 }
1332 for(i=2; i<4; i++){
1333 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
1334 }
danielk19776f8a5032004-05-10 10:34:51 +00001335 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
drhd1bf3512001-04-07 15:24:33 +00001336 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +00001337 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +00001338 return TCL_OK;
1339}
1340
1341/*
drhb3738b62007-03-31 15:02:49 +00001342** Usage: sqlite3_snprintf_str INTEGER FORMAT INTEGER INTEGER STRING
1343**
1344** Call mprintf with two integer arguments and one string argument
1345*/
1346static int sqlite3_snprintf_str(
1347 void *NotUsed,
1348 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1349 int argc, /* Number of arguments */
1350 char **argv /* Text of each argument */
1351){
1352 int a[3], i;
1353 int n;
1354 char *z;
1355 if( argc<5 || argc>6 ){
1356 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1357 " INT FORMAT INT INT ?STRING?\"", 0);
1358 return TCL_ERROR;
1359 }
1360 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
1361 if( n<0 ){
1362 Tcl_AppendResult(interp, "N must be non-negative", 0);
1363 return TCL_ERROR;
1364 }
1365 for(i=3; i<5; i++){
1366 if( Tcl_GetInt(interp, argv[i], &a[i-3]) ) return TCL_ERROR;
1367 }
1368 z = sqlite3_malloc( n+1 );
1369 sqlite3_snprintf(n, z, argv[2], a[0], a[1], argc>4 ? argv[5] : NULL);
1370 Tcl_AppendResult(interp, z, 0);
1371 sqlite3_free(z);
1372 return TCL_OK;
1373}
1374
1375/*
drh63782852005-08-30 19:30:59 +00001376** Usage: sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE
drhd1bf3512001-04-07 15:24:33 +00001377**
1378** Call mprintf with two integer arguments and one double argument
1379*/
danielk19776f8a5032004-05-10 10:34:51 +00001380static int sqlite3_mprintf_double(
drhd1bf3512001-04-07 15:24:33 +00001381 void *NotUsed,
1382 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1383 int argc, /* Number of arguments */
1384 char **argv /* Text of each argument */
1385){
1386 int a[3], i;
1387 double r;
1388 char *z;
1389 if( argc!=5 ){
1390 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drh63782852005-08-30 19:30:59 +00001391 " FORMAT INT INT DOUBLE\"", 0);
drhd1bf3512001-04-07 15:24:33 +00001392 return TCL_ERROR;
1393 }
1394 for(i=2; i<4; i++){
1395 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
1396 }
1397 if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +00001398 z = sqlite3_mprintf(argv[1], a[0], a[1], r);
drhd1bf3512001-04-07 15:24:33 +00001399 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +00001400 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +00001401 return TCL_OK;
1402}
1403
1404/*
drh63782852005-08-30 19:30:59 +00001405** Usage: sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE
drhb621c232004-02-21 19:41:04 +00001406**
1407** Call mprintf with a single double argument which is the product of the
1408** two arguments given above. This is used to generate overflow and underflow
1409** doubles to test that they are converted properly.
1410*/
danielk19776f8a5032004-05-10 10:34:51 +00001411static int sqlite3_mprintf_scaled(
drhb621c232004-02-21 19:41:04 +00001412 void *NotUsed,
1413 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1414 int argc, /* Number of arguments */
1415 char **argv /* Text of each argument */
1416){
1417 int i;
1418 double r[2];
1419 char *z;
1420 if( argc!=4 ){
1421 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1422 " FORMAT DOUBLE DOUBLE\"", 0);
1423 return TCL_ERROR;
1424 }
1425 for(i=2; i<4; i++){
1426 if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
1427 }
danielk19776f8a5032004-05-10 10:34:51 +00001428 z = sqlite3_mprintf(argv[1], r[0]*r[1]);
drhb621c232004-02-21 19:41:04 +00001429 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +00001430 sqlite3_free(z);
drhb621c232004-02-21 19:41:04 +00001431 return TCL_OK;
1432}
1433
1434/*
drhe29b1a02004-07-17 21:56:09 +00001435** Usage: sqlite3_mprintf_stronly FORMAT STRING
1436**
1437** Call mprintf with a single double argument which is the product of the
1438** two arguments given above. This is used to generate overflow and underflow
1439** doubles to test that they are converted properly.
1440*/
1441static int sqlite3_mprintf_stronly(
1442 void *NotUsed,
1443 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1444 int argc, /* Number of arguments */
1445 char **argv /* Text of each argument */
1446){
1447 char *z;
1448 if( argc!=3 ){
1449 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1450 " FORMAT STRING\"", 0);
1451 return TCL_ERROR;
1452 }
1453 z = sqlite3_mprintf(argv[1], argv[2]);
1454 Tcl_AppendResult(interp, z, 0);
1455 sqlite3_free(z);
1456 return TCL_OK;
1457}
1458
1459/*
drh63782852005-08-30 19:30:59 +00001460** Usage: sqlite3_mprintf_hexdouble FORMAT HEX
1461**
1462** Call mprintf with a single double argument which is derived from the
1463** hexadecimal encoding of an IEEE double.
1464*/
1465static int sqlite3_mprintf_hexdouble(
1466 void *NotUsed,
1467 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1468 int argc, /* Number of arguments */
1469 char **argv /* Text of each argument */
1470){
1471 char *z;
1472 double r;
shane5e73db32008-07-08 03:04:58 +00001473 unsigned int x1, x2;
1474 sqlite_uint64 d;
drh63782852005-08-30 19:30:59 +00001475 if( argc!=3 ){
1476 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1477 " FORMAT STRING\"", 0);
1478 return TCL_ERROR;
1479 }
1480 if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){
1481 Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0);
1482 return TCL_ERROR;
1483 }
1484 d = x2;
1485 d = (d<<32) + x1;
1486 memcpy(&r, &d, sizeof(r));
1487 z = sqlite3_mprintf(argv[1], r);
1488 Tcl_AppendResult(interp, z, 0);
1489 sqlite3_free(z);
1490 return TCL_OK;
1491}
1492
1493/*
danielk1977c1def3e2008-08-30 13:25:10 +00001494** Usage: sqlite3_enable_shared_cache ?BOOLEAN?
danielk1977aef0bf62005-12-30 16:28:01 +00001495**
1496*/
drh6f7adc82006-01-11 21:41:20 +00001497#if !defined(SQLITE_OMIT_SHARED_CACHE)
1498static int test_enable_shared(
danielk197752622822006-01-09 09:59:49 +00001499 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
danielk1977aef0bf62005-12-30 16:28:01 +00001500 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1501 int objc, /* Number of arguments */
1502 Tcl_Obj *CONST objv[] /* Command arguments */
1503){
1504 int rc;
1505 int enable;
danielk197752622822006-01-09 09:59:49 +00001506 int ret = 0;
danielk1977aef0bf62005-12-30 16:28:01 +00001507
danielk1977c1def3e2008-08-30 13:25:10 +00001508 if( objc!=2 && objc!=1 ){
1509 Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?");
danielk1977aef0bf62005-12-30 16:28:01 +00001510 return TCL_ERROR;
1511 }
danielk1977502b4e02008-09-02 14:07:24 +00001512 ret = sqlite3GlobalConfig.sharedCacheEnabled;
danielk1977c1def3e2008-08-30 13:25:10 +00001513
1514 if( objc==2 ){
1515 if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){
1516 return TCL_ERROR;
1517 }
1518 rc = sqlite3_enable_shared_cache(enable);
1519 if( rc!=SQLITE_OK ){
1520 Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
1521 return TCL_ERROR;
1522 }
danielk1977aef0bf62005-12-30 16:28:01 +00001523 }
danielk197752622822006-01-09 09:59:49 +00001524 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret));
danielk1977aef0bf62005-12-30 16:28:01 +00001525 return TCL_OK;
1526}
1527#endif
1528
drh16a9b832007-05-05 18:39:25 +00001529
1530
danielk1977aef0bf62005-12-30 16:28:01 +00001531/*
drh4ac285a2006-09-15 07:28:50 +00001532** Usage: sqlite3_extended_result_codes DB BOOLEAN
1533**
1534*/
1535static int test_extended_result_codes(
1536 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1537 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1538 int objc, /* Number of arguments */
1539 Tcl_Obj *CONST objv[] /* Command arguments */
1540){
1541 int enable;
1542 sqlite3 *db;
1543
1544 if( objc!=3 ){
1545 Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN");
1546 return TCL_ERROR;
1547 }
1548 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1549 if( Tcl_GetBooleanFromObj(interp, objv[2], &enable) ) return TCL_ERROR;
1550 sqlite3_extended_result_codes(db, enable);
1551 return TCL_OK;
1552}
1553
1554/*
danielk1977161fb792006-01-24 10:58:21 +00001555** Usage: sqlite3_libversion_number
1556**
1557*/
1558static int test_libversion_number(
1559 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1560 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1561 int objc, /* Number of arguments */
1562 Tcl_Obj *CONST objv[] /* Command arguments */
1563){
1564 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_libversion_number()));
1565 return TCL_OK;
1566}
1567
1568/*
danielk1977deb802c2006-02-09 13:43:28 +00001569** Usage: sqlite3_table_column_metadata DB dbname tblname colname
1570**
1571*/
danielk1977deb802c2006-02-09 13:43:28 +00001572static int test_table_column_metadata(
1573 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1574 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1575 int objc, /* Number of arguments */
1576 Tcl_Obj *CONST objv[] /* Command arguments */
1577){
1578 sqlite3 *db;
1579 const char *zDb;
1580 const char *zTbl;
1581 const char *zCol;
1582 int rc;
1583 Tcl_Obj *pRet;
1584
1585 const char *zDatatype;
1586 const char *zCollseq;
1587 int notnull;
1588 int primarykey;
1589 int autoincrement;
1590
drh45d1b202014-12-09 22:24:42 +00001591 if( objc!=5 && objc!=4 ){
danielk1977deb802c2006-02-09 13:43:28 +00001592 Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname");
1593 return TCL_ERROR;
1594 }
1595 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1596 zDb = Tcl_GetString(objv[2]);
1597 zTbl = Tcl_GetString(objv[3]);
drh45d1b202014-12-09 22:24:42 +00001598 zCol = objc==5 ? Tcl_GetString(objv[4]) : 0;
danielk1977deb802c2006-02-09 13:43:28 +00001599
1600 if( strlen(zDb)==0 ) zDb = 0;
1601
1602 rc = sqlite3_table_column_metadata(db, zDb, zTbl, zCol,
1603 &zDatatype, &zCollseq, &notnull, &primarykey, &autoincrement);
1604
1605 if( rc!=SQLITE_OK ){
1606 Tcl_AppendResult(interp, sqlite3_errmsg(db), 0);
1607 return TCL_ERROR;
1608 }
1609
1610 pRet = Tcl_NewObj();
1611 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zDatatype, -1));
1612 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zCollseq, -1));
1613 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(notnull));
1614 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(primarykey));
1615 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(autoincrement));
1616 Tcl_SetObjResult(interp, pRet);
1617
1618 return TCL_OK;
1619}
danielk1977deb802c2006-02-09 13:43:28 +00001620
danielk1977dcbb5d32007-05-04 18:36:44 +00001621#ifndef SQLITE_OMIT_INCRBLOB
1622
dan61c7f592010-10-26 18:42:52 +00001623static int blobHandleFromObj(
1624 Tcl_Interp *interp,
1625 Tcl_Obj *pObj,
1626 sqlite3_blob **ppBlob
1627){
1628 char *z;
1629 int n;
1630
1631 z = Tcl_GetStringFromObj(pObj, &n);
1632 if( n==0 ){
1633 *ppBlob = 0;
1634 }else{
1635 int notUsed;
1636 Tcl_Channel channel;
1637 ClientData instanceData;
1638
1639 channel = Tcl_GetChannel(interp, z, &notUsed);
1640 if( !channel ) return TCL_ERROR;
1641
1642 Tcl_Flush(channel);
1643 Tcl_Seek(channel, 0, SEEK_SET);
1644
1645 instanceData = Tcl_GetChannelInstanceData(channel);
1646 *ppBlob = *((sqlite3_blob **)instanceData);
1647 }
1648
1649 return TCL_OK;
1650}
1651
dan4e76cc32010-10-20 18:56:04 +00001652static int test_blob_reopen(
1653 ClientData clientData, /* Not used */
1654 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1655 int objc, /* Number of arguments */
1656 Tcl_Obj *CONST objv[] /* Command arguments */
1657){
1658 Tcl_WideInt iRowid;
dan4e76cc32010-10-20 18:56:04 +00001659 sqlite3_blob *pBlob;
dan4e76cc32010-10-20 18:56:04 +00001660 int rc;
1661
dan4e76cc32010-10-20 18:56:04 +00001662 if( objc!=3 ){
1663 Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL ROWID");
1664 return TCL_ERROR;
1665 }
1666
dan61c7f592010-10-26 18:42:52 +00001667 if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
1668 if( Tcl_GetWideIntFromObj(interp, objv[2], &iRowid) ) return TCL_ERROR;
dan4e76cc32010-10-20 18:56:04 +00001669
1670 rc = sqlite3_blob_reopen(pBlob, iRowid);
1671 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +00001672 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
dan4e76cc32010-10-20 18:56:04 +00001673 }
1674
1675 return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
1676}
1677
danielk1977dcbb5d32007-05-04 18:36:44 +00001678#endif
drhc2e87a32006-06-27 15:16:14 +00001679
danielk1977deb802c2006-02-09 13:43:28 +00001680/*
danielk1977a393c032007-05-07 14:58:53 +00001681** Usage: sqlite3_create_collation_v2 DB-HANDLE NAME CMP-PROC DEL-PROC
danielk1977a9808b32007-05-07 09:32:45 +00001682**
1683** This Tcl proc is used for testing the experimental
danielk1977a393c032007-05-07 14:58:53 +00001684** sqlite3_create_collation_v2() interface.
danielk1977a9808b32007-05-07 09:32:45 +00001685*/
1686struct TestCollationX {
1687 Tcl_Interp *interp;
1688 Tcl_Obj *pCmp;
1689 Tcl_Obj *pDel;
1690};
1691typedef struct TestCollationX TestCollationX;
1692static void testCreateCollationDel(void *pCtx){
1693 TestCollationX *p = (TestCollationX *)pCtx;
1694
1695 int rc = Tcl_EvalObjEx(p->interp, p->pDel, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL);
1696 if( rc!=TCL_OK ){
1697 Tcl_BackgroundError(p->interp);
1698 }
1699
1700 Tcl_DecrRefCount(p->pCmp);
1701 Tcl_DecrRefCount(p->pDel);
1702 sqlite3_free((void *)p);
1703}
1704static int testCreateCollationCmp(
1705 void *pCtx,
1706 int nLeft,
1707 const void *zLeft,
1708 int nRight,
1709 const void *zRight
1710){
1711 TestCollationX *p = (TestCollationX *)pCtx;
1712 Tcl_Obj *pScript = Tcl_DuplicateObj(p->pCmp);
1713 int iRes = 0;
1714
1715 Tcl_IncrRefCount(pScript);
1716 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zLeft, nLeft));
1717 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zRight,nRight));
1718
1719 if( TCL_OK!=Tcl_EvalObjEx(p->interp, pScript, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL)
1720 || TCL_OK!=Tcl_GetIntFromObj(p->interp, Tcl_GetObjResult(p->interp), &iRes)
1721 ){
1722 Tcl_BackgroundError(p->interp);
1723 }
1724 Tcl_DecrRefCount(pScript);
1725
1726 return iRes;
1727}
danielk1977a393c032007-05-07 14:58:53 +00001728static int test_create_collation_v2(
danielk1977a9808b32007-05-07 09:32:45 +00001729 ClientData clientData, /* Not used */
1730 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1731 int objc, /* Number of arguments */
1732 Tcl_Obj *CONST objv[] /* Command arguments */
1733){
1734 TestCollationX *p;
1735 sqlite3 *db;
drhd55d57e2008-07-07 17:53:07 +00001736 int rc;
danielk1977a9808b32007-05-07 09:32:45 +00001737
1738 if( objc!=5 ){
1739 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE NAME CMP-PROC DEL-PROC");
1740 return TCL_ERROR;
1741 }
1742 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1743
1744 p = (TestCollationX *)sqlite3_malloc(sizeof(TestCollationX));
1745 p->pCmp = objv[3];
1746 p->pDel = objv[4];
1747 p->interp = interp;
1748 Tcl_IncrRefCount(p->pCmp);
1749 Tcl_IncrRefCount(p->pDel);
1750
drhd55d57e2008-07-07 17:53:07 +00001751 rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), 16,
1752 (void *)p, testCreateCollationCmp, testCreateCollationDel
1753 );
1754 if( rc!=SQLITE_MISUSE ){
1755 Tcl_AppendResult(interp, "sqlite3_create_collate_v2() failed to detect "
1756 "an invalid encoding", (char*)0);
1757 return TCL_ERROR;
1758 }
1759 rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), SQLITE_UTF8,
danielk1977a9808b32007-05-07 09:32:45 +00001760 (void *)p, testCreateCollationCmp, testCreateCollationDel
1761 );
1762 return TCL_OK;
1763}
1764
1765/*
dand2199f02010-08-27 17:48:52 +00001766** USAGE: sqlite3_create_function_v2 DB NAME NARG ENC ?SWITCHES?
1767**
1768** Available switches are:
1769**
1770** -func SCRIPT
1771** -step SCRIPT
1772** -final SCRIPT
1773** -destroy SCRIPT
1774*/
1775typedef struct CreateFunctionV2 CreateFunctionV2;
1776struct CreateFunctionV2 {
1777 Tcl_Interp *interp;
1778 Tcl_Obj *pFunc; /* Script for function invocation */
1779 Tcl_Obj *pStep; /* Script for agg. step invocation */
1780 Tcl_Obj *pFinal; /* Script for agg. finalization invocation */
1781 Tcl_Obj *pDestroy; /* Destructor script */
1782};
1783static void cf2Func(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
1784}
1785static void cf2Step(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
1786}
1787static void cf2Final(sqlite3_context *ctx){
1788}
1789static void cf2Destroy(void *pUser){
1790 CreateFunctionV2 *p = (CreateFunctionV2 *)pUser;
1791
1792 if( p->interp && p->pDestroy ){
1793 int rc = Tcl_EvalObjEx(p->interp, p->pDestroy, 0);
1794 if( rc!=TCL_OK ) Tcl_BackgroundError(p->interp);
1795 }
1796
1797 if( p->pFunc ) Tcl_DecrRefCount(p->pFunc);
1798 if( p->pStep ) Tcl_DecrRefCount(p->pStep);
1799 if( p->pFinal ) Tcl_DecrRefCount(p->pFinal);
1800 if( p->pDestroy ) Tcl_DecrRefCount(p->pDestroy);
1801 sqlite3_free(p);
1802}
1803static int test_create_function_v2(
1804 ClientData clientData, /* Not used */
1805 Tcl_Interp *interp, /* The invoking TCL interpreter */
1806 int objc, /* Number of arguments */
1807 Tcl_Obj *CONST objv[] /* Command arguments */
1808){
1809 sqlite3 *db;
1810 const char *zFunc;
1811 int nArg;
1812 int enc;
1813 CreateFunctionV2 *p;
1814 int i;
1815 int rc;
1816
1817 struct EncTable {
1818 const char *zEnc;
1819 int enc;
1820 } aEnc[] = {
1821 {"utf8", SQLITE_UTF8 },
1822 {"utf16", SQLITE_UTF16 },
1823 {"utf16le", SQLITE_UTF16LE },
1824 {"utf16be", SQLITE_UTF16BE },
1825 {"any", SQLITE_ANY },
1826 {"0", 0 }
1827 };
1828
1829 if( objc<5 || (objc%2)==0 ){
1830 Tcl_WrongNumArgs(interp, 1, objv, "DB NAME NARG ENC SWITCHES...");
1831 return TCL_ERROR;
1832 }
1833
1834 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1835 zFunc = Tcl_GetString(objv[2]);
1836 if( Tcl_GetIntFromObj(interp, objv[3], &nArg) ) return TCL_ERROR;
1837 if( Tcl_GetIndexFromObjStruct(interp, objv[4], aEnc, sizeof(aEnc[0]),
1838 "encoding", 0, &enc)
1839 ){
1840 return TCL_ERROR;
1841 }
1842 enc = aEnc[enc].enc;
1843
1844 p = sqlite3_malloc(sizeof(CreateFunctionV2));
1845 assert( p );
1846 memset(p, 0, sizeof(CreateFunctionV2));
1847 p->interp = interp;
1848
1849 for(i=5; i<objc; i+=2){
1850 int iSwitch;
1851 const char *azSwitch[] = {"-func", "-step", "-final", "-destroy", 0};
1852 if( Tcl_GetIndexFromObj(interp, objv[i], azSwitch, "switch", 0, &iSwitch) ){
1853 sqlite3_free(p);
1854 return TCL_ERROR;
1855 }
1856
1857 switch( iSwitch ){
1858 case 0: p->pFunc = objv[i+1]; break;
1859 case 1: p->pStep = objv[i+1]; break;
1860 case 2: p->pFinal = objv[i+1]; break;
1861 case 3: p->pDestroy = objv[i+1]; break;
1862 }
1863 }
1864 if( p->pFunc ) p->pFunc = Tcl_DuplicateObj(p->pFunc);
1865 if( p->pStep ) p->pStep = Tcl_DuplicateObj(p->pStep);
1866 if( p->pFinal ) p->pFinal = Tcl_DuplicateObj(p->pFinal);
1867 if( p->pDestroy ) p->pDestroy = Tcl_DuplicateObj(p->pDestroy);
1868
1869 if( p->pFunc ) Tcl_IncrRefCount(p->pFunc);
1870 if( p->pStep ) Tcl_IncrRefCount(p->pStep);
1871 if( p->pFinal ) Tcl_IncrRefCount(p->pFinal);
1872 if( p->pDestroy ) Tcl_IncrRefCount(p->pDestroy);
1873
1874 rc = sqlite3_create_function_v2(db, zFunc, nArg, enc, (void *)p,
1875 (p->pFunc ? cf2Func : 0),
1876 (p->pStep ? cf2Step : 0),
1877 (p->pFinal ? cf2Final : 0),
1878 cf2Destroy
1879 );
1880 if( rc!=SQLITE_OK ){
dand2199f02010-08-27 17:48:52 +00001881 Tcl_ResetResult(interp);
mistachkine84d8d32013-04-29 03:09:10 +00001882 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
dand2199f02010-08-27 17:48:52 +00001883 return TCL_ERROR;
1884 }
1885 return TCL_OK;
1886}
1887
1888/*
danielk197769e777f2006-06-14 10:38:02 +00001889** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC?
1890*/
1891static int test_load_extension(
1892 ClientData clientData, /* Not used */
1893 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1894 int objc, /* Number of arguments */
1895 Tcl_Obj *CONST objv[] /* Command arguments */
1896){
1897 Tcl_CmdInfo cmdInfo;
1898 sqlite3 *db;
1899 int rc;
1900 char *zDb;
1901 char *zFile;
1902 char *zProc = 0;
1903 char *zErr = 0;
1904
1905 if( objc!=4 && objc!=3 ){
1906 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?");
1907 return TCL_ERROR;
1908 }
1909 zDb = Tcl_GetString(objv[1]);
1910 zFile = Tcl_GetString(objv[2]);
1911 if( objc==4 ){
1912 zProc = Tcl_GetString(objv[3]);
1913 }
1914
1915 /* Extract the C database handle from the Tcl command name */
1916 if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
1917 Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
1918 return TCL_ERROR;
1919 }
1920 db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
1921 assert(db);
1922
1923 /* Call the underlying C function. If an error occurs, set rc to
1924 ** TCL_ERROR and load any error string into the interpreter. If no
1925 ** error occurs, set rc to TCL_OK.
1926 */
drhc2e87a32006-06-27 15:16:14 +00001927#ifdef SQLITE_OMIT_LOAD_EXTENSION
1928 rc = SQLITE_ERROR;
1929 zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()");
1930#else
danielk197769e777f2006-06-14 10:38:02 +00001931 rc = sqlite3_load_extension(db, zFile, zProc, &zErr);
drhc2e87a32006-06-27 15:16:14 +00001932#endif
danielk197769e777f2006-06-14 10:38:02 +00001933 if( rc!=SQLITE_OK ){
1934 Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE);
1935 rc = TCL_ERROR;
1936 }else{
1937 rc = TCL_OK;
1938 }
1939 sqlite3_free(zErr);
1940
1941 return rc;
1942}
1943
1944/*
drhc2e87a32006-06-27 15:16:14 +00001945** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF
1946*/
1947static int test_enable_load(
1948 ClientData clientData, /* Not used */
1949 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1950 int objc, /* Number of arguments */
1951 Tcl_Obj *CONST objv[] /* Command arguments */
1952){
1953 Tcl_CmdInfo cmdInfo;
1954 sqlite3 *db;
1955 char *zDb;
1956 int onoff;
1957
1958 if( objc!=3 ){
1959 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF");
1960 return TCL_ERROR;
1961 }
1962 zDb = Tcl_GetString(objv[1]);
1963
1964 /* Extract the C database handle from the Tcl command name */
1965 if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
1966 Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
1967 return TCL_ERROR;
1968 }
1969 db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
1970 assert(db);
1971
1972 /* Get the onoff parameter */
1973 if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){
1974 return TCL_ERROR;
1975 }
1976
1977#ifdef SQLITE_OMIT_LOAD_EXTENSION
1978 Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()");
1979 return TCL_ERROR;
1980#else
1981 sqlite3_enable_load_extension(db, onoff);
1982 return TCL_OK;
1983#endif
1984}
1985
1986/*
drh28b4e482002-03-11 02:06:13 +00001987** Usage: sqlite_abort
1988**
1989** Shutdown the process immediately. This is not a clean shutdown.
1990** This command is used to test the recoverability of a database in
1991** the event of a program crash.
1992*/
1993static int sqlite_abort(
1994 void *NotUsed,
1995 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1996 int argc, /* Number of arguments */
1997 char **argv /* Text of each argument */
1998){
shaneh2ceced12010-07-07 16:51:36 +00001999#if defined(_MSC_VER)
2000 /* We do this, otherwise the test will halt with a popup message
2001 * that we have to click away before the test will continue.
2002 */
2003 _set_abort_behavior( 0, _CALL_REPORTFAULT );
2004#endif
dand3f6b812010-07-19 12:44:14 +00002005 exit(255);
drh28b4e482002-03-11 02:06:13 +00002006 assert( interp==0 ); /* This will always fail */
2007 return TCL_OK;
2008}
2009
2010/*
drh6cbe1f12002-07-01 00:31:36 +00002011** The following routine is a user-defined SQL function whose purpose
2012** is to test the sqlite_set_result() API.
2013*/
danielk19770ae8b832004-05-25 12:05:56 +00002014static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
drh6cbe1f12002-07-01 00:31:36 +00002015 while( argc>=2 ){
drh03d847e2005-12-09 20:21:58 +00002016 const char *zArg0 = (char*)sqlite3_value_text(argv[0]);
danielk19776d88bad2004-05-27 14:23:36 +00002017 if( zArg0 ){
2018 if( 0==sqlite3StrICmp(zArg0, "int") ){
2019 sqlite3_result_int(context, sqlite3_value_int(argv[1]));
2020 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
2021 sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
2022 }else if( sqlite3StrICmp(zArg0,"string")==0 ){
drh03d847e2005-12-09 20:21:58 +00002023 sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1,
danielk1977d8123362004-06-12 09:25:12 +00002024 SQLITE_TRANSIENT);
danielk19776d88bad2004-05-27 14:23:36 +00002025 }else if( sqlite3StrICmp(zArg0,"double")==0 ){
2026 sqlite3_result_double(context, sqlite3_value_double(argv[1]));
2027 }else if( sqlite3StrICmp(zArg0,"null")==0 ){
2028 sqlite3_result_null(context);
2029 }else if( sqlite3StrICmp(zArg0,"value")==0 ){
2030 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
2031 }else{
2032 goto error_out;
2033 }
drh6cbe1f12002-07-01 00:31:36 +00002034 }else{
danielk19776d88bad2004-05-27 14:23:36 +00002035 goto error_out;
drh6cbe1f12002-07-01 00:31:36 +00002036 }
2037 argc -= 2;
2038 argv += 2;
2039 }
danielk19776d88bad2004-05-27 14:23:36 +00002040 return;
2041
2042error_out:
2043 sqlite3_result_error(context,"first argument should be one of: "
2044 "int int64 string double null value", -1);
drh6cbe1f12002-07-01 00:31:36 +00002045}
2046
2047/*
2048** Usage: sqlite_register_test_function DB NAME
2049**
2050** Register the test SQL function on the database DB under the name NAME.
2051*/
drhc2eef3b2002-08-31 18:53:06 +00002052static int test_register_func(
drh6cbe1f12002-07-01 00:31:36 +00002053 void *NotUsed,
2054 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
2055 int argc, /* Number of arguments */
2056 char **argv /* Text of each argument */
2057){
drh9bb575f2004-09-06 17:24:11 +00002058 sqlite3 *db;
drh6cbe1f12002-07-01 00:31:36 +00002059 int rc;
2060 if( argc!=3 ){
2061 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2062 " DB FUNCTION-NAME", 0);
2063 return TCL_ERROR;
2064 }
drhb86ccfb2003-01-28 23:13:10 +00002065 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977f9d64d22004-06-19 08:18:07 +00002066 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
danielk1977d8123362004-06-12 09:25:12 +00002067 testFunc, 0, 0);
drh6cbe1f12002-07-01 00:31:36 +00002068 if( rc!=0 ){
danielk1977f20b21c2004-05-31 23:56:42 +00002069 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
drh6cbe1f12002-07-01 00:31:36 +00002070 return TCL_ERROR;
2071 }
drhc60d0442004-09-30 13:43:13 +00002072 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drh6cbe1f12002-07-01 00:31:36 +00002073 return TCL_OK;
2074}
2075
2076/*
danielk1977106bb232004-05-21 10:08:53 +00002077** Usage: sqlite3_finalize STMT
drhb86ccfb2003-01-28 23:13:10 +00002078**
danielk1977106bb232004-05-21 10:08:53 +00002079** Finalize a statement handle.
drhb86ccfb2003-01-28 23:13:10 +00002080*/
2081static int test_finalize(
danielk1977106bb232004-05-21 10:08:53 +00002082 void * clientData,
2083 Tcl_Interp *interp,
2084 int objc,
2085 Tcl_Obj *CONST objv[]
drhb86ccfb2003-01-28 23:13:10 +00002086){
danielk1977106bb232004-05-21 10:08:53 +00002087 sqlite3_stmt *pStmt;
drhb86ccfb2003-01-28 23:13:10 +00002088 int rc;
drhdddb2f22007-01-03 23:37:28 +00002089 sqlite3 *db = 0;
danielk1977106bb232004-05-21 10:08:53 +00002090
2091 if( objc!=2 ){
2092 Tcl_AppendResult(interp, "wrong # args: should be \"",
2093 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
drhb86ccfb2003-01-28 23:13:10 +00002094 return TCL_ERROR;
2095 }
danielk1977106bb232004-05-21 10:08:53 +00002096
2097 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2098
danielk19774397de52005-01-12 12:44:03 +00002099 if( pStmt ){
2100 db = StmtToDb(pStmt);
2101 }
danielk1977fc57d7b2004-05-26 02:04:57 +00002102 rc = sqlite3_finalize(pStmt);
drh4f0c5872007-03-26 22:05:01 +00002103 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
danielk19774397de52005-01-12 12:44:03 +00002104 if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk1977106bb232004-05-21 10:08:53 +00002105 return TCL_OK;
2106}
2107
2108/*
drhd1d38482008-10-07 23:46:38 +00002109** Usage: sqlite3_stmt_status STMT CODE RESETFLAG
2110**
2111** Get the value of a status counter from a statement.
2112*/
2113static int test_stmt_status(
2114 void * clientData,
2115 Tcl_Interp *interp,
2116 int objc,
2117 Tcl_Obj *CONST objv[]
2118){
2119 int iValue;
2120 int i, op, resetFlag;
2121 const char *zOpName;
2122 sqlite3_stmt *pStmt;
2123
2124 static const struct {
2125 const char *zName;
2126 int op;
2127 } aOp[] = {
2128 { "SQLITE_STMTSTATUS_FULLSCAN_STEP", SQLITE_STMTSTATUS_FULLSCAN_STEP },
2129 { "SQLITE_STMTSTATUS_SORT", SQLITE_STMTSTATUS_SORT },
drha21a64d2010-04-06 22:33:55 +00002130 { "SQLITE_STMTSTATUS_AUTOINDEX", SQLITE_STMTSTATUS_AUTOINDEX },
drhbf159fa2013-06-25 22:01:22 +00002131 { "SQLITE_STMTSTATUS_VM_STEP", SQLITE_STMTSTATUS_VM_STEP },
drhd1d38482008-10-07 23:46:38 +00002132 };
2133 if( objc!=4 ){
2134 Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG");
2135 return TCL_ERROR;
2136 }
2137 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2138 zOpName = Tcl_GetString(objv[2]);
2139 for(i=0; i<ArraySize(aOp); i++){
2140 if( strcmp(aOp[i].zName, zOpName)==0 ){
2141 op = aOp[i].op;
2142 break;
2143 }
2144 }
2145 if( i>=ArraySize(aOp) ){
2146 if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR;
2147 }
2148 if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR;
2149 iValue = sqlite3_stmt_status(pStmt, op, resetFlag);
2150 Tcl_SetObjResult(interp, Tcl_NewIntObj(iValue));
2151 return TCL_OK;
2152}
2153
dan04489b62014-10-31 20:11:32 +00002154#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
2155/*
2156** Usage: sqlite3_stmt_scanstatus STMT IDX
2157*/
2158static int test_stmt_scanstatus(
2159 void * clientData,
2160 Tcl_Interp *interp,
2161 int objc,
2162 Tcl_Obj *CONST objv[]
2163){
2164 sqlite3_stmt *pStmt; /* First argument */
2165 int idx; /* Second argument */
2166
2167 const char *zName;
2168 const char *zExplain;
2169 sqlite3_int64 nLoop;
2170 sqlite3_int64 nVisit;
drh518140e2014-11-06 03:55:10 +00002171 double rEst;
dan04489b62014-10-31 20:11:32 +00002172 int res;
2173
2174 if( objc!=3 ){
2175 Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX");
2176 return TCL_ERROR;
2177 }
2178 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2179 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
2180
drhd1a1c232014-11-03 16:35:55 +00002181 res = sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop);
dan04489b62014-10-31 20:11:32 +00002182 if( res==0 ){
2183 Tcl_Obj *pRet = Tcl_NewObj();
2184 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nLoop", -1));
2185 Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nLoop));
drhd1a1c232014-11-03 16:35:55 +00002186 sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
dan04489b62014-10-31 20:11:32 +00002187 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nVisit", -1));
2188 Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nVisit));
drh518140e2014-11-06 03:55:10 +00002189 sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EST, (void*)&rEst);
dan04489b62014-10-31 20:11:32 +00002190 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nEst", -1));
drh518140e2014-11-06 03:55:10 +00002191 Tcl_ListObjAppendElement(0, pRet, Tcl_NewDoubleObj(rEst));
drhd1a1c232014-11-03 16:35:55 +00002192 sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NAME, (void*)&zName);
dan04489b62014-10-31 20:11:32 +00002193 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zName", -1));
2194 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zName, -1));
drhd1a1c232014-11-03 16:35:55 +00002195 sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
dan04489b62014-10-31 20:11:32 +00002196 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zExplain", -1));
2197 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zExplain, -1));
2198 Tcl_SetObjResult(interp, pRet);
2199 }else{
2200 Tcl_ResetResult(interp);
2201 }
2202 return TCL_OK;
2203}
2204
2205/*
2206** Usage: sqlite3_stmt_scanstatus_reset STMT
2207*/
2208static int test_stmt_scanstatus_reset(
2209 void * clientData,
2210 Tcl_Interp *interp,
2211 int objc,
2212 Tcl_Obj *CONST objv[]
2213){
2214 sqlite3_stmt *pStmt; /* First argument */
2215 if( objc!=2 ){
2216 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
2217 return TCL_ERROR;
2218 }
2219 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2220 sqlite3_stmt_scanstatus_reset(pStmt);
2221 return TCL_OK;
2222}
2223#endif
2224
drhd1d38482008-10-07 23:46:38 +00002225/*
drhbb5a9c32008-06-19 02:52:25 +00002226** Usage: sqlite3_next_stmt DB STMT
2227**
2228** Return the next statment in sequence after STMT.
2229*/
2230static int test_next_stmt(
2231 void * clientData,
2232 Tcl_Interp *interp,
2233 int objc,
2234 Tcl_Obj *CONST objv[]
2235){
2236 sqlite3_stmt *pStmt;
2237 sqlite3 *db = 0;
2238 char zBuf[50];
2239
2240 if( objc!=3 ){
2241 Tcl_AppendResult(interp, "wrong # args: should be \"",
2242 Tcl_GetStringFromObj(objv[0], 0), " DB STMT", 0);
2243 return TCL_ERROR;
2244 }
2245
2246 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2247 if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt) ) return TCL_ERROR;
2248 pStmt = sqlite3_next_stmt(db, pStmt);
2249 if( pStmt ){
2250 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
2251 Tcl_AppendResult(interp, zBuf, 0);
2252 }
2253 return TCL_OK;
2254}
2255
drhf03d9cc2010-11-16 23:10:25 +00002256/*
2257** Usage: sqlite3_stmt_readonly STMT
2258**
2259** Return true if STMT is a NULL pointer or a pointer to a statement
2260** that is guaranteed to leave the database unmodified.
2261*/
2262static int test_stmt_readonly(
2263 void * clientData,
2264 Tcl_Interp *interp,
2265 int objc,
2266 Tcl_Obj *CONST objv[]
2267){
2268 sqlite3_stmt *pStmt;
2269 int rc;
2270
2271 if( objc!=2 ){
2272 Tcl_AppendResult(interp, "wrong # args: should be \"",
2273 Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
2274 return TCL_ERROR;
2275 }
2276
2277 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2278 rc = sqlite3_stmt_readonly(pStmt);
2279 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
2280 return TCL_OK;
2281}
2282
dand9495cd2011-04-27 12:08:04 +00002283/*
drh2fb66932011-11-25 17:21:47 +00002284** Usage: sqlite3_stmt_busy STMT
2285**
2286** Return true if STMT is a non-NULL pointer to a statement
2287** that has been stepped but not to completion.
2288*/
2289static int test_stmt_busy(
2290 void * clientData,
2291 Tcl_Interp *interp,
2292 int objc,
2293 Tcl_Obj *CONST objv[]
2294){
2295 sqlite3_stmt *pStmt;
2296 int rc;
2297
2298 if( objc!=2 ){
2299 Tcl_AppendResult(interp, "wrong # args: should be \"",
2300 Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
2301 return TCL_ERROR;
2302 }
2303
2304 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2305 rc = sqlite3_stmt_busy(pStmt);
2306 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
2307 return TCL_OK;
2308}
2309
2310/*
dand9495cd2011-04-27 12:08:04 +00002311** Usage: uses_stmt_journal STMT
2312**
2313** Return true if STMT uses a statement journal.
2314*/
2315static int uses_stmt_journal(
2316 void * clientData,
2317 Tcl_Interp *interp,
2318 int objc,
2319 Tcl_Obj *CONST objv[]
2320){
2321 sqlite3_stmt *pStmt;
dand9495cd2011-04-27 12:08:04 +00002322
2323 if( objc!=2 ){
2324 Tcl_AppendResult(interp, "wrong # args: should be \"",
2325 Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
2326 return TCL_ERROR;
2327 }
2328
2329 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
drhcaffb1a2012-01-30 18:00:31 +00002330 sqlite3_stmt_readonly(pStmt);
dand9495cd2011-04-27 12:08:04 +00002331 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(((Vdbe *)pStmt)->usesStmtJournal));
2332 return TCL_OK;
2333}
2334
drhbb5a9c32008-06-19 02:52:25 +00002335
2336/*
danielk1977106bb232004-05-21 10:08:53 +00002337** Usage: sqlite3_reset STMT
2338**
danielk1977261919c2005-12-06 12:52:59 +00002339** Reset a statement handle.
danielk1977106bb232004-05-21 10:08:53 +00002340*/
2341static int test_reset(
2342 void * clientData,
2343 Tcl_Interp *interp,
2344 int objc,
2345 Tcl_Obj *CONST objv[]
2346){
2347 sqlite3_stmt *pStmt;
2348 int rc;
2349
2350 if( objc!=2 ){
2351 Tcl_AppendResult(interp, "wrong # args: should be \"",
2352 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
2353 return TCL_ERROR;
2354 }
2355
2356 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2357
danielk1977fc57d7b2004-05-26 02:04:57 +00002358 rc = sqlite3_reset(pStmt);
danielk1977261919c2005-12-06 12:52:59 +00002359 if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){
2360 return TCL_ERROR;
2361 }
drh4f0c5872007-03-26 22:05:01 +00002362 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
danielk1977261919c2005-12-06 12:52:59 +00002363/*
danielk1977106bb232004-05-21 10:08:53 +00002364 if( rc ){
drhb86ccfb2003-01-28 23:13:10 +00002365 return TCL_ERROR;
2366 }
danielk1977261919c2005-12-06 12:52:59 +00002367*/
drhb86ccfb2003-01-28 23:13:10 +00002368 return TCL_OK;
2369}
2370
drh5a387052003-01-11 14:19:51 +00002371/*
drhd89bd002005-01-22 03:03:54 +00002372** Usage: sqlite3_expired STMT
2373**
2374** Return TRUE if a recompilation of the statement is recommended.
2375*/
2376static int test_expired(
2377 void * clientData,
2378 Tcl_Interp *interp,
2379 int objc,
2380 Tcl_Obj *CONST objv[]
2381){
shaneeec556d2008-10-12 00:27:53 +00002382#ifndef SQLITE_OMIT_DEPRECATED
drhd89bd002005-01-22 03:03:54 +00002383 sqlite3_stmt *pStmt;
2384 if( objc!=2 ){
2385 Tcl_AppendResult(interp, "wrong # args: should be \"",
2386 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
2387 return TCL_ERROR;
2388 }
2389 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2390 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt)));
shaneeec556d2008-10-12 00:27:53 +00002391#endif
drhd89bd002005-01-22 03:03:54 +00002392 return TCL_OK;
2393}
2394
2395/*
drhf8db1bc2005-04-22 02:38:37 +00002396** Usage: sqlite3_transfer_bindings FROMSTMT TOSTMT
2397**
2398** Transfer all bindings from FROMSTMT over to TOSTMT
2399*/
2400static int test_transfer_bind(
2401 void * clientData,
2402 Tcl_Interp *interp,
2403 int objc,
2404 Tcl_Obj *CONST objv[]
2405){
shaneeec556d2008-10-12 00:27:53 +00002406#ifndef SQLITE_OMIT_DEPRECATED
drhf8db1bc2005-04-22 02:38:37 +00002407 sqlite3_stmt *pStmt1, *pStmt2;
2408 if( objc!=3 ){
2409 Tcl_AppendResult(interp, "wrong # args: should be \"",
2410 Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0);
2411 return TCL_ERROR;
2412 }
2413 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR;
2414 if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR;
2415 Tcl_SetObjResult(interp,
2416 Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2)));
shaneeec556d2008-10-12 00:27:53 +00002417#endif
drhf8db1bc2005-04-22 02:38:37 +00002418 return TCL_OK;
2419}
2420
2421/*
danielk1977fbcd5852004-06-15 02:44:18 +00002422** Usage: sqlite3_changes DB
drh50457892003-09-06 01:10:47 +00002423**
danielk1977fbcd5852004-06-15 02:44:18 +00002424** Return the number of changes made to the database by the last SQL
2425** execution.
drh50457892003-09-06 01:10:47 +00002426*/
danielk1977fbcd5852004-06-15 02:44:18 +00002427static int test_changes(
2428 void * clientData,
2429 Tcl_Interp *interp,
2430 int objc,
2431 Tcl_Obj *CONST objv[]
2432){
2433 sqlite3 *db;
2434 if( objc!=2 ){
2435 Tcl_AppendResult(interp, "wrong # args: should be \"",
2436 Tcl_GetString(objv[0]), " DB", 0);
2437 return TCL_ERROR;
2438 }
2439 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2440 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
2441 return TCL_OK;
2442}
drh50457892003-09-06 01:10:47 +00002443
2444/*
drh7c972de2003-09-06 22:18:07 +00002445** This is the "static_bind_value" that variables are bound to when
danielk19776f8a5032004-05-10 10:34:51 +00002446** the FLAG option of sqlite3_bind is "static"
drh50457892003-09-06 01:10:47 +00002447*/
drh7c972de2003-09-06 22:18:07 +00002448static char *sqlite_static_bind_value = 0;
drhf0313812006-09-04 15:53:53 +00002449static int sqlite_static_bind_nbyte = 0;
drh7c972de2003-09-06 22:18:07 +00002450
2451/*
danielk19776f8a5032004-05-10 10:34:51 +00002452** Usage: sqlite3_bind VM IDX VALUE FLAGS
drh7c972de2003-09-06 22:18:07 +00002453**
drhf7b54962013-05-28 12:11:54 +00002454** Sets the value of the IDX-th occurrence of "?" in the original SQL
drh7c972de2003-09-06 22:18:07 +00002455** string. VALUE is the new value. If FLAGS=="null" then VALUE is
2456** ignored and the value is set to NULL. If FLAGS=="static" then
2457** the value is set to the value of a static variable named
2458** "sqlite_static_bind_value". If FLAGS=="normal" then a copy
drhbf8aa2a2005-12-02 02:44:05 +00002459** of the VALUE is made. If FLAGS=="blob10" then a VALUE is ignored
2460** an a 10-byte blob "abc\000xyz\000pq" is inserted.
drh7c972de2003-09-06 22:18:07 +00002461*/
2462static int test_bind(
drh50457892003-09-06 01:10:47 +00002463 void *NotUsed,
2464 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
2465 int argc, /* Number of arguments */
2466 char **argv /* Text of each argument */
2467){
danielk1977fc57d7b2004-05-26 02:04:57 +00002468 sqlite3_stmt *pStmt;
drh50457892003-09-06 01:10:47 +00002469 int rc;
drh7c972de2003-09-06 22:18:07 +00002470 int idx;
2471 if( argc!=5 ){
drh50457892003-09-06 01:10:47 +00002472 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drh7c972de2003-09-06 22:18:07 +00002473 " VM IDX VALUE (null|static|normal)\"", 0);
drh50457892003-09-06 01:10:47 +00002474 return TCL_ERROR;
2475 }
danielk1977fc57d7b2004-05-26 02:04:57 +00002476 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
drh7c972de2003-09-06 22:18:07 +00002477 if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
2478 if( strcmp(argv[4],"null")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +00002479 rc = sqlite3_bind_null(pStmt, idx);
drh7c972de2003-09-06 22:18:07 +00002480 }else if( strcmp(argv[4],"static")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +00002481 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
drhf0313812006-09-04 15:53:53 +00002482 }else if( strcmp(argv[4],"static-nbytes")==0 ){
2483 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value,
2484 sqlite_static_bind_nbyte, 0);
drh7c972de2003-09-06 22:18:07 +00002485 }else if( strcmp(argv[4],"normal")==0 ){
danielk1977d8123362004-06-12 09:25:12 +00002486 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
drhbf8aa2a2005-12-02 02:44:05 +00002487 }else if( strcmp(argv[4],"blob10")==0 ){
2488 rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC);
drh7c972de2003-09-06 22:18:07 +00002489 }else{
2490 Tcl_AppendResult(interp, "4th argument should be "
2491 "\"null\" or \"static\" or \"normal\"", 0);
2492 return TCL_ERROR;
2493 }
drhc60d0442004-09-30 13:43:13 +00002494 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
drh50457892003-09-06 01:10:47 +00002495 if( rc ){
2496 char zBuf[50];
2497 sprintf(zBuf, "(%d) ", rc);
danielk1977f20b21c2004-05-31 23:56:42 +00002498 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
drh50457892003-09-06 01:10:47 +00002499 return TCL_ERROR;
2500 }
2501 return TCL_OK;
2502}
2503
drh5436dc22004-11-14 04:04:17 +00002504#ifndef SQLITE_OMIT_UTF16
danielk19774e6af132004-06-10 14:01:08 +00002505/*
2506** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
2507**
2508** This function is used to test that SQLite selects the correct collation
2509** sequence callback when multiple versions (for different text encodings)
2510** are available.
2511**
2512** Calling this routine registers the collation sequence "test_collate"
2513** with database handle <db>. The second argument must be a list of three
2514** boolean values. If the first is true, then a version of test_collate is
2515** registered for UTF-8, if the second is true, a version is registered for
2516** UTF-16le, if the third is true, a UTF-16be version is available.
2517** Previous versions of test_collate are deleted.
2518**
2519** The collation sequence test_collate is implemented by calling the
2520** following TCL script:
2521**
2522** "test_collate <enc> <lhs> <rhs>"
2523**
2524** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
2525** The <enc> parameter is the encoding of the collation function that
2526** SQLite selected to call. The TCL test script implements the
2527** "test_collate" proc.
2528**
peter.d.reid60ec9142014-09-06 16:39:46 +00002529** Note that this will only work with one interpreter at a time, as the
danielk19774e6af132004-06-10 14:01:08 +00002530** interp pointer to use when evaluating the TCL script is stored in
2531** pTestCollateInterp.
2532*/
2533static Tcl_Interp* pTestCollateInterp;
2534static int test_collate_func(
2535 void *pCtx,
2536 int nA, const void *zA,
2537 int nB, const void *zB
2538){
2539 Tcl_Interp *i = pTestCollateInterp;
dand2199f02010-08-27 17:48:52 +00002540 int encin = SQLITE_PTR_TO_INT(pCtx);
danielk19774e6af132004-06-10 14:01:08 +00002541 int res;
drh4db38a72005-09-01 12:16:28 +00002542 int n;
danielk19774e6af132004-06-10 14:01:08 +00002543
2544 sqlite3_value *pVal;
2545 Tcl_Obj *pX;
2546
2547 pX = Tcl_NewStringObj("test_collate", -1);
2548 Tcl_IncrRefCount(pX);
2549
2550 switch( encin ){
2551 case SQLITE_UTF8:
2552 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
2553 break;
2554 case SQLITE_UTF16LE:
2555 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
2556 break;
2557 case SQLITE_UTF16BE:
2558 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
2559 break;
2560 default:
2561 assert(0);
2562 }
2563
dan02fa4692009-08-17 17:06:58 +00002564 sqlite3BeginBenignMalloc();
danielk19771e536952007-08-16 10:09:01 +00002565 pVal = sqlite3ValueNew(0);
dan02fa4692009-08-17 17:06:58 +00002566 if( pVal ){
2567 sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
2568 n = sqlite3_value_bytes(pVal);
2569 Tcl_ListObjAppendElement(i,pX,
2570 Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
2571 sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
2572 n = sqlite3_value_bytes(pVal);
2573 Tcl_ListObjAppendElement(i,pX,
2574 Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
2575 sqlite3ValueFree(pVal);
2576 }
2577 sqlite3EndBenignMalloc();
danielk19774e6af132004-06-10 14:01:08 +00002578
2579 Tcl_EvalObjEx(i, pX, 0);
2580 Tcl_DecrRefCount(pX);
2581 Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
2582 return res;
2583}
2584static int test_collate(
2585 void * clientData,
2586 Tcl_Interp *interp,
2587 int objc,
2588 Tcl_Obj *CONST objv[]
2589){
2590 sqlite3 *db;
2591 int val;
danielk1977312d6b32004-06-29 13:18:23 +00002592 sqlite3_value *pVal;
drhc60d0442004-09-30 13:43:13 +00002593 int rc;
danielk19774e6af132004-06-10 14:01:08 +00002594
2595 if( objc!=5 ) goto bad_args;
2596 pTestCollateInterp = interp;
2597 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2598
2599 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +00002600 rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
2601 (void *)SQLITE_UTF8, val?test_collate_func:0);
2602 if( rc==SQLITE_OK ){
drheee4c8c2008-02-18 22:24:57 +00002603 const void *zUtf16;
drhc60d0442004-09-30 13:43:13 +00002604 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
2605 rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
2606 (void *)SQLITE_UTF16LE, val?test_collate_func:0);
2607 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
danielk1977312d6b32004-06-29 13:18:23 +00002608
drh86f8c192007-08-22 00:39:19 +00002609#if 0
danielk19779a30cf62006-01-18 04:26:07 +00002610 if( sqlite3_iMallocFail>0 ){
2611 sqlite3_iMallocFail++;
2612 }
2613#endif
drhf3a65f72007-08-22 20:18:21 +00002614 sqlite3_mutex_enter(db->mutex);
2615 pVal = sqlite3ValueNew(db);
drhb21c8cd2007-08-21 19:33:56 +00002616 sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
danielk1977a7a8e142008-02-13 18:25:27 +00002617 zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
drhf3a65f72007-08-22 20:18:21 +00002618 if( db->mallocFailed ){
2619 rc = SQLITE_NOMEM;
2620 }else{
danielk1977a7a8e142008-02-13 18:25:27 +00002621 rc = sqlite3_create_collation16(db, zUtf16, SQLITE_UTF16BE,
danielk19779a30cf62006-01-18 04:26:07 +00002622 (void *)SQLITE_UTF16BE, val?test_collate_func:0);
drhf3a65f72007-08-22 20:18:21 +00002623 }
drhc60d0442004-09-30 13:43:13 +00002624 sqlite3ValueFree(pVal);
drhf3a65f72007-08-22 20:18:21 +00002625 sqlite3_mutex_leave(db->mutex);
drhc60d0442004-09-30 13:43:13 +00002626 }
2627 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk19779a30cf62006-01-18 04:26:07 +00002628
2629 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +00002630 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
danielk19779a30cf62006-01-18 04:26:07 +00002631 return TCL_ERROR;
2632 }
danielk19774e6af132004-06-10 14:01:08 +00002633 return TCL_OK;
2634
2635bad_args:
2636 Tcl_AppendResult(interp, "wrong # args: should be \"",
2637 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
2638 return TCL_ERROR;
2639}
2640
drh268803a2005-12-14 20:11:30 +00002641/*
dan38fdead2014-04-01 10:19:02 +00002642** Usage: add_test_utf16bin_collate <db ptr>
2643**
2644** Add a utf-16 collation sequence named "utf16bin" to the database
2645** handle. This collation sequence compares arguments in the same way as the
2646** built-in collation "binary".
2647*/
2648static int test_utf16bin_collate_func(
2649 void *pCtx,
2650 int nA, const void *zA,
2651 int nB, const void *zB
2652){
2653 int nCmp = (nA>nB ? nB : nA);
2654 int res = memcmp(zA, zB, nCmp);
2655 if( res==0 ) res = nA - nB;
2656 return res;
2657}
2658static int test_utf16bin_collate(
2659 void * clientData,
2660 Tcl_Interp *interp,
2661 int objc,
2662 Tcl_Obj *CONST objv[]
2663){
2664 sqlite3 *db;
2665 int rc;
2666
2667 if( objc!=2 ) goto bad_args;
2668 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2669
2670 rc = sqlite3_create_collation(db, "utf16bin", SQLITE_UTF16, 0,
2671 test_utf16bin_collate_func
2672 );
2673 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
2674 return TCL_OK;
2675
2676bad_args:
2677 Tcl_WrongNumArgs(interp, 1, objv, "DB");
2678 return TCL_ERROR;
2679}
2680
2681/*
drh268803a2005-12-14 20:11:30 +00002682** When the collation needed callback is invoked, record the name of
2683** the requested collating function here. The recorded name is linked
2684** to a TCL variable and used to make sure that the requested collation
2685** name is correct.
2686*/
2687static char zNeededCollation[200];
2688static char *pzNeededCollation = zNeededCollation;
2689
2690
2691/*
2692** Called when a collating sequence is needed. Registered using
2693** sqlite3_collation_needed16().
2694*/
danielk1977312d6b32004-06-29 13:18:23 +00002695static void test_collate_needed_cb(
2696 void *pCtx,
2697 sqlite3 *db,
2698 int eTextRep,
drh268803a2005-12-14 20:11:30 +00002699 const void *pName
danielk1977312d6b32004-06-29 13:18:23 +00002700){
danielk197714db2662006-01-09 16:12:04 +00002701 int enc = ENC(db);
drh268803a2005-12-14 20:11:30 +00002702 int i;
2703 char *z;
2704 for(z = (char*)pName, i=0; *z || z[1]; z++){
2705 if( *z ) zNeededCollation[i++] = *z;
2706 }
2707 zNeededCollation[i] = 0;
danielk1977312d6b32004-06-29 13:18:23 +00002708 sqlite3_create_collation(
dand2199f02010-08-27 17:48:52 +00002709 db, "test_collate", ENC(db), SQLITE_INT_TO_PTR(enc), test_collate_func);
danielk1977312d6b32004-06-29 13:18:23 +00002710}
2711
2712/*
2713** Usage: add_test_collate_needed DB
2714*/
2715static int test_collate_needed(
2716 void * clientData,
2717 Tcl_Interp *interp,
2718 int objc,
2719 Tcl_Obj *CONST objv[]
2720){
2721 sqlite3 *db;
drhc60d0442004-09-30 13:43:13 +00002722 int rc;
danielk1977312d6b32004-06-29 13:18:23 +00002723
2724 if( objc!=2 ) goto bad_args;
2725 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +00002726 rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
drh268803a2005-12-14 20:11:30 +00002727 zNeededCollation[0] = 0;
drhc60d0442004-09-30 13:43:13 +00002728 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk1977312d6b32004-06-29 13:18:23 +00002729 return TCL_OK;
2730
2731bad_args:
2732 Tcl_WrongNumArgs(interp, 1, objv, "DB");
2733 return TCL_ERROR;
2734}
drh7d9bd4e2006-02-16 18:16:36 +00002735
2736/*
2737** tclcmd: add_alignment_test_collations DB
2738**
2739** Add two new collating sequences to the database DB
2740**
2741** utf16_aligned
2742** utf16_unaligned
2743**
2744** Both collating sequences use the same sort order as BINARY.
2745** The only difference is that the utf16_aligned collating
2746** sequence is declared with the SQLITE_UTF16_ALIGNED flag.
2747** Both collating functions increment the unaligned utf16 counter
2748** whenever they see a string that begins on an odd byte boundary.
2749*/
2750static int unaligned_string_counter = 0;
2751static int alignmentCollFunc(
2752 void *NotUsed,
2753 int nKey1, const void *pKey1,
2754 int nKey2, const void *pKey2
2755){
2756 int rc, n;
2757 n = nKey1<nKey2 ? nKey1 : nKey2;
dand2199f02010-08-27 17:48:52 +00002758 if( nKey1>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey1))) ) unaligned_string_counter++;
2759 if( nKey2>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey2))) ) unaligned_string_counter++;
drh7d9bd4e2006-02-16 18:16:36 +00002760 rc = memcmp(pKey1, pKey2, n);
2761 if( rc==0 ){
2762 rc = nKey1 - nKey2;
2763 }
2764 return rc;
2765}
2766static int add_alignment_test_collations(
2767 void * clientData,
2768 Tcl_Interp *interp,
2769 int objc,
2770 Tcl_Obj *CONST objv[]
2771){
2772 sqlite3 *db;
2773 if( objc>=2 ){
2774 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
danielk1977ebb32932009-04-28 15:35:38 +00002775 sqlite3_create_collation(db, "utf16_unaligned", SQLITE_UTF16,
drh7d9bd4e2006-02-16 18:16:36 +00002776 0, alignmentCollFunc);
danielk1977ebb32932009-04-28 15:35:38 +00002777 sqlite3_create_collation(db, "utf16_aligned", SQLITE_UTF16_ALIGNED,
drh7d9bd4e2006-02-16 18:16:36 +00002778 0, alignmentCollFunc);
2779 }
2780 return SQLITE_OK;
2781}
2782#endif /* !defined(SQLITE_OMIT_UTF16) */
danielk1977312d6b32004-06-29 13:18:23 +00002783
danielk1977c8e9a2d2004-06-25 12:08:46 +00002784/*
2785** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
2786**
2787** This function is used to test that SQLite selects the correct user
2788** function callback when multiple versions (for different text encodings)
2789** are available.
2790**
2791** Calling this routine registers up to three versions of the user function
2792** "test_function" with database handle <db>. If the second argument is
2793** true, then a version of test_function is registered for UTF-8, if the
2794** third is true, a version is registered for UTF-16le, if the fourth is
2795** true, a UTF-16be version is available. Previous versions of
2796** test_function are deleted.
2797**
2798** The user function is implemented by calling the following TCL script:
2799**
2800** "test_function <enc> <arg>"
2801**
2802** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
2803** single argument passed to the SQL function. The value returned by
2804** the TCL script is used as the return value of the SQL function. It
2805** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
2806** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
2807** prefers UTF-16BE.
2808*/
drh5436dc22004-11-14 04:04:17 +00002809#ifndef SQLITE_OMIT_UTF16
danielk1977c8e9a2d2004-06-25 12:08:46 +00002810static void test_function_utf8(
2811 sqlite3_context *pCtx,
2812 int nArg,
2813 sqlite3_value **argv
2814){
2815 Tcl_Interp *interp;
2816 Tcl_Obj *pX;
2817 sqlite3_value *pVal;
2818 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
2819 pX = Tcl_NewStringObj("test_function", -1);
2820 Tcl_IncrRefCount(pX);
2821 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
2822 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00002823 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00002824 Tcl_EvalObjEx(interp, pX, 0);
2825 Tcl_DecrRefCount(pX);
2826 sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
danielk19771e536952007-08-16 10:09:01 +00002827 pVal = sqlite3ValueNew(0);
drhb21c8cd2007-08-21 19:33:56 +00002828 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
danielk1977c8e9a2d2004-06-25 12:08:46 +00002829 SQLITE_UTF8, SQLITE_STATIC);
2830 sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
2831 -1, SQLITE_TRANSIENT);
2832 sqlite3ValueFree(pVal);
2833}
2834static void test_function_utf16le(
2835 sqlite3_context *pCtx,
2836 int nArg,
2837 sqlite3_value **argv
2838){
2839 Tcl_Interp *interp;
2840 Tcl_Obj *pX;
2841 sqlite3_value *pVal;
2842 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
2843 pX = Tcl_NewStringObj("test_function", -1);
2844 Tcl_IncrRefCount(pX);
2845 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
2846 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00002847 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00002848 Tcl_EvalObjEx(interp, pX, 0);
2849 Tcl_DecrRefCount(pX);
danielk19771e536952007-08-16 10:09:01 +00002850 pVal = sqlite3ValueNew(0);
drhb21c8cd2007-08-21 19:33:56 +00002851 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
danielk1977c8e9a2d2004-06-25 12:08:46 +00002852 SQLITE_UTF8, SQLITE_STATIC);
drh03d847e2005-12-09 20:21:58 +00002853 sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
danielk1977c8e9a2d2004-06-25 12:08:46 +00002854 sqlite3ValueFree(pVal);
2855}
2856static void test_function_utf16be(
2857 sqlite3_context *pCtx,
2858 int nArg,
2859 sqlite3_value **argv
2860){
2861 Tcl_Interp *interp;
2862 Tcl_Obj *pX;
2863 sqlite3_value *pVal;
2864 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
2865 pX = Tcl_NewStringObj("test_function", -1);
2866 Tcl_IncrRefCount(pX);
2867 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
2868 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00002869 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00002870 Tcl_EvalObjEx(interp, pX, 0);
2871 Tcl_DecrRefCount(pX);
danielk19771e536952007-08-16 10:09:01 +00002872 pVal = sqlite3ValueNew(0);
drhb21c8cd2007-08-21 19:33:56 +00002873 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
danielk1977c8e9a2d2004-06-25 12:08:46 +00002874 SQLITE_UTF8, SQLITE_STATIC);
drhde4fcfd2008-01-19 23:50:26 +00002875 sqlite3_result_text16(pCtx, sqlite3_value_text16le(pVal),
2876 -1, SQLITE_TRANSIENT);
2877 sqlite3_result_text16be(pCtx, sqlite3_value_text16le(pVal),
2878 -1, SQLITE_TRANSIENT);
danielk1977c8e9a2d2004-06-25 12:08:46 +00002879 sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
2880 -1, SQLITE_TRANSIENT);
2881 sqlite3ValueFree(pVal);
2882}
drh5436dc22004-11-14 04:04:17 +00002883#endif /* SQLITE_OMIT_UTF16 */
danielk1977c8e9a2d2004-06-25 12:08:46 +00002884static int test_function(
2885 void * clientData,
2886 Tcl_Interp *interp,
2887 int objc,
2888 Tcl_Obj *CONST objv[]
2889){
drh5436dc22004-11-14 04:04:17 +00002890#ifndef SQLITE_OMIT_UTF16
danielk1977c8e9a2d2004-06-25 12:08:46 +00002891 sqlite3 *db;
2892 int val;
2893
2894 if( objc!=5 ) goto bad_args;
2895 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2896
2897 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
2898 if( val ){
2899 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
2900 interp, test_function_utf8, 0, 0);
2901 }
2902 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
2903 if( val ){
2904 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
2905 interp, test_function_utf16le, 0, 0);
2906 }
2907 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
2908 if( val ){
2909 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
2910 interp, test_function_utf16be, 0, 0);
2911 }
2912
2913 return TCL_OK;
2914bad_args:
2915 Tcl_AppendResult(interp, "wrong # args: should be \"",
2916 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
drh5436dc22004-11-14 04:04:17 +00002917#endif /* SQLITE_OMIT_UTF16 */
danielk1977c8e9a2d2004-06-25 12:08:46 +00002918 return TCL_ERROR;
2919}
2920
danielk1977312d6b32004-06-29 13:18:23 +00002921/*
danba3cbf32010-06-30 04:29:03 +00002922** Usage: sqlite3_test_errstr <err code>
danielk1977312d6b32004-06-29 13:18:23 +00002923**
2924** Test that the english language string equivalents for sqlite error codes
2925** are sane. The parameter is an integer representing an sqlite error code.
2926** The result is a list of two elements, the string representation of the
2927** error code and the english language explanation.
2928*/
2929static int test_errstr(
2930 void * clientData,
2931 Tcl_Interp *interp,
2932 int objc,
2933 Tcl_Obj *CONST objv[]
2934){
2935 char *zCode;
2936 int i;
2937 if( objc!=1 ){
2938 Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
2939 }
2940
2941 zCode = Tcl_GetString(objv[1]);
2942 for(i=0; i<200; i++){
drh4f0c5872007-03-26 22:05:01 +00002943 if( 0==strcmp(t1ErrorName(i), zCode) ) break;
danielk1977312d6b32004-06-29 13:18:23 +00002944 }
2945 Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
2946 return TCL_OK;
2947}
2948
drh50457892003-09-06 01:10:47 +00002949/*
drh99ee3602003-02-16 19:13:36 +00002950** Usage: breakpoint
2951**
2952** This routine exists for one purpose - to provide a place to put a
2953** breakpoint with GDB that can be triggered using TCL code. The use
2954** for this is when a particular test fails on (say) the 1485th iteration.
2955** In the TCL test script, we can add code like this:
2956**
2957** if {$i==1485} breakpoint
2958**
2959** Then run testfixture in the debugger and wait for the breakpoint to
2960** fire. Then additional breakpoints can be set to trace down the bug.
2961*/
2962static int test_breakpoint(
2963 void *NotUsed,
2964 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
2965 int argc, /* Number of arguments */
2966 char **argv /* Text of each argument */
2967){
2968 return TCL_OK; /* Do nothing */
2969}
2970
drh241db312004-06-22 12:46:53 +00002971/*
drhb026e052007-05-02 01:34:31 +00002972** Usage: sqlite3_bind_zeroblob STMT IDX N
2973**
2974** Test the sqlite3_bind_zeroblob interface. STMT is a prepared statement.
2975** IDX is the index of a wildcard in the prepared statement. This command
2976** binds a N-byte zero-filled BLOB to the wildcard.
2977*/
2978static int test_bind_zeroblob(
2979 void * clientData,
2980 Tcl_Interp *interp,
2981 int objc,
2982 Tcl_Obj *CONST objv[]
2983){
2984 sqlite3_stmt *pStmt;
2985 int idx;
2986 int n;
2987 int rc;
2988
2989 if( objc!=4 ){
danielk197728c66302007-09-01 11:04:26 +00002990 Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N");
drhb026e052007-05-02 01:34:31 +00002991 return TCL_ERROR;
2992 }
2993
2994 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2995 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
2996 if( Tcl_GetIntFromObj(interp, objv[3], &n) ) return TCL_ERROR;
2997
2998 rc = sqlite3_bind_zeroblob(pStmt, idx, n);
2999 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3000 if( rc!=SQLITE_OK ){
3001 return TCL_ERROR;
3002 }
3003
3004 return TCL_OK;
3005}
3006
3007/*
drh241db312004-06-22 12:46:53 +00003008** Usage: sqlite3_bind_int STMT N VALUE
3009**
3010** Test the sqlite3_bind_int interface. STMT is a prepared statement.
3011** N is the index of a wildcard in the prepared statement. This command
3012** binds a 32-bit integer VALUE to that wildcard.
3013*/
3014static int test_bind_int(
danielk197751e3d8e2004-05-20 01:12:34 +00003015 void * clientData,
3016 Tcl_Interp *interp,
3017 int objc,
3018 Tcl_Obj *CONST objv[]
3019){
3020 sqlite3_stmt *pStmt;
3021 int idx;
3022 int value;
3023 int rc;
3024
3025 if( objc!=4 ){
3026 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00003027 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003028 return TCL_ERROR;
3029 }
3030
3031 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3032 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3033 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
3034
danielk1977c572ef72004-05-27 09:28:41 +00003035 rc = sqlite3_bind_int(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00003036 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003037 if( rc!=SQLITE_OK ){
3038 return TCL_ERROR;
3039 }
3040
3041 return TCL_OK;
3042}
3043
drh241db312004-06-22 12:46:53 +00003044
3045/*
3046** Usage: sqlite3_bind_int64 STMT N VALUE
3047**
3048** Test the sqlite3_bind_int64 interface. STMT is a prepared statement.
3049** N is the index of a wildcard in the prepared statement. This command
3050** binds a 64-bit integer VALUE to that wildcard.
3051*/
danielk197751e3d8e2004-05-20 01:12:34 +00003052static int test_bind_int64(
3053 void * clientData,
3054 Tcl_Interp *interp,
3055 int objc,
3056 Tcl_Obj *CONST objv[]
3057){
3058 sqlite3_stmt *pStmt;
3059 int idx;
drhb3f787f2012-09-29 14:45:54 +00003060 Tcl_WideInt value;
danielk197751e3d8e2004-05-20 01:12:34 +00003061 int rc;
3062
3063 if( objc!=4 ){
3064 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00003065 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003066 return TCL_ERROR;
3067 }
3068
3069 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3070 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3071 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
3072
3073 rc = sqlite3_bind_int64(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00003074 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003075 if( rc!=SQLITE_OK ){
3076 return TCL_ERROR;
3077 }
3078
3079 return TCL_OK;
3080}
3081
drh241db312004-06-22 12:46:53 +00003082
3083/*
3084** Usage: sqlite3_bind_double STMT N VALUE
3085**
3086** Test the sqlite3_bind_double interface. STMT is a prepared statement.
3087** N is the index of a wildcard in the prepared statement. This command
3088** binds a 64-bit integer VALUE to that wildcard.
3089*/
danielk197751e3d8e2004-05-20 01:12:34 +00003090static int test_bind_double(
3091 void * clientData,
3092 Tcl_Interp *interp,
3093 int objc,
3094 Tcl_Obj *CONST objv[]
3095){
3096 sqlite3_stmt *pStmt;
3097 int idx;
3098 double value;
3099 int rc;
drha06f17f2008-05-11 11:07:06 +00003100 const char *zVal;
3101 int i;
3102 static const struct {
3103 const char *zName; /* Name of the special floating point value */
3104 unsigned int iUpper; /* Upper 32 bits */
3105 unsigned int iLower; /* Lower 32 bits */
3106 } aSpecialFp[] = {
3107 { "NaN", 0x7fffffff, 0xffffffff },
3108 { "SNaN", 0x7ff7ffff, 0xffffffff },
3109 { "-NaN", 0xffffffff, 0xffffffff },
3110 { "-SNaN", 0xfff7ffff, 0xffffffff },
3111 { "+Inf", 0x7ff00000, 0x00000000 },
3112 { "-Inf", 0xfff00000, 0x00000000 },
3113 { "Epsilon", 0x00000000, 0x00000001 },
3114 { "-Epsilon", 0x80000000, 0x00000001 },
3115 { "NaN0", 0x7ff80000, 0x00000000 },
3116 { "-NaN0", 0xfff80000, 0x00000000 },
3117 };
danielk197751e3d8e2004-05-20 01:12:34 +00003118
3119 if( objc!=4 ){
3120 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00003121 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003122 return TCL_ERROR;
3123 }
3124
3125 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3126 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003127
drh394f07e2008-04-28 15:23:02 +00003128 /* Intercept the string "NaN" and generate a NaN value for it.
3129 ** All other strings are passed through to Tcl_GetDoubleFromObj().
3130 ** Tcl_GetDoubleFromObj() should understand "NaN" but some versions
3131 ** contain a bug.
3132 */
drha06f17f2008-05-11 11:07:06 +00003133 zVal = Tcl_GetString(objv[3]);
3134 for(i=0; i<sizeof(aSpecialFp)/sizeof(aSpecialFp[0]); i++){
3135 if( strcmp(aSpecialFp[i].zName, zVal)==0 ){
3136 sqlite3_uint64 x;
3137 x = aSpecialFp[i].iUpper;
3138 x <<= 32;
3139 x |= aSpecialFp[i].iLower;
drh0a667332008-05-11 17:22:01 +00003140 assert( sizeof(value)==8 );
3141 assert( sizeof(x)==8 );
3142 memcpy(&value, &x, 8);
drha06f17f2008-05-11 11:07:06 +00003143 break;
3144 }
3145 }
3146 if( i>=sizeof(aSpecialFp)/sizeof(aSpecialFp[0]) &&
3147 Tcl_GetDoubleFromObj(interp, objv[3], &value) ){
drh394f07e2008-04-28 15:23:02 +00003148 return TCL_ERROR;
3149 }
danielk197751e3d8e2004-05-20 01:12:34 +00003150 rc = sqlite3_bind_double(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00003151 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003152 if( rc!=SQLITE_OK ){
3153 return TCL_ERROR;
3154 }
3155
3156 return TCL_OK;
3157}
3158
drh241db312004-06-22 12:46:53 +00003159/*
3160** Usage: sqlite3_bind_null STMT N
3161**
3162** Test the sqlite3_bind_null interface. STMT is a prepared statement.
3163** N is the index of a wildcard in the prepared statement. This command
3164** binds a NULL to the wildcard.
3165*/
danielk197751e3d8e2004-05-20 01:12:34 +00003166static int test_bind_null(
3167 void * clientData,
3168 Tcl_Interp *interp,
3169 int objc,
3170 Tcl_Obj *CONST objv[]
3171){
3172 sqlite3_stmt *pStmt;
3173 int idx;
3174 int rc;
3175
3176 if( objc!=3 ){
3177 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00003178 Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003179 return TCL_ERROR;
3180 }
3181
3182 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3183 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3184
3185 rc = sqlite3_bind_null(pStmt, idx);
drhc60d0442004-09-30 13:43:13 +00003186 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003187 if( rc!=SQLITE_OK ){
3188 return TCL_ERROR;
3189 }
3190
3191 return TCL_OK;
3192}
3193
drh241db312004-06-22 12:46:53 +00003194/*
3195** Usage: sqlite3_bind_text STMT N STRING BYTES
3196**
3197** Test the sqlite3_bind_text interface. STMT is a prepared statement.
3198** N is the index of a wildcard in the prepared statement. This command
3199** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes
3200** long.
3201*/
danielk197751e3d8e2004-05-20 01:12:34 +00003202static int test_bind_text(
3203 void * clientData,
3204 Tcl_Interp *interp,
3205 int objc,
3206 Tcl_Obj *CONST objv[]
3207){
3208 sqlite3_stmt *pStmt;
3209 int idx;
3210 int bytes;
3211 char *value;
3212 int rc;
3213
3214 if( objc!=5 ){
3215 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00003216 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003217 return TCL_ERROR;
3218 }
3219
3220 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3221 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
drh10dfbbb2008-04-16 12:58:53 +00003222 value = (char*)Tcl_GetByteArrayFromObj(objv[3], &bytes);
danielk197751e3d8e2004-05-20 01:12:34 +00003223 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
3224
danielk1977d8123362004-06-12 09:25:12 +00003225 rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
drhc60d0442004-09-30 13:43:13 +00003226 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003227 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +00003228 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003229 return TCL_ERROR;
3230 }
3231
3232 return TCL_OK;
3233}
3234
drh241db312004-06-22 12:46:53 +00003235/*
danielk1977161fb792006-01-24 10:58:21 +00003236** Usage: sqlite3_bind_text16 ?-static? STMT N STRING BYTES
drh241db312004-06-22 12:46:53 +00003237**
3238** Test the sqlite3_bind_text16 interface. STMT is a prepared statement.
3239** N is the index of a wildcard in the prepared statement. This command
3240** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes
3241** long.
3242*/
danielk197751e3d8e2004-05-20 01:12:34 +00003243static int test_bind_text16(
3244 void * clientData,
3245 Tcl_Interp *interp,
3246 int objc,
3247 Tcl_Obj *CONST objv[]
3248){
drh5436dc22004-11-14 04:04:17 +00003249#ifndef SQLITE_OMIT_UTF16
danielk197751e3d8e2004-05-20 01:12:34 +00003250 sqlite3_stmt *pStmt;
3251 int idx;
3252 int bytes;
3253 char *value;
3254 int rc;
3255
drh7da5fcb2012-03-30 14:59:43 +00003256 void (*xDel)(void*) = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
danielk1977161fb792006-01-24 10:58:21 +00003257 Tcl_Obj *oStmt = objv[objc-4];
3258 Tcl_Obj *oN = objv[objc-3];
3259 Tcl_Obj *oString = objv[objc-2];
3260 Tcl_Obj *oBytes = objv[objc-1];
3261
3262 if( objc!=5 && objc!=6){
danielk197751e3d8e2004-05-20 01:12:34 +00003263 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00003264 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003265 return TCL_ERROR;
3266 }
3267
danielk1977161fb792006-01-24 10:58:21 +00003268 if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR;
3269 if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR;
3270 value = (char*)Tcl_GetByteArrayFromObj(oString, 0);
3271 if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003272
danielk1977161fb792006-01-24 10:58:21 +00003273 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel);
drhc60d0442004-09-30 13:43:13 +00003274 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003275 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +00003276 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003277 return TCL_ERROR;
3278 }
3279
drh5436dc22004-11-14 04:04:17 +00003280#endif /* SQLITE_OMIT_UTF16 */
danielk197751e3d8e2004-05-20 01:12:34 +00003281 return TCL_OK;
3282}
3283
drh241db312004-06-22 12:46:53 +00003284/*
danielk19775b159dc2007-05-17 16:34:43 +00003285** Usage: sqlite3_bind_blob ?-static? STMT N DATA BYTES
drh241db312004-06-22 12:46:53 +00003286**
3287** Test the sqlite3_bind_blob interface. STMT is a prepared statement.
3288** N is the index of a wildcard in the prepared statement. This command
3289** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size.
3290*/
danielk197751e3d8e2004-05-20 01:12:34 +00003291static int test_bind_blob(
3292 void * clientData,
3293 Tcl_Interp *interp,
3294 int objc,
3295 Tcl_Obj *CONST objv[]
3296){
3297 sqlite3_stmt *pStmt;
3298 int idx;
3299 int bytes;
3300 char *value;
3301 int rc;
danielk19775b159dc2007-05-17 16:34:43 +00003302 sqlite3_destructor_type xDestructor = SQLITE_TRANSIENT;
danielk197751e3d8e2004-05-20 01:12:34 +00003303
danielk19775b159dc2007-05-17 16:34:43 +00003304 if( objc!=5 && objc!=6 ){
danielk197751e3d8e2004-05-20 01:12:34 +00003305 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00003306 Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003307 return TCL_ERROR;
3308 }
3309
danielk19775b159dc2007-05-17 16:34:43 +00003310 if( objc==6 ){
3311 xDestructor = SQLITE_STATIC;
3312 objv++;
3313 }
3314
danielk197751e3d8e2004-05-20 01:12:34 +00003315 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3316 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3317 value = Tcl_GetString(objv[3]);
danielk197749e46432004-05-27 13:55:27 +00003318 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003319
danielk19775b159dc2007-05-17 16:34:43 +00003320 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, xDestructor);
drhc60d0442004-09-30 13:43:13 +00003321 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00003322 if( rc!=SQLITE_OK ){
3323 return TCL_ERROR;
3324 }
3325
3326 return TCL_OK;
3327}
3328
drh99ee3602003-02-16 19:13:36 +00003329/*
drh75f6a032004-07-15 14:15:00 +00003330** Usage: sqlite3_bind_parameter_count STMT
3331**
3332** Return the number of wildcards in the given statement.
3333*/
3334static int test_bind_parameter_count(
3335 void * clientData,
3336 Tcl_Interp *interp,
3337 int objc,
3338 Tcl_Obj *CONST objv[]
3339){
3340 sqlite3_stmt *pStmt;
3341
3342 if( objc!=2 ){
3343 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
3344 return TCL_ERROR;
3345 }
3346 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3347 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
3348 return TCL_OK;
3349}
3350
3351/*
drh895d7472004-08-20 16:02:39 +00003352** Usage: sqlite3_bind_parameter_name STMT N
3353**
3354** Return the name of the Nth wildcard. The first wildcard is 1.
3355** An empty string is returned if N is out of range or if the wildcard
3356** is nameless.
3357*/
3358static int test_bind_parameter_name(
3359 void * clientData,
3360 Tcl_Interp *interp,
3361 int objc,
3362 Tcl_Obj *CONST objv[]
3363){
3364 sqlite3_stmt *pStmt;
3365 int i;
3366
3367 if( objc!=3 ){
3368 Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
3369 return TCL_ERROR;
3370 }
3371 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3372 if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
3373 Tcl_SetObjResult(interp,
3374 Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
3375 );
3376 return TCL_OK;
3377}
3378
3379/*
drhfa6bc002004-09-07 16:19:52 +00003380** Usage: sqlite3_bind_parameter_index STMT NAME
3381**
3382** Return the index of the wildcard called NAME. Return 0 if there is
3383** no such wildcard.
3384*/
3385static int test_bind_parameter_index(
3386 void * clientData,
3387 Tcl_Interp *interp,
3388 int objc,
3389 Tcl_Obj *CONST objv[]
3390){
3391 sqlite3_stmt *pStmt;
3392
3393 if( objc!=3 ){
3394 Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
3395 return TCL_ERROR;
3396 }
3397 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3398 Tcl_SetObjResult(interp,
3399 Tcl_NewIntObj(
3400 sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
3401 )
3402 );
3403 return TCL_OK;
3404}
3405
3406/*
danielk1977600dd0b2005-01-20 01:14:23 +00003407** Usage: sqlite3_clear_bindings STMT
3408**
3409*/
danielk1977600dd0b2005-01-20 01:14:23 +00003410static int test_clear_bindings(
3411 void * clientData,
3412 Tcl_Interp *interp,
3413 int objc,
3414 Tcl_Obj *CONST objv[]
3415){
3416 sqlite3_stmt *pStmt;
3417
3418 if( objc!=2 ){
3419 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
3420 return TCL_ERROR;
3421 }
3422 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3423 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
3424 return TCL_OK;
3425}
drhf9cb7f52006-06-27 20:06:44 +00003426
3427/*
3428** Usage: sqlite3_sleep MILLISECONDS
3429*/
3430static int test_sleep(
3431 void * clientData,
3432 Tcl_Interp *interp,
3433 int objc,
3434 Tcl_Obj *CONST objv[]
3435){
3436 int ms;
3437
3438 if( objc!=2 ){
3439 Tcl_WrongNumArgs(interp, 1, objv, "MILLISECONDS");
3440 return TCL_ERROR;
3441 }
3442 if( Tcl_GetIntFromObj(interp, objv[1], &ms) ){
3443 return TCL_ERROR;
3444 }
3445 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(ms)));
3446 return TCL_OK;
3447}
danielk1977600dd0b2005-01-20 01:14:23 +00003448
3449/*
drh99dfe5e2008-10-30 15:03:15 +00003450** Usage: sqlite3_extended_errcode DB
3451**
3452** Return the string representation of the most recent sqlite3_* API
3453** error code. e.g. "SQLITE_ERROR".
3454*/
3455static int test_ex_errcode(
3456 void * clientData,
3457 Tcl_Interp *interp,
3458 int objc,
3459 Tcl_Obj *CONST objv[]
3460){
3461 sqlite3 *db;
3462 int rc;
3463
3464 if( objc!=2 ){
3465 Tcl_AppendResult(interp, "wrong # args: should be \"",
3466 Tcl_GetString(objv[0]), " DB", 0);
3467 return TCL_ERROR;
3468 }
3469 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3470 rc = sqlite3_extended_errcode(db);
3471 Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0);
3472 return TCL_OK;
3473}
3474
3475
3476/*
danielk19776622cce2004-05-20 11:00:52 +00003477** Usage: sqlite3_errcode DB
3478**
3479** Return the string representation of the most recent sqlite3_* API
3480** error code. e.g. "SQLITE_ERROR".
3481*/
3482static int test_errcode(
3483 void * clientData,
3484 Tcl_Interp *interp,
3485 int objc,
3486 Tcl_Obj *CONST objv[]
3487){
3488 sqlite3 *db;
drh4ac285a2006-09-15 07:28:50 +00003489 int rc;
danielk19776622cce2004-05-20 11:00:52 +00003490
3491 if( objc!=2 ){
3492 Tcl_AppendResult(interp, "wrong # args: should be \"",
3493 Tcl_GetString(objv[0]), " DB", 0);
3494 return TCL_ERROR;
3495 }
3496 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
drh4ac285a2006-09-15 07:28:50 +00003497 rc = sqlite3_errcode(db);
drh99dfe5e2008-10-30 15:03:15 +00003498 Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0);
danielk19776622cce2004-05-20 11:00:52 +00003499 return TCL_OK;
3500}
3501
3502/*
danielk197704103022009-02-03 16:51:24 +00003503** Usage: sqlite3_errmsg DB
danielk19776622cce2004-05-20 11:00:52 +00003504**
3505** Returns the UTF-8 representation of the error message string for the
3506** most recent sqlite3_* API call.
3507*/
3508static int test_errmsg(
3509 void * clientData,
3510 Tcl_Interp *interp,
3511 int objc,
3512 Tcl_Obj *CONST objv[]
3513){
drh9bb575f2004-09-06 17:24:11 +00003514 sqlite3 *db;
danielk19776622cce2004-05-20 11:00:52 +00003515 const char *zErr;
3516
3517 if( objc!=2 ){
3518 Tcl_AppendResult(interp, "wrong # args: should be \"",
3519 Tcl_GetString(objv[0]), " DB", 0);
3520 return TCL_ERROR;
3521 }
3522 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3523
3524 zErr = sqlite3_errmsg(db);
3525 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
3526 return TCL_OK;
3527}
3528
3529/*
3530** Usage: test_errmsg16 DB
3531**
3532** Returns the UTF-16 representation of the error message string for the
3533** most recent sqlite3_* API call. This is a byte array object at the TCL
3534** level, and it includes the 0x00 0x00 terminator bytes at the end of the
3535** UTF-16 string.
3536*/
3537static int test_errmsg16(
3538 void * clientData,
3539 Tcl_Interp *interp,
3540 int objc,
3541 Tcl_Obj *CONST objv[]
3542){
drh5436dc22004-11-14 04:04:17 +00003543#ifndef SQLITE_OMIT_UTF16
drh9bb575f2004-09-06 17:24:11 +00003544 sqlite3 *db;
danielk19776622cce2004-05-20 11:00:52 +00003545 const void *zErr;
drhaed382f2009-04-01 18:40:32 +00003546 const char *z;
danielk1977950f0542006-01-18 05:51:57 +00003547 int bytes = 0;
danielk19776622cce2004-05-20 11:00:52 +00003548
3549 if( objc!=2 ){
3550 Tcl_AppendResult(interp, "wrong # args: should be \"",
3551 Tcl_GetString(objv[0]), " DB", 0);
3552 return TCL_ERROR;
3553 }
3554 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3555
3556 zErr = sqlite3_errmsg16(db);
danielk1977950f0542006-01-18 05:51:57 +00003557 if( zErr ){
drhaed382f2009-04-01 18:40:32 +00003558 z = zErr;
3559 for(bytes=0; z[bytes] || z[bytes+1]; bytes+=2){}
danielk1977950f0542006-01-18 05:51:57 +00003560 }
danielk19776622cce2004-05-20 11:00:52 +00003561 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
drh5436dc22004-11-14 04:04:17 +00003562#endif /* SQLITE_OMIT_UTF16 */
danielk19776622cce2004-05-20 11:00:52 +00003563 return TCL_OK;
3564}
3565
3566/*
drh1c767f02009-01-09 02:49:31 +00003567** Usage: sqlite3_prepare DB sql bytes ?tailvar?
danielk19776622cce2004-05-20 11:00:52 +00003568**
3569** Compile up to <bytes> bytes of the supplied SQL string <sql> using
3570** database handle <DB>. The parameter <tailval> is the name of a global
3571** variable that is set to the unused portion of <sql> (if any). A
3572** STMT handle is returned.
3573*/
3574static int test_prepare(
3575 void * clientData,
3576 Tcl_Interp *interp,
3577 int objc,
3578 Tcl_Obj *CONST objv[]
3579){
3580 sqlite3 *db;
3581 const char *zSql;
3582 int bytes;
3583 const char *zTail = 0;
3584 sqlite3_stmt *pStmt = 0;
3585 char zBuf[50];
danielk19774ad17132004-05-21 01:47:26 +00003586 int rc;
danielk19776622cce2004-05-20 11:00:52 +00003587
drh1c767f02009-01-09 02:49:31 +00003588 if( objc!=5 && objc!=4 ){
danielk19776622cce2004-05-20 11:00:52 +00003589 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh1c767f02009-01-09 02:49:31 +00003590 Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
danielk19776622cce2004-05-20 11:00:52 +00003591 return TCL_ERROR;
3592 }
3593 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3594 zSql = Tcl_GetString(objv[2]);
3595 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
3596
drh1c767f02009-01-09 02:49:31 +00003597 rc = sqlite3_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
dan937d0de2009-10-15 18:35:38 +00003598 Tcl_ResetResult(interp);
drhc60d0442004-09-30 13:43:13 +00003599 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drh1c767f02009-01-09 02:49:31 +00003600 if( zTail && objc>=5 ){
danielk19776622cce2004-05-20 11:00:52 +00003601 if( bytes>=0 ){
drh83cc1392012-04-19 18:04:28 +00003602 bytes = bytes - (int)(zTail-zSql);
danielk19776622cce2004-05-20 11:00:52 +00003603 }
drh7da5fcb2012-03-30 14:59:43 +00003604 if( (int)strlen(zTail)<bytes ){
drh83cc1392012-04-19 18:04:28 +00003605 bytes = (int)strlen(zTail);
danielk19773a2c8c82008-04-03 14:36:25 +00003606 }
danielk19776622cce2004-05-20 11:00:52 +00003607 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
3608 }
danielk19774ad17132004-05-21 01:47:26 +00003609 if( rc!=SQLITE_OK ){
3610 assert( pStmt==0 );
3611 sprintf(zBuf, "(%d) ", rc);
3612 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
3613 return TCL_ERROR;
3614 }
danielk19776622cce2004-05-20 11:00:52 +00003615
danielk19774ad17132004-05-21 01:47:26 +00003616 if( pStmt ){
drh64b1bea2006-01-15 02:30:57 +00003617 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
danielk19774ad17132004-05-21 01:47:26 +00003618 Tcl_AppendResult(interp, zBuf, 0);
3619 }
danielk19776622cce2004-05-20 11:00:52 +00003620 return TCL_OK;
3621}
3622
3623/*
drh1c767f02009-01-09 02:49:31 +00003624** Usage: sqlite3_prepare_v2 DB sql bytes ?tailvar?
drhb900aaf2006-11-09 00:24:53 +00003625**
3626** Compile up to <bytes> bytes of the supplied SQL string <sql> using
3627** database handle <DB>. The parameter <tailval> is the name of a global
3628** variable that is set to the unused portion of <sql> (if any). A
3629** STMT handle is returned.
3630*/
3631static int test_prepare_v2(
3632 void * clientData,
3633 Tcl_Interp *interp,
3634 int objc,
3635 Tcl_Obj *CONST objv[]
3636){
3637 sqlite3 *db;
3638 const char *zSql;
dand89b8342014-11-27 11:36:36 +00003639 char *zCopy = 0; /* malloc() copy of zSql */
drhb900aaf2006-11-09 00:24:53 +00003640 int bytes;
3641 const char *zTail = 0;
3642 sqlite3_stmt *pStmt = 0;
3643 char zBuf[50];
3644 int rc;
3645
drh1c767f02009-01-09 02:49:31 +00003646 if( objc!=5 && objc!=4 ){
drhb900aaf2006-11-09 00:24:53 +00003647 Tcl_AppendResult(interp, "wrong # args: should be \"",
3648 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
3649 return TCL_ERROR;
3650 }
3651 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3652 zSql = Tcl_GetString(objv[2]);
3653 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
3654
dand89b8342014-11-27 11:36:36 +00003655 /* Instead of using zSql directly, make a copy into a buffer obtained
3656 ** directly from malloc(). The idea is to make it easier for valgrind
3657 ** to spot buffer overreads. */
3658 if( bytes>=0 ){
3659 zCopy = malloc(bytes);
3660 memcpy(zCopy, zSql, bytes);
3661 }else{
drh2c3abeb2014-12-05 00:32:09 +00003662 int n = (int)strlen(zSql) + 1;
dand89b8342014-11-27 11:36:36 +00003663 zCopy = malloc(n);
3664 memcpy(zCopy, zSql, n);
3665 }
3666 rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, objc>=5 ? &zTail : 0);
3667 free(zCopy);
3668 zTail = &zSql[(zTail - zCopy)];
3669
danielk19777e29e952007-04-19 11:09:01 +00003670 assert(rc==SQLITE_OK || pStmt==0);
dan937d0de2009-10-15 18:35:38 +00003671 Tcl_ResetResult(interp);
drhb900aaf2006-11-09 00:24:53 +00003672 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhe5d7bf12014-12-23 20:05:19 +00003673 if( rc==SQLITE_OK && zTail && objc>=5 ){
drhb900aaf2006-11-09 00:24:53 +00003674 if( bytes>=0 ){
drh83cc1392012-04-19 18:04:28 +00003675 bytes = bytes - (int)(zTail-zSql);
drhb900aaf2006-11-09 00:24:53 +00003676 }
3677 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
3678 }
3679 if( rc!=SQLITE_OK ){
3680 assert( pStmt==0 );
3681 sprintf(zBuf, "(%d) ", rc);
3682 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
3683 return TCL_ERROR;
3684 }
3685
3686 if( pStmt ){
3687 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
3688 Tcl_AppendResult(interp, zBuf, 0);
3689 }
3690 return TCL_OK;
3691}
3692
3693/*
drh4837f532008-05-23 14:49:49 +00003694** Usage: sqlite3_prepare_tkt3134 DB
3695**
3696** Generate a prepared statement for a zero-byte string as a test
peter.d.reid60ec9142014-09-06 16:39:46 +00003697** for ticket #3134. The string should be preceded by a zero byte.
drh4837f532008-05-23 14:49:49 +00003698*/
3699static int test_prepare_tkt3134(
3700 void * clientData,
3701 Tcl_Interp *interp,
3702 int objc,
3703 Tcl_Obj *CONST objv[]
3704){
3705 sqlite3 *db;
3706 static const char zSql[] = "\000SELECT 1";
3707 sqlite3_stmt *pStmt = 0;
3708 char zBuf[50];
3709 int rc;
3710
3711 if( objc!=2 ){
3712 Tcl_AppendResult(interp, "wrong # args: should be \"",
3713 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
3714 return TCL_ERROR;
3715 }
3716 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3717 rc = sqlite3_prepare_v2(db, &zSql[1], 0, &pStmt, 0);
3718 assert(rc==SQLITE_OK || pStmt==0);
3719 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
3720 if( rc!=SQLITE_OK ){
3721 assert( pStmt==0 );
3722 sprintf(zBuf, "(%d) ", rc);
3723 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
3724 return TCL_ERROR;
3725 }
3726
3727 if( pStmt ){
3728 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
3729 Tcl_AppendResult(interp, zBuf, 0);
3730 }
3731 return TCL_OK;
3732}
3733
3734/*
drhb900aaf2006-11-09 00:24:53 +00003735** Usage: sqlite3_prepare16 DB sql bytes tailvar
danielk19776622cce2004-05-20 11:00:52 +00003736**
3737** Compile up to <bytes> bytes of the supplied SQL string <sql> using
3738** database handle <DB>. The parameter <tailval> is the name of a global
3739** variable that is set to the unused portion of <sql> (if any). A
3740** STMT handle is returned.
3741*/
3742static int test_prepare16(
3743 void * clientData,
3744 Tcl_Interp *interp,
3745 int objc,
3746 Tcl_Obj *CONST objv[]
3747){
drh5436dc22004-11-14 04:04:17 +00003748#ifndef SQLITE_OMIT_UTF16
danielk19776622cce2004-05-20 11:00:52 +00003749 sqlite3 *db;
3750 const void *zSql;
3751 const void *zTail = 0;
3752 Tcl_Obj *pTail = 0;
3753 sqlite3_stmt *pStmt = 0;
drhc60d0442004-09-30 13:43:13 +00003754 char zBuf[50];
3755 int rc;
danielk19776622cce2004-05-20 11:00:52 +00003756 int bytes; /* The integer specified as arg 3 */
3757 int objlen; /* The byte-array length of arg 2 */
3758
drh1c767f02009-01-09 02:49:31 +00003759 if( objc!=5 && objc!=4 ){
danielk19776622cce2004-05-20 11:00:52 +00003760 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh1c767f02009-01-09 02:49:31 +00003761 Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
danielk19776622cce2004-05-20 11:00:52 +00003762 return TCL_ERROR;
3763 }
3764 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3765 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
3766 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
3767
drh1c767f02009-01-09 02:49:31 +00003768 rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
drhc60d0442004-09-30 13:43:13 +00003769 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
3770 if( rc ){
danielk19776622cce2004-05-20 11:00:52 +00003771 return TCL_ERROR;
3772 }
3773
drh1c767f02009-01-09 02:49:31 +00003774 if( objc>=5 ){
3775 if( zTail ){
drh83cc1392012-04-19 18:04:28 +00003776 objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql);
drh1c767f02009-01-09 02:49:31 +00003777 }else{
3778 objlen = 0;
3779 }
3780 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
3781 Tcl_IncrRefCount(pTail);
3782 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
3783 Tcl_DecrRefCount(pTail);
danielk19776622cce2004-05-20 11:00:52 +00003784 }
danielk19776622cce2004-05-20 11:00:52 +00003785
danielk19774ad17132004-05-21 01:47:26 +00003786 if( pStmt ){
drh64b1bea2006-01-15 02:30:57 +00003787 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
danielk19774ad17132004-05-21 01:47:26 +00003788 }
danielk19776622cce2004-05-20 11:00:52 +00003789 Tcl_AppendResult(interp, zBuf, 0);
drh5436dc22004-11-14 04:04:17 +00003790#endif /* SQLITE_OMIT_UTF16 */
danielk19776622cce2004-05-20 11:00:52 +00003791 return TCL_OK;
3792}
3793
danielk19774ad17132004-05-21 01:47:26 +00003794/*
drh1c767f02009-01-09 02:49:31 +00003795** Usage: sqlite3_prepare16_v2 DB sql bytes ?tailvar?
drhb900aaf2006-11-09 00:24:53 +00003796**
3797** Compile up to <bytes> bytes of the supplied SQL string <sql> using
3798** database handle <DB>. The parameter <tailval> is the name of a global
3799** variable that is set to the unused portion of <sql> (if any). A
3800** STMT handle is returned.
3801*/
3802static int test_prepare16_v2(
3803 void * clientData,
3804 Tcl_Interp *interp,
3805 int objc,
3806 Tcl_Obj *CONST objv[]
3807){
3808#ifndef SQLITE_OMIT_UTF16
3809 sqlite3 *db;
3810 const void *zSql;
3811 const void *zTail = 0;
3812 Tcl_Obj *pTail = 0;
3813 sqlite3_stmt *pStmt = 0;
3814 char zBuf[50];
3815 int rc;
3816 int bytes; /* The integer specified as arg 3 */
3817 int objlen; /* The byte-array length of arg 2 */
3818
drh1c767f02009-01-09 02:49:31 +00003819 if( objc!=5 && objc!=4 ){
drhb900aaf2006-11-09 00:24:53 +00003820 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh1c767f02009-01-09 02:49:31 +00003821 Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
drhb900aaf2006-11-09 00:24:53 +00003822 return TCL_ERROR;
3823 }
3824 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3825 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
3826 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
3827
drh1c767f02009-01-09 02:49:31 +00003828 rc = sqlite3_prepare16_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
drhb900aaf2006-11-09 00:24:53 +00003829 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
3830 if( rc ){
3831 return TCL_ERROR;
3832 }
3833
drh1c767f02009-01-09 02:49:31 +00003834 if( objc>=5 ){
3835 if( zTail ){
drh83cc1392012-04-19 18:04:28 +00003836 objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql);
drh1c767f02009-01-09 02:49:31 +00003837 }else{
3838 objlen = 0;
3839 }
3840 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
3841 Tcl_IncrRefCount(pTail);
3842 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
3843 Tcl_DecrRefCount(pTail);
drhb900aaf2006-11-09 00:24:53 +00003844 }
drhb900aaf2006-11-09 00:24:53 +00003845
3846 if( pStmt ){
3847 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
3848 }
3849 Tcl_AppendResult(interp, zBuf, 0);
3850#endif /* SQLITE_OMIT_UTF16 */
3851 return TCL_OK;
3852}
3853
3854/*
danielk19774ad17132004-05-21 01:47:26 +00003855** Usage: sqlite3_open filename ?options-list?
3856*/
3857static int test_open(
3858 void * clientData,
3859 Tcl_Interp *interp,
3860 int objc,
3861 Tcl_Obj *CONST objv[]
3862){
3863 const char *zFilename;
3864 sqlite3 *db;
danielk19774ad17132004-05-21 01:47:26 +00003865 char zBuf[100];
3866
drhafc91042008-02-21 02:09:45 +00003867 if( objc!=3 && objc!=2 && objc!=1 ){
danielk19774ad17132004-05-21 01:47:26 +00003868 Tcl_AppendResult(interp, "wrong # args: should be \"",
3869 Tcl_GetString(objv[0]), " filename options-list", 0);
3870 return TCL_ERROR;
3871 }
3872
drhafc91042008-02-21 02:09:45 +00003873 zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0;
drhcaffb1a2012-01-30 18:00:31 +00003874 sqlite3_open(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00003875
drh64b1bea2006-01-15 02:30:57 +00003876 if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
danielk19774ad17132004-05-21 01:47:26 +00003877 Tcl_AppendResult(interp, zBuf, 0);
3878 return TCL_OK;
3879}
3880
3881/*
dan286ab7c2011-05-06 18:34:54 +00003882** Usage: sqlite3_open_v2 FILENAME FLAGS VFS
3883*/
3884static int test_open_v2(
3885 void * clientData,
3886 Tcl_Interp *interp,
3887 int objc,
3888 Tcl_Obj *CONST objv[]
3889){
3890 const char *zFilename;
3891 const char *zVfs;
3892 int flags = 0;
3893 sqlite3 *db;
3894 int rc;
3895 char zBuf[100];
3896
3897 int nFlag;
3898 Tcl_Obj **apFlag;
3899 int i;
3900
3901 if( objc!=4 ){
3902 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS");
3903 return TCL_ERROR;
3904 }
3905 zFilename = Tcl_GetString(objv[1]);
3906 zVfs = Tcl_GetString(objv[3]);
3907 if( zVfs[0]==0x00 ) zVfs = 0;
3908
3909 rc = Tcl_ListObjGetElements(interp, objv[2], &nFlag, &apFlag);
3910 if( rc!=TCL_OK ) return rc;
3911 for(i=0; i<nFlag; i++){
3912 int iFlag;
3913 struct OpenFlag {
3914 const char *zFlag;
3915 int flag;
3916 } aFlag[] = {
3917 { "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY },
3918 { "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE },
3919 { "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE },
3920 { "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE },
3921 { "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE },
3922 { "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY },
3923 { "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB },
3924 { "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB },
3925 { "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB },
3926 { "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL },
3927 { "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL },
3928 { "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL },
3929 { "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL },
3930 { "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX },
3931 { "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX },
3932 { "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE },
3933 { "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE },
3934 { "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL },
3935 { "SQLITE_OPEN_URI", SQLITE_OPEN_URI },
3936 { 0, 0 }
3937 };
3938 rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]),
3939 "flag", 0, &iFlag
3940 );
3941 if( rc!=TCL_OK ) return rc;
3942 flags |= aFlag[iFlag].flag;
3943 }
3944
3945 rc = sqlite3_open_v2(zFilename, &db, flags, zVfs);
3946 if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
3947 Tcl_AppendResult(interp, zBuf, 0);
3948 return TCL_OK;
3949}
3950
3951/*
danielk19774ad17132004-05-21 01:47:26 +00003952** Usage: sqlite3_open16 filename options
3953*/
3954static int test_open16(
3955 void * clientData,
3956 Tcl_Interp *interp,
3957 int objc,
3958 Tcl_Obj *CONST objv[]
3959){
drh5436dc22004-11-14 04:04:17 +00003960#ifndef SQLITE_OMIT_UTF16
danielk19774ad17132004-05-21 01:47:26 +00003961 const void *zFilename;
3962 sqlite3 *db;
danielk19774ad17132004-05-21 01:47:26 +00003963 char zBuf[100];
3964
3965 if( objc!=3 ){
3966 Tcl_AppendResult(interp, "wrong # args: should be \"",
3967 Tcl_GetString(objv[0]), " filename options-list", 0);
3968 return TCL_ERROR;
3969 }
3970
3971 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
drhcaffb1a2012-01-30 18:00:31 +00003972 sqlite3_open16(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00003973
drh64b1bea2006-01-15 02:30:57 +00003974 if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
danielk19774ad17132004-05-21 01:47:26 +00003975 Tcl_AppendResult(interp, zBuf, 0);
drh5436dc22004-11-14 04:04:17 +00003976#endif /* SQLITE_OMIT_UTF16 */
danielk19774ad17132004-05-21 01:47:26 +00003977 return TCL_OK;
3978}
drhd3d39e92004-05-20 22:16:29 +00003979
3980/*
danielk1977bc6ada42004-06-30 08:20:16 +00003981** Usage: sqlite3_complete16 <UTF-16 string>
3982**
3983** Return 1 if the supplied argument is a complete SQL statement, or zero
3984** otherwise.
3985*/
3986static int test_complete16(
3987 void * clientData,
3988 Tcl_Interp *interp,
3989 int objc,
3990 Tcl_Obj *CONST objv[]
3991){
drhccae6022005-02-26 17:31:26 +00003992#if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16)
danielk1977bc6ada42004-06-30 08:20:16 +00003993 char *zBuf;
3994
3995 if( objc!=2 ){
3996 Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
3997 return TCL_ERROR;
3998 }
3999
drh03d847e2005-12-09 20:21:58 +00004000 zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0);
danielk1977bc6ada42004-06-30 08:20:16 +00004001 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
drhccae6022005-02-26 17:31:26 +00004002#endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */
danielk1977bc6ada42004-06-30 08:20:16 +00004003 return TCL_OK;
4004}
4005
4006/*
danielk1977106bb232004-05-21 10:08:53 +00004007** Usage: sqlite3_step STMT
4008**
4009** Advance the statement to the next row.
4010*/
danielk197717240fd2004-05-26 00:07:25 +00004011static int test_step(
danielk1977106bb232004-05-21 10:08:53 +00004012 void * clientData,
4013 Tcl_Interp *interp,
4014 int objc,
4015 Tcl_Obj *CONST objv[]
4016){
4017 sqlite3_stmt *pStmt;
4018 int rc;
4019
danielk1977e1cd9872004-05-22 10:33:04 +00004020 if( objc!=2 ){
danielk1977106bb232004-05-21 10:08:53 +00004021 Tcl_AppendResult(interp, "wrong # args: should be \"",
4022 Tcl_GetString(objv[0]), " STMT", 0);
4023 return TCL_ERROR;
4024 }
4025
4026 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
danielk197717240fd2004-05-26 00:07:25 +00004027 rc = sqlite3_step(pStmt);
danielk1977106bb232004-05-21 10:08:53 +00004028
danielk1977fbcd5852004-06-15 02:44:18 +00004029 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
drh4f0c5872007-03-26 22:05:01 +00004030 Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
danielk1977e1cd9872004-05-22 10:33:04 +00004031 return TCL_OK;
4032}
4033
danielk1977404ca072009-03-16 13:19:36 +00004034static int test_sql(
4035 void * clientData,
4036 Tcl_Interp *interp,
4037 int objc,
4038 Tcl_Obj *CONST objv[]
4039){
4040 sqlite3_stmt *pStmt;
4041
4042 if( objc!=2 ){
4043 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
4044 return TCL_ERROR;
4045 }
4046
4047 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4048 Tcl_SetResult(interp, (char *)sqlite3_sql(pStmt), TCL_VOLATILE);
4049 return TCL_OK;
4050}
4051
danielk1977e1cd9872004-05-22 10:33:04 +00004052/*
danielk197717240fd2004-05-26 00:07:25 +00004053** Usage: sqlite3_column_count STMT
4054**
4055** Return the number of columns returned by the sql statement STMT.
4056*/
4057static int test_column_count(
4058 void * clientData,
4059 Tcl_Interp *interp,
4060 int objc,
4061 Tcl_Obj *CONST objv[]
4062){
4063 sqlite3_stmt *pStmt;
4064
4065 if( objc!=2 ){
4066 Tcl_AppendResult(interp, "wrong # args: should be \"",
4067 Tcl_GetString(objv[0]), " STMT column", 0);
4068 return TCL_ERROR;
4069 }
4070
4071 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4072
4073 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
4074 return TCL_OK;
4075}
4076
4077/*
danielk19773cf86062004-05-26 10:11:05 +00004078** Usage: sqlite3_column_type STMT column
4079**
4080** Return the type of the data in column 'column' of the current row.
4081*/
4082static int test_column_type(
4083 void * clientData,
4084 Tcl_Interp *interp,
4085 int objc,
4086 Tcl_Obj *CONST objv[]
4087){
4088 sqlite3_stmt *pStmt;
4089 int col;
4090 int tp;
4091
4092 if( objc!=3 ){
4093 Tcl_AppendResult(interp, "wrong # args: should be \"",
4094 Tcl_GetString(objv[0]), " STMT column", 0);
4095 return TCL_ERROR;
4096 }
4097
4098 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4099 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4100
4101 tp = sqlite3_column_type(pStmt, col);
4102 switch( tp ){
drh9c054832004-05-31 18:51:57 +00004103 case SQLITE_INTEGER:
danielk19773cf86062004-05-26 10:11:05 +00004104 Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
4105 break;
drh9c054832004-05-31 18:51:57 +00004106 case SQLITE_NULL:
danielk19773cf86062004-05-26 10:11:05 +00004107 Tcl_SetResult(interp, "NULL", TCL_STATIC);
4108 break;
drh9c054832004-05-31 18:51:57 +00004109 case SQLITE_FLOAT:
danielk19773cf86062004-05-26 10:11:05 +00004110 Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
4111 break;
drh9c054832004-05-31 18:51:57 +00004112 case SQLITE_TEXT:
danielk19773cf86062004-05-26 10:11:05 +00004113 Tcl_SetResult(interp, "TEXT", TCL_STATIC);
4114 break;
drh9c054832004-05-31 18:51:57 +00004115 case SQLITE_BLOB:
danielk19773cf86062004-05-26 10:11:05 +00004116 Tcl_SetResult(interp, "BLOB", TCL_STATIC);
4117 break;
4118 default:
4119 assert(0);
4120 }
4121
4122 return TCL_OK;
4123}
4124
4125/*
danielk197704f2e682004-05-27 01:04:07 +00004126** Usage: sqlite3_column_int64 STMT column
danielk19773cf86062004-05-26 10:11:05 +00004127**
4128** Return the data in column 'column' of the current row cast as an
danielk197704f2e682004-05-27 01:04:07 +00004129** wide (64-bit) integer.
danielk19773cf86062004-05-26 10:11:05 +00004130*/
danielk197704f2e682004-05-27 01:04:07 +00004131static int test_column_int64(
danielk19773cf86062004-05-26 10:11:05 +00004132 void * clientData,
4133 Tcl_Interp *interp,
4134 int objc,
4135 Tcl_Obj *CONST objv[]
4136){
4137 sqlite3_stmt *pStmt;
4138 int col;
danielk197704f2e682004-05-27 01:04:07 +00004139 i64 iVal;
danielk19773cf86062004-05-26 10:11:05 +00004140
4141 if( objc!=3 ){
4142 Tcl_AppendResult(interp, "wrong # args: should be \"",
4143 Tcl_GetString(objv[0]), " STMT column", 0);
4144 return TCL_ERROR;
4145 }
4146
4147 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4148 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4149
danielk197704f2e682004-05-27 01:04:07 +00004150 iVal = sqlite3_column_int64(pStmt, col);
4151 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
4152 return TCL_OK;
4153}
4154
4155/*
danielk1977ea61b2c2004-05-27 01:49:51 +00004156** Usage: sqlite3_column_blob STMT column
4157*/
4158static int test_column_blob(
4159 void * clientData,
4160 Tcl_Interp *interp,
4161 int objc,
4162 Tcl_Obj *CONST objv[]
4163){
4164 sqlite3_stmt *pStmt;
4165 int col;
4166
4167 int len;
danielk1977c572ef72004-05-27 09:28:41 +00004168 const void *pBlob;
danielk1977ea61b2c2004-05-27 01:49:51 +00004169
4170 if( objc!=3 ){
4171 Tcl_AppendResult(interp, "wrong # args: should be \"",
4172 Tcl_GetString(objv[0]), " STMT column", 0);
4173 return TCL_ERROR;
4174 }
4175
4176 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4177 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4178
danielk1977ea61b2c2004-05-27 01:49:51 +00004179 len = sqlite3_column_bytes(pStmt, col);
drh9310ef22007-04-27 17:16:20 +00004180 pBlob = sqlite3_column_blob(pStmt, col);
danielk1977ea61b2c2004-05-27 01:49:51 +00004181 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
4182 return TCL_OK;
4183}
4184
4185/*
danielk197704f2e682004-05-27 01:04:07 +00004186** Usage: sqlite3_column_double STMT column
4187**
4188** Return the data in column 'column' of the current row cast as a double.
4189*/
4190static int test_column_double(
4191 void * clientData,
4192 Tcl_Interp *interp,
4193 int objc,
4194 Tcl_Obj *CONST objv[]
4195){
4196 sqlite3_stmt *pStmt;
4197 int col;
4198 double rVal;
4199
4200 if( objc!=3 ){
4201 Tcl_AppendResult(interp, "wrong # args: should be \"",
4202 Tcl_GetString(objv[0]), " STMT column", 0);
4203 return TCL_ERROR;
4204 }
4205
4206 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4207 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4208
4209 rVal = sqlite3_column_double(pStmt, col);
danielk1977c572ef72004-05-27 09:28:41 +00004210 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
danielk19773cf86062004-05-26 10:11:05 +00004211 return TCL_OK;
4212}
4213
4214/*
danielk197717240fd2004-05-26 00:07:25 +00004215** Usage: sqlite3_data_count STMT
4216**
4217** Return the number of columns returned by the sql statement STMT.
4218*/
4219static int test_data_count(
4220 void * clientData,
4221 Tcl_Interp *interp,
4222 int objc,
4223 Tcl_Obj *CONST objv[]
4224){
4225 sqlite3_stmt *pStmt;
4226
4227 if( objc!=2 ){
4228 Tcl_AppendResult(interp, "wrong # args: should be \"",
4229 Tcl_GetString(objv[0]), " STMT column", 0);
4230 return TCL_ERROR;
4231 }
4232
4233 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4234
4235 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
4236 return TCL_OK;
4237}
4238
4239/*
danielk197704f2e682004-05-27 01:04:07 +00004240** Usage: sqlite3_column_text STMT column
4241**
4242** Usage: sqlite3_column_decltype STMT column
4243**
4244** Usage: sqlite3_column_name STMT column
4245*/
4246static int test_stmt_utf8(
drh241db312004-06-22 12:46:53 +00004247 void * clientData, /* Pointer to SQLite API function to be invoke */
danielk197704f2e682004-05-27 01:04:07 +00004248 Tcl_Interp *interp,
4249 int objc,
4250 Tcl_Obj *CONST objv[]
4251){
4252 sqlite3_stmt *pStmt;
4253 int col;
danielk197744a376f2008-08-12 15:04:58 +00004254 const char *(*xFunc)(sqlite3_stmt*, int);
danielk1977f93bbbe2004-05-27 10:30:52 +00004255 const char *zRet;
danielk197704f2e682004-05-27 01:04:07 +00004256
danielk197744a376f2008-08-12 15:04:58 +00004257 xFunc = (const char *(*)(sqlite3_stmt*, int))clientData;
danielk197704f2e682004-05-27 01:04:07 +00004258 if( objc!=3 ){
4259 Tcl_AppendResult(interp, "wrong # args: should be \"",
4260 Tcl_GetString(objv[0]), " STMT column", 0);
4261 return TCL_ERROR;
4262 }
4263
4264 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4265 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
danielk1977f93bbbe2004-05-27 10:30:52 +00004266 zRet = xFunc(pStmt, col);
4267 if( zRet ){
4268 Tcl_SetResult(interp, (char *)zRet, 0);
4269 }
danielk197704f2e682004-05-27 01:04:07 +00004270 return TCL_OK;
4271}
4272
danielk19776b456a22005-03-21 04:04:02 +00004273static int test_global_recover(
4274 void * clientData,
4275 Tcl_Interp *interp,
4276 int objc,
4277 Tcl_Obj *CONST objv[]
4278){
shaneeec556d2008-10-12 00:27:53 +00004279#ifndef SQLITE_OMIT_DEPRECATED
danielk19776b456a22005-03-21 04:04:02 +00004280 int rc;
4281 if( objc!=1 ){
4282 Tcl_WrongNumArgs(interp, 1, objv, "");
4283 return TCL_ERROR;
4284 }
4285 rc = sqlite3_global_recover();
drh4f0c5872007-03-26 22:05:01 +00004286 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
danielk19776b456a22005-03-21 04:04:02 +00004287#endif
4288 return TCL_OK;
4289}
4290
danielk197704f2e682004-05-27 01:04:07 +00004291/*
4292** Usage: sqlite3_column_text STMT column
4293**
4294** Usage: sqlite3_column_decltype STMT column
4295**
4296** Usage: sqlite3_column_name STMT column
4297*/
4298static int test_stmt_utf16(
drh241db312004-06-22 12:46:53 +00004299 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00004300 Tcl_Interp *interp,
4301 int objc,
4302 Tcl_Obj *CONST objv[]
4303){
drh5436dc22004-11-14 04:04:17 +00004304#ifndef SQLITE_OMIT_UTF16
danielk197704f2e682004-05-27 01:04:07 +00004305 sqlite3_stmt *pStmt;
4306 int col;
4307 Tcl_Obj *pRet;
4308 const void *zName16;
danielk197744a376f2008-08-12 15:04:58 +00004309 const void *(*xFunc)(sqlite3_stmt*, int);
danielk197704f2e682004-05-27 01:04:07 +00004310
danielk197744a376f2008-08-12 15:04:58 +00004311 xFunc = (const void *(*)(sqlite3_stmt*, int))clientData;
danielk197704f2e682004-05-27 01:04:07 +00004312 if( objc!=3 ){
4313 Tcl_AppendResult(interp, "wrong # args: should be \"",
4314 Tcl_GetString(objv[0]), " STMT column", 0);
4315 return TCL_ERROR;
4316 }
4317
4318 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4319 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4320
4321 zName16 = xFunc(pStmt, col);
danielk1977f93bbbe2004-05-27 10:30:52 +00004322 if( zName16 ){
drhaed382f2009-04-01 18:40:32 +00004323 int n;
4324 const char *z = zName16;
4325 for(n=0; z[n] || z[n+1]; n+=2){}
4326 pRet = Tcl_NewByteArrayObj(zName16, n+2);
danielk1977f93bbbe2004-05-27 10:30:52 +00004327 Tcl_SetObjResult(interp, pRet);
4328 }
drh5436dc22004-11-14 04:04:17 +00004329#endif /* SQLITE_OMIT_UTF16 */
danielk197704f2e682004-05-27 01:04:07 +00004330
4331 return TCL_OK;
4332}
4333
4334/*
4335** Usage: sqlite3_column_int STMT column
4336**
4337** Usage: sqlite3_column_bytes STMT column
4338**
4339** Usage: sqlite3_column_bytes16 STMT column
4340**
4341*/
4342static int test_stmt_int(
drh241db312004-06-22 12:46:53 +00004343 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00004344 Tcl_Interp *interp,
4345 int objc,
4346 Tcl_Obj *CONST objv[]
4347){
4348 sqlite3_stmt *pStmt;
4349 int col;
danielk197744a376f2008-08-12 15:04:58 +00004350 int (*xFunc)(sqlite3_stmt*, int);
danielk197704f2e682004-05-27 01:04:07 +00004351
danielk197755a25a12008-09-11 10:29:15 +00004352 xFunc = (int (*)(sqlite3_stmt*, int))clientData;
danielk197704f2e682004-05-27 01:04:07 +00004353 if( objc!=3 ){
4354 Tcl_AppendResult(interp, "wrong # args: should be \"",
4355 Tcl_GetString(objv[0]), " STMT column", 0);
4356 return TCL_ERROR;
4357 }
4358
4359 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4360 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4361
4362 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
4363 return TCL_OK;
4364}
4365
danielk19776622cce2004-05-20 11:00:52 +00004366/*
drhcacb2082005-01-11 15:28:33 +00004367** Usage: sqlite_set_magic DB MAGIC-NUMBER
4368**
4369** Set the db->magic value. This is used to test error recovery logic.
4370*/
4371static int sqlite_set_magic(
4372 void * clientData,
4373 Tcl_Interp *interp,
4374 int argc,
4375 char **argv
4376){
4377 sqlite3 *db;
4378 if( argc!=3 ){
4379 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4380 " DB MAGIC", 0);
4381 return TCL_ERROR;
4382 }
4383 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4384 if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
4385 db->magic = SQLITE_MAGIC_OPEN;
4386 }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
4387 db->magic = SQLITE_MAGIC_CLOSED;
4388 }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
4389 db->magic = SQLITE_MAGIC_BUSY;
4390 }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
4391 db->magic = SQLITE_MAGIC_ERROR;
drh902b9ee2008-12-05 17:17:07 +00004392 }else if( Tcl_GetInt(interp, argv[2], (int*)&db->magic) ){
drhcacb2082005-01-11 15:28:33 +00004393 return TCL_ERROR;
4394 }
4395 return TCL_OK;
4396}
4397
4398/*
drhc5cdca62005-01-11 16:54:14 +00004399** Usage: sqlite3_interrupt DB
4400**
4401** Trigger an interrupt on DB
4402*/
4403static int test_interrupt(
4404 void * clientData,
4405 Tcl_Interp *interp,
4406 int argc,
4407 char **argv
4408){
4409 sqlite3 *db;
4410 if( argc!=2 ){
4411 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
4412 return TCL_ERROR;
4413 }
4414 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4415 sqlite3_interrupt(db);
4416 return TCL_OK;
4417}
4418
drh79158e12005-09-06 21:40:45 +00004419static u8 *sqlite3_stack_baseline = 0;
4420
drhc5cdca62005-01-11 16:54:14 +00004421/*
drh79158e12005-09-06 21:40:45 +00004422** Fill the stack with a known bitpattern.
danielk1977600dd0b2005-01-20 01:14:23 +00004423*/
drh79158e12005-09-06 21:40:45 +00004424static void prepStack(void){
4425 int i;
4426 u32 bigBuf[65536];
drhbc2be0c2011-08-30 00:53:50 +00004427 for(i=0; i<sizeof(bigBuf)/sizeof(bigBuf[0]); i++) bigBuf[i] = 0xdeadbeef;
drh79158e12005-09-06 21:40:45 +00004428 sqlite3_stack_baseline = (u8*)&bigBuf[65536];
4429}
4430
4431/*
4432** Get the current stack depth. Used for debugging only.
4433*/
4434u64 sqlite3StackDepth(void){
4435 u8 x;
4436 return (u64)(sqlite3_stack_baseline - &x);
4437}
4438
4439/*
4440** Usage: sqlite3_stack_used DB SQL
4441**
4442** Try to measure the amount of stack space used by a call to sqlite3_exec
4443*/
4444static int test_stack_used(
danielk1977600dd0b2005-01-20 01:14:23 +00004445 void * clientData,
4446 Tcl_Interp *interp,
4447 int argc,
4448 char **argv
4449){
4450 sqlite3 *db;
drh79158e12005-09-06 21:40:45 +00004451 int i;
4452 if( argc!=3 ){
4453 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4454 " DB SQL", 0);
danielk1977600dd0b2005-01-20 01:14:23 +00004455 return TCL_ERROR;
4456 }
drh79158e12005-09-06 21:40:45 +00004457 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4458 prepStack();
drh37527852006-03-16 16:19:56 +00004459 (void)sqlite3_exec(db, argv[2], 0, 0, 0);
drh79158e12005-09-06 21:40:45 +00004460 for(i=65535; i>=0 && ((u32*)sqlite3_stack_baseline)[-i]==0xdeadbeef; i--){}
4461 Tcl_SetObjResult(interp, Tcl_NewIntObj(i*4));
danielk1977600dd0b2005-01-20 01:14:23 +00004462 return TCL_OK;
4463}
danielk1977600dd0b2005-01-20 01:14:23 +00004464
4465/*
danielk19779636c4e2005-01-25 04:27:54 +00004466** Usage: sqlite_delete_function DB function-name
4467**
4468** Delete the user function 'function-name' from database handle DB. It
4469** is assumed that the user function was created as UTF8, any number of
4470** arguments (the way the TCL interface does it).
4471*/
4472static int delete_function(
4473 void * clientData,
4474 Tcl_Interp *interp,
4475 int argc,
4476 char **argv
4477){
4478 int rc;
4479 sqlite3 *db;
4480 if( argc!=3 ){
4481 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4482 " DB function-name", 0);
4483 return TCL_ERROR;
4484 }
4485 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4486 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
drh4f0c5872007-03-26 22:05:01 +00004487 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
danielk19779636c4e2005-01-25 04:27:54 +00004488 return TCL_OK;
4489}
4490
4491/*
4492** Usage: sqlite_delete_collation DB collation-name
4493**
4494** Delete the collation sequence 'collation-name' from database handle
4495** DB. It is assumed that the collation sequence was created as UTF8 (the
4496** way the TCL interface does it).
4497*/
4498static int delete_collation(
4499 void * clientData,
4500 Tcl_Interp *interp,
4501 int argc,
4502 char **argv
4503){
4504 int rc;
4505 sqlite3 *db;
4506 if( argc!=3 ){
4507 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4508 " DB function-name", 0);
4509 return TCL_ERROR;
4510 }
4511 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4512 rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
drh4f0c5872007-03-26 22:05:01 +00004513 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
danielk19779636c4e2005-01-25 04:27:54 +00004514 return TCL_OK;
4515}
4516
4517/*
drh3e1d8e62005-05-26 16:23:34 +00004518** Usage: sqlite3_get_autocommit DB
4519**
4520** Return true if the database DB is currently in auto-commit mode.
4521** Return false if not.
4522*/
4523static int get_autocommit(
4524 void * clientData,
4525 Tcl_Interp *interp,
4526 int argc,
4527 char **argv
4528){
4529 char zBuf[30];
4530 sqlite3 *db;
4531 if( argc!=2 ){
4532 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4533 " DB", 0);
4534 return TCL_ERROR;
4535 }
4536 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4537 sprintf(zBuf, "%d", sqlite3_get_autocommit(db));
4538 Tcl_AppendResult(interp, zBuf, 0);
4539 return TCL_OK;
4540}
4541
4542/*
drh30867652006-07-06 10:59:57 +00004543** Usage: sqlite3_busy_timeout DB MS
4544**
4545** Set the busy timeout. This is more easily done using the timeout
4546** method of the TCL interface. But we need a way to test the case
4547** where it returns SQLITE_MISUSE.
4548*/
4549static int test_busy_timeout(
4550 void * clientData,
4551 Tcl_Interp *interp,
4552 int argc,
4553 char **argv
4554){
4555 int rc, ms;
4556 sqlite3 *db;
4557 if( argc!=3 ){
4558 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4559 " DB", 0);
4560 return TCL_ERROR;
4561 }
4562 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4563 if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR;
4564 rc = sqlite3_busy_timeout(db, ms);
mistachkine84d8d32013-04-29 03:09:10 +00004565 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drh30867652006-07-06 10:59:57 +00004566 return TCL_OK;
4567}
4568
4569/*
drh92febd92004-08-20 18:34:20 +00004570** Usage: tcl_variable_type VARIABLENAME
4571**
4572** Return the name of the internal representation for the
4573** value of the given variable.
4574*/
4575static int tcl_variable_type(
4576 void * clientData,
4577 Tcl_Interp *interp,
4578 int objc,
4579 Tcl_Obj *CONST objv[]
4580){
4581 Tcl_Obj *pVar;
4582 if( objc!=2 ){
4583 Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
4584 return TCL_ERROR;
4585 }
4586 pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
4587 if( pVar==0 ) return TCL_ERROR;
4588 if( pVar->typePtr ){
4589 Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
4590 }
4591 return TCL_OK;
4592}
4593
4594/*
drh6aafc292006-01-05 15:50:06 +00004595** Usage: sqlite3_release_memory ?N?
4596**
4597** Attempt to release memory currently held but not actually required.
4598** The integer N is the number of bytes we are trying to release. The
4599** return value is the amount of memory actually released.
4600*/
4601static int test_release_memory(
4602 void * clientData,
4603 Tcl_Interp *interp,
4604 int objc,
4605 Tcl_Obj *CONST objv[]
4606){
drh6f7adc82006-01-11 21:41:20 +00004607#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
drh6aafc292006-01-05 15:50:06 +00004608 int N;
4609 int amt;
4610 if( objc!=1 && objc!=2 ){
4611 Tcl_WrongNumArgs(interp, 1, objv, "?N?");
4612 return TCL_ERROR;
4613 }
4614 if( objc==2 ){
4615 if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
4616 }else{
4617 N = -1;
4618 }
4619 amt = sqlite3_release_memory(N);
4620 Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
4621#endif
4622 return TCL_OK;
4623}
4624
drh09419b42011-11-16 19:29:17 +00004625
4626/*
4627** Usage: sqlite3_db_release_memory DB
4628**
4629** Attempt to release memory currently held by database DB. Return the
4630** result code (which in the current implementation is always zero).
4631*/
4632static int test_db_release_memory(
4633 void * clientData,
4634 Tcl_Interp *interp,
4635 int objc,
4636 Tcl_Obj *CONST objv[]
4637){
4638 sqlite3 *db;
4639 int rc;
4640 if( objc!=2 ){
4641 Tcl_WrongNumArgs(interp, 1, objv, "DB");
4642 return TCL_ERROR;
4643 }
4644 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4645 rc = sqlite3_db_release_memory(db);
4646 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
4647 return TCL_OK;
4648}
4649
drh6aafc292006-01-05 15:50:06 +00004650/*
drh283829c2011-11-17 00:56:20 +00004651** Usage: sqlite3_db_filename DB DBNAME
4652**
4653** Return the name of a file associated with a database.
4654*/
4655static int test_db_filename(
4656 void * clientData,
4657 Tcl_Interp *interp,
4658 int objc,
4659 Tcl_Obj *CONST objv[]
4660){
4661 sqlite3 *db;
4662 const char *zDbName;
4663 if( objc!=3 ){
4664 Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
4665 return TCL_ERROR;
4666 }
4667 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4668 zDbName = Tcl_GetString(objv[2]);
4669 Tcl_AppendResult(interp, sqlite3_db_filename(db, zDbName), (void*)0);
4670 return TCL_OK;
4671}
4672
4673/*
drh421377e2012-03-15 21:28:54 +00004674** Usage: sqlite3_db_readonly DB DBNAME
4675**
4676** Return 1 or 0 if DBNAME is readonly or not. Return -1 if DBNAME does
4677** not exist.
4678*/
4679static int test_db_readonly(
4680 void * clientData,
4681 Tcl_Interp *interp,
4682 int objc,
4683 Tcl_Obj *CONST objv[]
4684){
4685 sqlite3 *db;
4686 const char *zDbName;
4687 if( objc!=3 ){
4688 Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
4689 return TCL_ERROR;
4690 }
4691 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4692 zDbName = Tcl_GetString(objv[2]);
4693 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_db_readonly(db, zDbName)));
4694 return TCL_OK;
4695}
4696
4697/*
drh6aafc292006-01-05 15:50:06 +00004698** Usage: sqlite3_soft_heap_limit ?N?
4699**
4700** Query or set the soft heap limit for the current thread. The
4701** limit is only changed if the N is present. The previous limit
4702** is returned.
4703*/
4704static int test_soft_heap_limit(
4705 void * clientData,
4706 Tcl_Interp *interp,
4707 int objc,
4708 Tcl_Obj *CONST objv[]
4709){
drhf82ccf62010-09-15 17:54:31 +00004710 sqlite3_int64 amt;
drhb3f787f2012-09-29 14:45:54 +00004711 Tcl_WideInt N = -1;
drh6aafc292006-01-05 15:50:06 +00004712 if( objc!=1 && objc!=2 ){
4713 Tcl_WrongNumArgs(interp, 1, objv, "?N?");
4714 return TCL_ERROR;
4715 }
drh6aafc292006-01-05 15:50:06 +00004716 if( objc==2 ){
drhf82ccf62010-09-15 17:54:31 +00004717 if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
drh6aafc292006-01-05 15:50:06 +00004718 }
drhf82ccf62010-09-15 17:54:31 +00004719 amt = sqlite3_soft_heap_limit64(N);
4720 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt));
drh6aafc292006-01-05 15:50:06 +00004721 return TCL_OK;
4722}
4723
4724/*
drhb4bc7052006-01-11 23:40:33 +00004725** Usage: sqlite3_thread_cleanup
4726**
4727** Call the sqlite3_thread_cleanup API.
4728*/
4729static int test_thread_cleanup(
4730 void * clientData,
4731 Tcl_Interp *interp,
4732 int objc,
4733 Tcl_Obj *CONST objv[]
4734){
shaneeec556d2008-10-12 00:27:53 +00004735#ifndef SQLITE_OMIT_DEPRECATED
drhb4bc7052006-01-11 23:40:33 +00004736 sqlite3_thread_cleanup();
shaneeec556d2008-10-12 00:27:53 +00004737#endif
drhb4bc7052006-01-11 23:40:33 +00004738 return TCL_OK;
4739}
4740
drhb4bc7052006-01-11 23:40:33 +00004741/*
drhc6ba55f2007-04-05 17:36:18 +00004742** Usage: sqlite3_pager_refcounts DB
4743**
drhf5345442007-04-09 12:45:02 +00004744** Return a list of numbers which are the PagerRefcount for all
4745** pagers on each database connection.
drhc6ba55f2007-04-05 17:36:18 +00004746*/
4747static int test_pager_refcounts(
4748 void * clientData,
4749 Tcl_Interp *interp,
4750 int objc,
4751 Tcl_Obj *CONST objv[]
4752){
4753 sqlite3 *db;
4754 int i;
4755 int v, *a;
4756 Tcl_Obj *pResult;
4757
4758 if( objc!=2 ){
4759 Tcl_AppendResult(interp, "wrong # args: should be \"",
drhf5345442007-04-09 12:45:02 +00004760 Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
drhc6ba55f2007-04-05 17:36:18 +00004761 return TCL_ERROR;
4762 }
4763 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4764 pResult = Tcl_NewObj();
4765 for(i=0; i<db->nDb; i++){
4766 if( db->aDb[i].pBt==0 ){
4767 v = -1;
4768 }else{
drh27641702007-08-22 02:56:42 +00004769 sqlite3_mutex_enter(db->mutex);
drhc6ba55f2007-04-05 17:36:18 +00004770 a = sqlite3PagerStats(sqlite3BtreePager(db->aDb[i].pBt));
4771 v = a[0];
drh27641702007-08-22 02:56:42 +00004772 sqlite3_mutex_leave(db->mutex);
drhc6ba55f2007-04-05 17:36:18 +00004773 }
4774 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(v));
4775 }
4776 Tcl_SetObjResult(interp, pResult);
4777 return TCL_OK;
4778}
4779
4780
4781/*
drh80788d82006-09-02 14:50:23 +00004782** tclcmd: working_64bit_int
4783**
4784** Some TCL builds (ex: cygwin) do not support 64-bit integers. This
4785** leads to a number of test failures. The present command checks the
4786** TCL build to see whether or not it supports 64-bit integers. It
4787** returns TRUE if it does and FALSE if not.
4788**
4789** This command is used to warn users that their TCL build is defective
4790** and that the errors they are seeing in the test scripts might be
4791** a result of their defective TCL rather than problems in SQLite.
4792*/
4793static int working_64bit_int(
4794 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4795 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4796 int objc, /* Number of arguments */
4797 Tcl_Obj *CONST objv[] /* Command arguments */
4798){
4799 Tcl_Obj *pTestObj;
4800 int working = 0;
4801
4802 pTestObj = Tcl_NewWideIntObj(1000000*(i64)1234567890);
4803 working = strcmp(Tcl_GetString(pTestObj), "1234567890000000")==0;
4804 Tcl_DecrRefCount(pTestObj);
4805 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(working));
4806 return TCL_OK;
4807}
4808
4809
4810/*
drh9bc54492007-10-23 14:49:59 +00004811** tclcmd: vfs_unlink_test
4812**
4813** This TCL command unregisters the primary VFS and then registers
4814** it back again. This is used to test the ability to register a
4815** VFS when none are previously registered, and the ability to
4816** unregister the only available VFS. Ticket #2738
4817*/
4818static int vfs_unlink_test(
4819 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4820 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4821 int objc, /* Number of arguments */
4822 Tcl_Obj *CONST objv[] /* Command arguments */
4823){
4824 int i;
drh91fd4d42008-01-19 20:11:25 +00004825 sqlite3_vfs *pMain;
drh9bc54492007-10-23 14:49:59 +00004826 sqlite3_vfs *apVfs[20];
drh91fd4d42008-01-19 20:11:25 +00004827 sqlite3_vfs one, two;
drh9bc54492007-10-23 14:49:59 +00004828
drh91fd4d42008-01-19 20:11:25 +00004829 sqlite3_vfs_unregister(0); /* Unregister of NULL is harmless */
4830 one.zName = "__one";
4831 two.zName = "__two";
4832
4833 /* Calling sqlite3_vfs_register with 2nd argument of 0 does not
4834 ** change the default VFS
4835 */
4836 pMain = sqlite3_vfs_find(0);
4837 sqlite3_vfs_register(&one, 0);
4838 assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
4839 sqlite3_vfs_register(&two, 0);
4840 assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
4841
4842 /* We can find a VFS by its name */
4843 assert( sqlite3_vfs_find("__one")==&one );
4844 assert( sqlite3_vfs_find("__two")==&two );
4845
4846 /* Calling sqlite_vfs_register with non-zero second parameter changes the
4847 ** default VFS, even if the 1st parameter is an existig VFS that is
4848 ** previously registered as the non-default.
4849 */
4850 sqlite3_vfs_register(&one, 1);
4851 assert( sqlite3_vfs_find("__one")==&one );
4852 assert( sqlite3_vfs_find("__two")==&two );
4853 assert( sqlite3_vfs_find(0)==&one );
4854 sqlite3_vfs_register(&two, 1);
4855 assert( sqlite3_vfs_find("__one")==&one );
4856 assert( sqlite3_vfs_find("__two")==&two );
4857 assert( sqlite3_vfs_find(0)==&two );
4858 if( pMain ){
4859 sqlite3_vfs_register(pMain, 1);
4860 assert( sqlite3_vfs_find("__one")==&one );
4861 assert( sqlite3_vfs_find("__two")==&two );
4862 assert( sqlite3_vfs_find(0)==pMain );
4863 }
4864
4865 /* Unlink the default VFS. Repeat until there are no more VFSes
4866 ** registered.
4867 */
drh9bc54492007-10-23 14:49:59 +00004868 for(i=0; i<sizeof(apVfs)/sizeof(apVfs[0]); i++){
4869 apVfs[i] = sqlite3_vfs_find(0);
4870 if( apVfs[i] ){
4871 assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
4872 sqlite3_vfs_unregister(apVfs[i]);
4873 assert( 0==sqlite3_vfs_find(apVfs[i]->zName) );
4874 }
4875 }
4876 assert( 0==sqlite3_vfs_find(0) );
mlcreech1f045332008-04-08 03:07:54 +00004877
4878 /* Register the main VFS as non-default (will be made default, since
4879 ** it'll be the only one in existence).
4880 */
4881 sqlite3_vfs_register(pMain, 0);
4882 assert( sqlite3_vfs_find(0)==pMain );
4883
4884 /* Un-register the main VFS again to restore an empty VFS list */
4885 sqlite3_vfs_unregister(pMain);
4886 assert( 0==sqlite3_vfs_find(0) );
drh91fd4d42008-01-19 20:11:25 +00004887
4888 /* Relink all VFSes in reverse order. */
drh9bc54492007-10-23 14:49:59 +00004889 for(i=sizeof(apVfs)/sizeof(apVfs[0])-1; i>=0; i--){
4890 if( apVfs[i] ){
4891 sqlite3_vfs_register(apVfs[i], 1);
4892 assert( apVfs[i]==sqlite3_vfs_find(0) );
4893 assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
4894 }
4895 }
drh91fd4d42008-01-19 20:11:25 +00004896
4897 /* Unregister out sample VFSes. */
4898 sqlite3_vfs_unregister(&one);
4899 sqlite3_vfs_unregister(&two);
4900
4901 /* Unregistering a VFS that is not currently registered is harmless */
4902 sqlite3_vfs_unregister(&one);
4903 sqlite3_vfs_unregister(&two);
4904 assert( sqlite3_vfs_find("__one")==0 );
4905 assert( sqlite3_vfs_find("__two")==0 );
4906
4907 /* We should be left with the original default VFS back as the
4908 ** original */
4909 assert( sqlite3_vfs_find(0)==pMain );
4910
drh9bc54492007-10-23 14:49:59 +00004911 return TCL_OK;
4912}
4913
drh93aed5a2008-01-16 17:46:38 +00004914/*
drhc8d75672008-07-08 02:12:37 +00004915** tclcmd: vfs_initfail_test
4916**
4917** This TCL command attempts to vfs_find and vfs_register when the
4918** sqlite3_initialize() interface is failing. All calls should fail.
4919*/
4920static int vfs_initfail_test(
4921 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4922 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4923 int objc, /* Number of arguments */
4924 Tcl_Obj *CONST objv[] /* Command arguments */
4925){
4926 sqlite3_vfs one;
4927 one.zName = "__one";
4928
4929 if( sqlite3_vfs_find(0) ) return TCL_ERROR;
4930 sqlite3_vfs_register(&one, 0);
4931 if( sqlite3_vfs_find(0) ) return TCL_ERROR;
4932 sqlite3_vfs_register(&one, 1);
4933 if( sqlite3_vfs_find(0) ) return TCL_ERROR;
4934 return TCL_OK;
4935}
4936
4937/*
drha2820972008-07-07 13:31:58 +00004938** Saved VFSes
4939*/
4940static sqlite3_vfs *apVfs[20];
4941static int nVfs = 0;
4942
4943/*
4944** tclcmd: vfs_unregister_all
4945**
4946** Unregister all VFSes.
4947*/
4948static int vfs_unregister_all(
4949 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4950 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4951 int objc, /* Number of arguments */
4952 Tcl_Obj *CONST objv[] /* Command arguments */
4953){
4954 int i;
4955 for(i=0; i<ArraySize(apVfs); i++){
4956 apVfs[i] = sqlite3_vfs_find(0);
4957 if( apVfs[i]==0 ) break;
4958 sqlite3_vfs_unregister(apVfs[i]);
4959 }
4960 nVfs = i;
4961 return TCL_OK;
4962}
4963/*
4964** tclcmd: vfs_reregister_all
4965**
4966** Restore all VFSes that were removed using vfs_unregister_all
4967*/
4968static int vfs_reregister_all(
4969 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4970 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4971 int objc, /* Number of arguments */
4972 Tcl_Obj *CONST objv[] /* Command arguments */
4973){
4974 int i;
4975 for(i=0; i<nVfs; i++){
4976 sqlite3_vfs_register(apVfs[i], i==0);
4977 }
4978 return TCL_OK;
4979}
4980
4981
4982/*
drh55176252008-01-22 14:50:16 +00004983** tclcmd: file_control_test DB
4984**
4985** This TCL command runs the sqlite3_file_control interface and
4986** verifies correct operation of the same.
4987*/
4988static int file_control_test(
4989 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4990 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4991 int objc, /* Number of arguments */
4992 Tcl_Obj *CONST objv[] /* Command arguments */
4993){
4994 int iArg = 0;
4995 sqlite3 *db;
4996 int rc;
4997
4998 if( objc!=2 ){
4999 Tcl_AppendResult(interp, "wrong # args: should be \"",
5000 Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
5001 return TCL_ERROR;
5002 }
5003 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
5004 rc = sqlite3_file_control(db, 0, 0, &iArg);
drh0b52b7d2011-01-26 19:46:22 +00005005 assert( rc==SQLITE_NOTFOUND );
drh55176252008-01-22 14:50:16 +00005006 rc = sqlite3_file_control(db, "notadatabase", SQLITE_FCNTL_LOCKSTATE, &iArg);
5007 assert( rc==SQLITE_ERROR );
5008 rc = sqlite3_file_control(db, "main", -1, &iArg);
drh0b52b7d2011-01-26 19:46:22 +00005009 assert( rc==SQLITE_NOTFOUND );
drh55176252008-01-22 14:50:16 +00005010 rc = sqlite3_file_control(db, "temp", -1, &iArg);
drh0b52b7d2011-01-26 19:46:22 +00005011 assert( rc==SQLITE_NOTFOUND || rc==SQLITE_ERROR );
aswiftaebf4132008-11-21 00:10:35 +00005012
5013 return TCL_OK;
5014}
5015
5016
5017/*
5018** tclcmd: file_control_lasterrno_test DB
5019**
5020** This TCL command runs the sqlite3_file_control interface and
5021** verifies correct operation of the SQLITE_LAST_ERRNO verb.
5022*/
5023static int file_control_lasterrno_test(
5024 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5025 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5026 int objc, /* Number of arguments */
5027 Tcl_Obj *CONST objv[] /* Command arguments */
5028){
5029 int iArg = 0;
5030 sqlite3 *db;
5031 int rc;
5032
5033 if( objc!=2 ){
5034 Tcl_AppendResult(interp, "wrong # args: should be \"",
5035 Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
5036 return TCL_ERROR;
5037 }
shane9db299f2009-01-30 05:59:10 +00005038 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5039 return TCL_ERROR;
5040 }
aswiftaebf4132008-11-21 00:10:35 +00005041 rc = sqlite3_file_control(db, NULL, SQLITE_LAST_ERRNO, &iArg);
shane9db299f2009-01-30 05:59:10 +00005042 if( rc ){
5043 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5044 return TCL_ERROR;
5045 }
aswiftaebf4132008-11-21 00:10:35 +00005046 if( iArg!=0 ) {
5047 Tcl_AppendResult(interp, "Unexpected non-zero errno: ",
5048 Tcl_GetStringFromObj(Tcl_NewIntObj(iArg), 0), " ", 0);
5049 return TCL_ERROR;
5050 }
drh55176252008-01-22 14:50:16 +00005051 return TCL_OK;
5052}
5053
5054/*
dan6e09d692010-07-27 18:34:15 +00005055** tclcmd: file_control_chunksize_test DB DBNAME SIZE
5056**
5057** This TCL command runs the sqlite3_file_control interface and
5058** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
5059** SQLITE_SET_LOCKPROXYFILE verbs.
5060*/
5061static int file_control_chunksize_test(
5062 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5063 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5064 int objc, /* Number of arguments */
5065 Tcl_Obj *CONST objv[] /* Command arguments */
5066){
5067 int nSize; /* New chunk size */
5068 char *zDb; /* Db name ("main", "temp" etc.) */
5069 sqlite3 *db; /* Database handle */
5070 int rc; /* file_control() return code */
5071
5072 if( objc!=4 ){
5073 Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
5074 return TCL_ERROR;
5075 }
5076 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
5077 || Tcl_GetIntFromObj(interp, objv[3], &nSize)
5078 ){
5079 return TCL_ERROR;
5080 }
5081 zDb = Tcl_GetString(objv[2]);
5082 if( zDb[0]=='\0' ) zDb = NULL;
5083
5084 rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_CHUNK_SIZE, (void *)&nSize);
5085 if( rc ){
mistachkine84d8d32013-04-29 03:09:10 +00005086 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
dan6e09d692010-07-27 18:34:15 +00005087 return TCL_ERROR;
5088 }
5089 return TCL_OK;
5090}
5091
5092/*
dan661d71a2011-03-30 19:08:03 +00005093** tclcmd: file_control_sizehint_test DB DBNAME SIZE
5094**
drhfdd7f712011-08-13 10:47:51 +00005095** This TCL command runs the sqlite3_file_control interface
5096** with SQLITE_FCNTL_SIZE_HINT
dan661d71a2011-03-30 19:08:03 +00005097*/
5098static int file_control_sizehint_test(
5099 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5100 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5101 int objc, /* Number of arguments */
5102 Tcl_Obj *CONST objv[] /* Command arguments */
5103){
drhb3f787f2012-09-29 14:45:54 +00005104 Tcl_WideInt nSize; /* Hinted size */
dan661d71a2011-03-30 19:08:03 +00005105 char *zDb; /* Db name ("main", "temp" etc.) */
5106 sqlite3 *db; /* Database handle */
5107 int rc; /* file_control() return code */
5108
5109 if( objc!=4 ){
5110 Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
5111 return TCL_ERROR;
5112 }
5113 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
5114 || Tcl_GetWideIntFromObj(interp, objv[3], &nSize)
5115 ){
5116 return TCL_ERROR;
5117 }
5118 zDb = Tcl_GetString(objv[2]);
5119 if( zDb[0]=='\0' ) zDb = NULL;
5120
5121 rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_SIZE_HINT, (void *)&nSize);
5122 if( rc ){
mistachkine84d8d32013-04-29 03:09:10 +00005123 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
dan661d71a2011-03-30 19:08:03 +00005124 return TCL_ERROR;
5125 }
5126 return TCL_OK;
5127}
5128
5129/*
drhad245812010-06-01 00:28:42 +00005130** tclcmd: file_control_lockproxy_test DB PWD
aswiftaebf4132008-11-21 00:10:35 +00005131**
5132** This TCL command runs the sqlite3_file_control interface and
5133** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
5134** SQLITE_SET_LOCKPROXYFILE verbs.
5135*/
5136static int file_control_lockproxy_test(
5137 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5138 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5139 int objc, /* Number of arguments */
5140 Tcl_Obj *CONST objv[] /* Command arguments */
5141){
aswiftaebf4132008-11-21 00:10:35 +00005142 sqlite3 *db;
aswiftaebf4132008-11-21 00:10:35 +00005143
drhad245812010-06-01 00:28:42 +00005144 if( objc!=3 ){
aswiftaebf4132008-11-21 00:10:35 +00005145 Tcl_AppendResult(interp, "wrong # args: should be \"",
drhad245812010-06-01 00:28:42 +00005146 Tcl_GetStringFromObj(objv[0], 0), " DB PWD", 0);
aswiftaebf4132008-11-21 00:10:35 +00005147 return TCL_ERROR;
5148 }
shane9db299f2009-01-30 05:59:10 +00005149 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5150 return TCL_ERROR;
5151 }
aswiftaebf4132008-11-21 00:10:35 +00005152
drh9b35ea62008-11-29 02:20:26 +00005153#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
drhd2cb50b2009-01-09 21:41:17 +00005154# if defined(__APPLE__)
drh9b35ea62008-11-29 02:20:26 +00005155# define SQLITE_ENABLE_LOCKING_STYLE 1
5156# else
5157# define SQLITE_ENABLE_LOCKING_STYLE 0
5158# endif
5159#endif
drhd2cb50b2009-01-09 21:41:17 +00005160#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
drh7708e972008-11-29 00:56:52 +00005161 {
aswiftaebf4132008-11-21 00:10:35 +00005162 char *testPath;
drh103fe742008-12-11 02:56:07 +00005163 int rc;
drhcaffb1a2012-01-30 18:00:31 +00005164 int nPwd;
5165 const char *zPwd;
drhad245812010-06-01 00:28:42 +00005166 char proxyPath[400];
5167
drhcaffb1a2012-01-30 18:00:31 +00005168 zPwd = Tcl_GetStringFromObj(objv[2], &nPwd);
drhad245812010-06-01 00:28:42 +00005169 if( sizeof(proxyPath)<nPwd+20 ){
5170 Tcl_AppendResult(interp, "PWD too big", (void*)0);
5171 return TCL_ERROR;
5172 }
5173 sprintf(proxyPath, "%s/test.proxy", zPwd);
drh7708e972008-11-29 00:56:52 +00005174 rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
5175 if( rc ){
shane9db299f2009-01-30 05:59:10 +00005176 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5177 return TCL_ERROR;
drh7708e972008-11-29 00:56:52 +00005178 }
aswiftaebf4132008-11-21 00:10:35 +00005179 rc = sqlite3_file_control(db, NULL, SQLITE_GET_LOCKPROXYFILE, &testPath);
shane9db299f2009-01-30 05:59:10 +00005180 if( strncmp(proxyPath,testPath,11) ){
drh7708e972008-11-29 00:56:52 +00005181 Tcl_AppendResult(interp, "Lock proxy file did not match the "
5182 "previously assigned value", 0);
aswiftaebf4132008-11-21 00:10:35 +00005183 return TCL_ERROR;
5184 }
drh7708e972008-11-29 00:56:52 +00005185 if( rc ){
5186 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5187 return TCL_ERROR;
5188 }
5189 rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
5190 if( rc ){
5191 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5192 return TCL_ERROR;
5193 }
aswiftaebf4132008-11-21 00:10:35 +00005194 }
5195#endif
5196 return TCL_OK;
5197}
5198
mistachkin6b98d672014-05-30 16:42:35 +00005199#if SQLITE_OS_WIN
drhd0cdf012011-07-13 16:03:46 +00005200/*
5201** tclcmd: file_control_win32_av_retry DB NRETRY DELAY
5202**
5203** This TCL command runs the sqlite3_file_control interface with
5204** the SQLITE_FCNTL_WIN32_AV_RETRY opcode.
5205*/
5206static int file_control_win32_av_retry(
5207 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5208 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5209 int objc, /* Number of arguments */
5210 Tcl_Obj *CONST objv[] /* Command arguments */
5211){
5212 sqlite3 *db;
5213 int rc;
5214 int a[2];
5215 char z[100];
5216
5217 if( objc!=4 ){
5218 Tcl_AppendResult(interp, "wrong # args: should be \"",
5219 Tcl_GetStringFromObj(objv[0], 0), " DB NRETRY DELAY", 0);
5220 return TCL_ERROR;
5221 }
5222 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5223 return TCL_ERROR;
5224 }
5225 if( Tcl_GetIntFromObj(interp, objv[2], &a[0]) ) return TCL_ERROR;
5226 if( Tcl_GetIntFromObj(interp, objv[3], &a[1]) ) return TCL_ERROR;
5227 rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a);
5228 sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]);
5229 Tcl_AppendResult(interp, z, (char*)0);
5230 return TCL_OK;
5231}
5232
drh253cea52011-07-26 16:23:25 +00005233/*
mistachkin6b98d672014-05-30 16:42:35 +00005234** tclcmd: file_control_win32_set_handle DB HANDLE
5235**
5236** This TCL command runs the sqlite3_file_control interface with
5237** the SQLITE_FCNTL_WIN32_SET_HANDLE opcode.
5238*/
5239static int file_control_win32_set_handle(
5240 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5241 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5242 int objc, /* Number of arguments */
5243 Tcl_Obj *CONST objv[] /* Command arguments */
5244){
5245 sqlite3 *db;
5246 int rc;
5247 HANDLE hFile = NULL;
5248 char z[100];
5249
5250 if( objc!=3 ){
5251 Tcl_AppendResult(interp, "wrong # args: should be \"",
5252 Tcl_GetStringFromObj(objv[0], 0), " DB HANDLE", 0);
5253 return TCL_ERROR;
5254 }
5255 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5256 return TCL_ERROR;
5257 }
5258 if( getWin32Handle(interp, Tcl_GetString(objv[2]), &hFile) ){
5259 return TCL_ERROR;
5260 }
5261 rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_SET_HANDLE,
5262 (void*)&hFile);
5263 sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
5264 Tcl_AppendResult(interp, z, (char*)0);
5265 return TCL_OK;
5266}
5267#endif
5268
5269/*
drh253cea52011-07-26 16:23:25 +00005270** tclcmd: file_control_persist_wal DB PERSIST-FLAG
5271**
5272** This TCL command runs the sqlite3_file_control interface with
5273** the SQLITE_FCNTL_PERSIST_WAL opcode.
5274*/
5275static int file_control_persist_wal(
5276 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5277 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5278 int objc, /* Number of arguments */
5279 Tcl_Obj *CONST objv[] /* Command arguments */
5280){
5281 sqlite3 *db;
5282 int rc;
5283 int bPersist;
5284 char z[100];
5285
5286 if( objc!=3 ){
5287 Tcl_AppendResult(interp, "wrong # args: should be \"",
5288 Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
5289 return TCL_ERROR;
5290 }
5291 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5292 return TCL_ERROR;
5293 }
5294 if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR;
5295 rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist);
5296 sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist);
5297 Tcl_AppendResult(interp, z, (char*)0);
5298 return TCL_OK;
5299}
5300
drhf12b3f62011-12-21 14:42:29 +00005301/*
drhcb15f352011-12-23 01:04:17 +00005302** tclcmd: file_control_powersafe_overwrite DB PSOW-FLAG
drhf12b3f62011-12-21 14:42:29 +00005303**
5304** This TCL command runs the sqlite3_file_control interface with
drhcb15f352011-12-23 01:04:17 +00005305** the SQLITE_FCNTL_POWERSAFE_OVERWRITE opcode.
drhf12b3f62011-12-21 14:42:29 +00005306*/
drhcb15f352011-12-23 01:04:17 +00005307static int file_control_powersafe_overwrite(
drhf12b3f62011-12-21 14:42:29 +00005308 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5309 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5310 int objc, /* Number of arguments */
5311 Tcl_Obj *CONST objv[] /* Command arguments */
5312){
5313 sqlite3 *db;
5314 int rc;
drhcb15f352011-12-23 01:04:17 +00005315 int b;
drhf12b3f62011-12-21 14:42:29 +00005316 char z[100];
5317
5318 if( objc!=3 ){
5319 Tcl_AppendResult(interp, "wrong # args: should be \"",
5320 Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
5321 return TCL_ERROR;
5322 }
5323 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5324 return TCL_ERROR;
5325 }
drhcb15f352011-12-23 01:04:17 +00005326 if( Tcl_GetIntFromObj(interp, objv[2], &b) ) return TCL_ERROR;
5327 rc = sqlite3_file_control(db,NULL,SQLITE_FCNTL_POWERSAFE_OVERWRITE,(void*)&b);
5328 sqlite3_snprintf(sizeof(z), z, "%d %d", rc, b);
drhf12b3f62011-12-21 14:42:29 +00005329 Tcl_AppendResult(interp, z, (char*)0);
5330 return TCL_OK;
5331}
5332
aswiftaebf4132008-11-21 00:10:35 +00005333
5334/*
drhde60fc22011-12-14 17:53:36 +00005335** tclcmd: file_control_vfsname DB ?AUXDB?
5336**
5337** Return a string that describes the stack of VFSes.
5338*/
5339static int file_control_vfsname(
5340 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5341 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5342 int objc, /* Number of arguments */
5343 Tcl_Obj *CONST objv[] /* Command arguments */
5344){
5345 sqlite3 *db;
5346 const char *zDbName = "main";
5347 char *zVfsName = 0;
5348
5349 if( objc!=2 && objc!=3 ){
5350 Tcl_AppendResult(interp, "wrong # args: should be \"",
5351 Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
5352 return TCL_ERROR;
5353 }
5354 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5355 return TCL_ERROR;
5356 }
5357 if( objc==3 ){
5358 zDbName = Tcl_GetString(objv[2]);
5359 }
5360 sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName);
5361 Tcl_AppendResult(interp, zVfsName, (char*)0);
5362 sqlite3_free(zVfsName);
5363 return TCL_OK;
5364}
5365
drh696b33e2012-12-06 19:01:42 +00005366/*
5367** tclcmd: file_control_tempfilename DB ?AUXDB?
5368**
5369** Return a string that is a temporary filename
5370*/
5371static int file_control_tempfilename(
5372 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5373 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5374 int objc, /* Number of arguments */
5375 Tcl_Obj *CONST objv[] /* Command arguments */
5376){
5377 sqlite3 *db;
5378 const char *zDbName = "main";
5379 char *zTName = 0;
5380
5381 if( objc!=2 && objc!=3 ){
5382 Tcl_AppendResult(interp, "wrong # args: should be \"",
5383 Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
5384 return TCL_ERROR;
5385 }
5386 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5387 return TCL_ERROR;
5388 }
5389 if( objc==3 ){
5390 zDbName = Tcl_GetString(objv[2]);
5391 }
5392 sqlite3_file_control(db, zDbName, SQLITE_FCNTL_TEMPFILENAME, (void*)&zTName);
5393 Tcl_AppendResult(interp, zTName, (char*)0);
5394 sqlite3_free(zTName);
5395 return TCL_OK;
5396}
5397
drhde60fc22011-12-14 17:53:36 +00005398
5399/*
danielk1977e339d652008-06-28 11:23:00 +00005400** tclcmd: sqlite3_vfs_list
5401**
5402** Return a tcl list containing the names of all registered vfs's.
5403*/
5404static int vfs_list(
5405 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5406 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5407 int objc, /* Number of arguments */
5408 Tcl_Obj *CONST objv[] /* Command arguments */
5409){
5410 sqlite3_vfs *pVfs;
5411 Tcl_Obj *pRet = Tcl_NewObj();
5412 if( objc!=1 ){
5413 Tcl_WrongNumArgs(interp, 1, objv, "");
5414 return TCL_ERROR;
5415 }
5416 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
5417 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(pVfs->zName, -1));
5418 }
5419 Tcl_SetObjResult(interp, pRet);
5420 return TCL_OK;
5421}
5422
5423/*
drhb1a6c3c2008-03-20 16:30:17 +00005424** tclcmd: sqlite3_limit DB ID VALUE
5425**
5426** This TCL command runs the sqlite3_limit interface and
5427** verifies correct operation of the same.
5428*/
5429static int test_limit(
5430 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5431 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5432 int objc, /* Number of arguments */
5433 Tcl_Obj *CONST objv[] /* Command arguments */
5434){
5435 sqlite3 *db;
5436 int rc;
5437 static const struct {
5438 char *zName;
5439 int id;
5440 } aId[] = {
5441 { "SQLITE_LIMIT_LENGTH", SQLITE_LIMIT_LENGTH },
5442 { "SQLITE_LIMIT_SQL_LENGTH", SQLITE_LIMIT_SQL_LENGTH },
5443 { "SQLITE_LIMIT_COLUMN", SQLITE_LIMIT_COLUMN },
5444 { "SQLITE_LIMIT_EXPR_DEPTH", SQLITE_LIMIT_EXPR_DEPTH },
5445 { "SQLITE_LIMIT_COMPOUND_SELECT", SQLITE_LIMIT_COMPOUND_SELECT },
5446 { "SQLITE_LIMIT_VDBE_OP", SQLITE_LIMIT_VDBE_OP },
5447 { "SQLITE_LIMIT_FUNCTION_ARG", SQLITE_LIMIT_FUNCTION_ARG },
5448 { "SQLITE_LIMIT_ATTACHED", SQLITE_LIMIT_ATTACHED },
5449 { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
5450 { "SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER },
drh417168a2009-09-07 18:14:02 +00005451 { "SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH },
drh3705ef62014-10-08 15:53:21 +00005452 { "SQLITE_LIMIT_WORKER_THREADS", SQLITE_LIMIT_WORKER_THREADS },
drh521cc842008-04-15 02:36:33 +00005453
5454 /* Out of range test cases */
5455 { "SQLITE_LIMIT_TOOSMALL", -1, },
drh3705ef62014-10-08 15:53:21 +00005456 { "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_WORKER_THREADS+1 },
drhb1a6c3c2008-03-20 16:30:17 +00005457 };
5458 int i, id;
5459 int val;
5460 const char *zId;
5461
5462 if( objc!=4 ){
5463 Tcl_AppendResult(interp, "wrong # args: should be \"",
5464 Tcl_GetStringFromObj(objv[0], 0), " DB ID VALUE", 0);
5465 return TCL_ERROR;
5466 }
5467 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
5468 zId = Tcl_GetString(objv[2]);
5469 for(i=0; i<sizeof(aId)/sizeof(aId[0]); i++){
5470 if( strcmp(zId, aId[i].zName)==0 ){
5471 id = aId[i].id;
5472 break;
5473 }
5474 }
5475 if( i>=sizeof(aId)/sizeof(aId[0]) ){
5476 Tcl_AppendResult(interp, "unknown limit type: ", zId, (char*)0);
5477 return TCL_ERROR;
5478 }
5479 if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
5480 rc = sqlite3_limit(db, id, val);
5481 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5482 return TCL_OK;
5483}
5484
5485/*
drh93aed5a2008-01-16 17:46:38 +00005486** tclcmd: save_prng_state
drha2820972008-07-07 13:31:58 +00005487**
5488** Save the state of the pseudo-random number generator.
5489** At the same time, verify that sqlite3_test_control works even when
5490** called with an out-of-range opcode.
drh93aed5a2008-01-16 17:46:38 +00005491*/
5492static int save_prng_state(
5493 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5494 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5495 int objc, /* Number of arguments */
5496 Tcl_Obj *CONST objv[] /* Command arguments */
5497){
drha2820972008-07-07 13:31:58 +00005498 int rc = sqlite3_test_control(9999);
5499 assert( rc==0 );
5500 rc = sqlite3_test_control(-1);
5501 assert( rc==0 );
drh2fa18682008-03-19 14:15:34 +00005502 sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SAVE);
drh93aed5a2008-01-16 17:46:38 +00005503 return TCL_OK;
5504}
5505/*
5506** tclcmd: restore_prng_state
5507*/
5508static int restore_prng_state(
5509 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5510 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5511 int objc, /* Number of arguments */
5512 Tcl_Obj *CONST objv[] /* Command arguments */
5513){
drh2fa18682008-03-19 14:15:34 +00005514 sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESTORE);
drh93aed5a2008-01-16 17:46:38 +00005515 return TCL_OK;
5516}
5517/*
5518** tclcmd: reset_prng_state
5519*/
5520static int reset_prng_state(
5521 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5522 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5523 int objc, /* Number of arguments */
5524 Tcl_Obj *CONST objv[] /* Command arguments */
5525){
drh2fa18682008-03-19 14:15:34 +00005526 sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESET);
drh93aed5a2008-01-16 17:46:38 +00005527 return TCL_OK;
5528}
5529
danielk1977062d4cb2008-08-29 09:10:02 +00005530/*
drh09fe6142013-11-29 15:06:27 +00005531** tclcmd: database_may_be_corrupt
5532**
5533** Indicate that database files might be corrupt. In other words, set the normal
5534** state of operation.
5535*/
5536static int database_may_be_corrupt(
5537 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5538 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5539 int objc, /* Number of arguments */
5540 Tcl_Obj *CONST objv[] /* Command arguments */
5541){
5542 sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 0);
5543 return TCL_OK;
5544}
5545/*
5546** tclcmd: database_never_corrupt
5547**
5548** Indicate that database files are always well-formed. This enables extra assert()
5549** statements that test conditions that are always true for well-formed databases.
5550*/
5551static int database_never_corrupt(
5552 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5553 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5554 int objc, /* Number of arguments */
5555 Tcl_Obj *CONST objv[] /* Command arguments */
5556){
5557 sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 1);
5558 return TCL_OK;
5559}
5560
5561/*
danielk1977062d4cb2008-08-29 09:10:02 +00005562** tclcmd: pcache_stats
5563*/
5564static int test_pcache_stats(
5565 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5566 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5567 int objc, /* Number of arguments */
5568 Tcl_Obj *CONST objv[] /* Command arguments */
5569){
5570 int nMin;
5571 int nMax;
5572 int nCurrent;
5573 int nRecyclable;
5574 Tcl_Obj *pRet;
5575
5576 sqlite3PcacheStats(&nCurrent, &nMax, &nMin, &nRecyclable);
5577
5578 pRet = Tcl_NewObj();
5579 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("current", -1));
5580 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCurrent));
5581 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("max", -1));
5582 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMax));
5583 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("min", -1));
5584 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMin));
5585 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("recyclable", -1));
5586 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nRecyclable));
5587
5588 Tcl_SetObjResult(interp, pRet);
5589
5590 return TCL_OK;
5591}
5592
drh69910da2009-03-27 12:32:54 +00005593#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
danielk1977404ca072009-03-16 13:19:36 +00005594static void test_unlock_notify_cb(void **aArg, int nArg){
5595 int ii;
5596 for(ii=0; ii<nArg; ii++){
5597 Tcl_EvalEx((Tcl_Interp *)aArg[ii], "unlock_notify", -1, TCL_EVAL_GLOBAL);
5598 }
5599}
drh69910da2009-03-27 12:32:54 +00005600#endif /* SQLITE_ENABLE_UNLOCK_NOTIFY */
danielk1977404ca072009-03-16 13:19:36 +00005601
5602/*
5603** tclcmd: sqlite3_unlock_notify db
5604*/
5605#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
5606static int test_unlock_notify(
5607 ClientData clientData, /* Unused */
5608 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5609 int objc, /* Number of arguments */
5610 Tcl_Obj *CONST objv[] /* Command arguments */
5611){
5612 sqlite3 *db;
5613 int rc;
5614
5615 if( objc!=2 ){
5616 Tcl_WrongNumArgs(interp, 1, objv, "DB");
5617 return TCL_ERROR;
5618 }
5619
5620 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5621 return TCL_ERROR;
5622 }
5623 rc = sqlite3_unlock_notify(db, test_unlock_notify_cb, (void *)interp);
5624 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
5625 return TCL_OK;
5626}
5627#endif
5628
dan87c1fe12010-05-03 12:14:15 +00005629/*
5630** tclcmd: sqlite3_wal_checkpoint db ?NAME?
5631*/
5632static int test_wal_checkpoint(
5633 ClientData clientData, /* Unused */
5634 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5635 int objc, /* Number of arguments */
5636 Tcl_Obj *CONST objv[] /* Command arguments */
5637){
5638 char *zDb = 0;
5639 sqlite3 *db;
5640 int rc;
5641
5642 if( objc!=3 && objc!=2 ){
5643 Tcl_WrongNumArgs(interp, 1, objv, "DB ?NAME?");
5644 return TCL_ERROR;
5645 }
5646
5647 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5648 return TCL_ERROR;
5649 }
5650 if( objc==3 ){
5651 zDb = Tcl_GetString(objv[2]);
5652 }
5653 rc = sqlite3_wal_checkpoint(db, zDb);
5654 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
5655 return TCL_OK;
5656}
5657
daneb8763d2010-08-17 14:52:22 +00005658/*
dan9c5e3682011-02-07 15:12:12 +00005659** tclcmd: sqlite3_wal_checkpoint_v2 db MODE ?NAME?
5660**
5661** This command calls the wal_checkpoint_v2() function with the specified
5662** mode argument (passive, full or restart). If present, the database name
5663** NAME is passed as the second argument to wal_checkpoint_v2(). If it the
5664** NAME argument is not present, a NULL pointer is passed instead.
5665**
5666** If wal_checkpoint_v2() returns any value other than SQLITE_BUSY or
5667** SQLITE_OK, then this command returns TCL_ERROR. The Tcl result is set
5668** to the error message obtained from sqlite3_errmsg().
5669**
5670** Otherwise, this command returns a list of three integers. The first integer
5671** is 1 if SQLITE_BUSY was returned, or 0 otherwise. The following two integers
drhf7b54962013-05-28 12:11:54 +00005672** are the values returned via the output parameters by wal_checkpoint_v2() -
dan9c5e3682011-02-07 15:12:12 +00005673** the number of frames in the log and the number of frames in the log
5674** that have been checkpointed.
5675*/
5676static int test_wal_checkpoint_v2(
5677 ClientData clientData, /* Unused */
5678 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5679 int objc, /* Number of arguments */
5680 Tcl_Obj *CONST objv[] /* Command arguments */
5681){
5682 char *zDb = 0;
5683 sqlite3 *db;
5684 int rc;
5685
5686 int eMode;
5687 int nLog = -555;
5688 int nCkpt = -555;
5689 Tcl_Obj *pRet;
5690
danf26a1542014-12-02 19:04:54 +00005691 const char * aMode[] = { "passive", "full", "restart", "truncate", 0 };
dan9c5e3682011-02-07 15:12:12 +00005692 assert( SQLITE_CHECKPOINT_PASSIVE==0 );
5693 assert( SQLITE_CHECKPOINT_FULL==1 );
5694 assert( SQLITE_CHECKPOINT_RESTART==2 );
danf26a1542014-12-02 19:04:54 +00005695 assert( SQLITE_CHECKPOINT_TRUNCATE==3 );
dan9c5e3682011-02-07 15:12:12 +00005696
5697 if( objc!=3 && objc!=4 ){
5698 Tcl_WrongNumArgs(interp, 1, objv, "DB MODE ?NAME?");
5699 return TCL_ERROR;
5700 }
5701
5702 if( objc==4 ){
5703 zDb = Tcl_GetString(objv[3]);
5704 }
dan2928d322014-12-05 20:46:19 +00005705 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) || (
5706 TCL_OK!=Tcl_GetIntFromObj(0, objv[2], &eMode)
5707 && TCL_OK!=Tcl_GetIndexFromObj(interp, objv[2], aMode, "mode", 0, &eMode)
5708 )){
dan9c5e3682011-02-07 15:12:12 +00005709 return TCL_ERROR;
5710 }
5711
5712 rc = sqlite3_wal_checkpoint_v2(db, zDb, eMode, &nLog, &nCkpt);
5713 if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
dan2928d322014-12-05 20:46:19 +00005714 const char *zErrCode = sqlite3ErrName(rc);
dan9778bd72014-12-09 20:13:40 +00005715 Tcl_ResetResult(interp);
dan2928d322014-12-05 20:46:19 +00005716 Tcl_AppendResult(interp, zErrCode, " - ", (char *)sqlite3_errmsg(db), 0);
dan9c5e3682011-02-07 15:12:12 +00005717 return TCL_ERROR;
5718 }
5719
5720 pRet = Tcl_NewObj();
5721 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(rc==SQLITE_BUSY?1:0));
5722 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nLog));
5723 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCkpt));
5724 Tcl_SetObjResult(interp, pRet);
5725
5726 return TCL_OK;
5727}
5728
5729/*
dan9af10622014-12-15 16:27:12 +00005730** tclcmd: sqlite3_wal_autocheckpoint db VALUE
5731*/
5732static int test_wal_autocheckpoint(
5733 ClientData clientData, /* Unused */
5734 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5735 int objc, /* Number of arguments */
5736 Tcl_Obj *CONST objv[] /* Command arguments */
5737){
5738 sqlite3 *db;
5739 int rc;
5740 int iVal;
5741
5742
5743 if( objc!=3 ){
5744 Tcl_WrongNumArgs(interp, 1, objv, "DB VALUE");
5745 return TCL_ERROR;
5746 }
5747
5748 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
5749 || Tcl_GetIntFromObj(0, objv[2], &iVal)
5750 ){
5751 return TCL_ERROR;
5752 }
5753
5754 rc = sqlite3_wal_autocheckpoint(db, iVal);
5755 Tcl_ResetResult(interp);
5756 if( rc!=SQLITE_OK ){
5757 const char *zErrCode = sqlite3ErrName(rc);
5758 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErrCode, -1));
5759 return TCL_ERROR;
5760 }
5761
5762 return TCL_OK;
5763}
5764
5765
5766/*
daneb8763d2010-08-17 14:52:22 +00005767** tclcmd: test_sqlite3_log ?SCRIPT?
5768*/
5769static struct LogCallback {
5770 Tcl_Interp *pInterp;
5771 Tcl_Obj *pObj;
5772} logcallback = {0, 0};
5773static void xLogcallback(void *unused, int err, char *zMsg){
5774 Tcl_Obj *pNew = Tcl_DuplicateObj(logcallback.pObj);
5775 Tcl_IncrRefCount(pNew);
5776 Tcl_ListObjAppendElement(
mistachkine84d8d32013-04-29 03:09:10 +00005777 0, pNew, Tcl_NewStringObj(sqlite3ErrName(err), -1)
daneb8763d2010-08-17 14:52:22 +00005778 );
5779 Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zMsg, -1));
5780 Tcl_EvalObjEx(logcallback.pInterp, pNew, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
5781 Tcl_DecrRefCount(pNew);
5782}
5783static int test_sqlite3_log(
5784 ClientData clientData,
5785 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5786 int objc, /* Number of arguments */
5787 Tcl_Obj *CONST objv[] /* Command arguments */
5788){
5789 if( objc>2 ){
5790 Tcl_WrongNumArgs(interp, 1, objv, "SCRIPT");
5791 return TCL_ERROR;
5792 }
5793 if( logcallback.pObj ){
5794 Tcl_DecrRefCount(logcallback.pObj);
5795 logcallback.pObj = 0;
5796 logcallback.pInterp = 0;
5797 sqlite3_config(SQLITE_CONFIG_LOG, 0, 0);
5798 }
5799 if( objc>1 ){
5800 logcallback.pObj = objv[1];
5801 Tcl_IncrRefCount(logcallback.pObj);
5802 logcallback.pInterp = interp;
5803 sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, 0);
5804 }
5805 return TCL_OK;
5806}
drh9bc54492007-10-23 14:49:59 +00005807
5808/*
drha2c8a952009-10-13 18:38:34 +00005809** tcl_objproc COMMANDNAME ARGS...
5810**
5811** Run a TCL command using its objProc interface. Throw an error if
5812** the command has no objProc interface.
5813*/
5814static int runAsObjProc(
5815 void * clientData,
5816 Tcl_Interp *interp,
5817 int objc,
5818 Tcl_Obj *CONST objv[]
5819){
5820 Tcl_CmdInfo cmdInfo;
5821 if( objc<2 ){
5822 Tcl_WrongNumArgs(interp, 1, objv, "COMMAND ...");
5823 return TCL_ERROR;
5824 }
5825 if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
5826 Tcl_AppendResult(interp, "command not found: ",
5827 Tcl_GetString(objv[1]), (char*)0);
5828 return TCL_ERROR;
5829 }
5830 if( cmdInfo.objProc==0 ){
5831 Tcl_AppendResult(interp, "command has no objProc: ",
5832 Tcl_GetString(objv[1]), (char*)0);
5833 return TCL_ERROR;
5834 }
5835 return cmdInfo.objProc(cmdInfo.objClientData, interp, objc-1, objv+1);
5836}
5837
dan91da6b82010-11-15 14:51:33 +00005838#ifndef SQLITE_OMIT_EXPLAIN
5839/*
5840** WARNING: The following function, printExplainQueryPlan() is an exact
5841** copy of example code from eqp.in (eqp.html). If this code is modified,
5842** then the documentation copy needs to be modified as well.
5843*/
5844/*
5845** Argument pStmt is a prepared SQL statement. This function compiles
5846** an EXPLAIN QUERY PLAN command to report on the prepared statement,
5847** and prints the report to stdout using printf().
5848*/
5849int printExplainQueryPlan(sqlite3_stmt *pStmt){
5850 const char *zSql; /* Input SQL */
5851 char *zExplain; /* SQL with EXPLAIN QUERY PLAN prepended */
5852 sqlite3_stmt *pExplain; /* Compiled EXPLAIN QUERY PLAN command */
5853 int rc; /* Return code from sqlite3_prepare_v2() */
5854
5855 zSql = sqlite3_sql(pStmt);
5856 if( zSql==0 ) return SQLITE_ERROR;
5857
5858 zExplain = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zSql);
5859 if( zExplain==0 ) return SQLITE_NOMEM;
5860
5861 rc = sqlite3_prepare_v2(sqlite3_db_handle(pStmt), zExplain, -1, &pExplain, 0);
5862 sqlite3_free(zExplain);
5863 if( rc!=SQLITE_OK ) return rc;
5864
5865 while( SQLITE_ROW==sqlite3_step(pExplain) ){
5866 int iSelectid = sqlite3_column_int(pExplain, 0);
5867 int iOrder = sqlite3_column_int(pExplain, 1);
5868 int iFrom = sqlite3_column_int(pExplain, 2);
5869 const char *zDetail = (const char *)sqlite3_column_text(pExplain, 3);
5870
5871 printf("%d %d %d %s\n", iSelectid, iOrder, iFrom, zDetail);
5872 }
5873
5874 return sqlite3_finalize(pExplain);
5875}
5876
5877static int test_print_eqp(
5878 void * clientData,
5879 Tcl_Interp *interp,
5880 int objc,
5881 Tcl_Obj *CONST objv[]
5882){
5883 int rc;
5884 sqlite3_stmt *pStmt;
5885
5886 if( objc!=2 ){
5887 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
5888 return TCL_ERROR;
5889 }
5890 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
5891 rc = printExplainQueryPlan(pStmt);
shaneh7c5d8fb2011-06-22 14:21:31 +00005892 /* This is needed on Windows so that a test case using this
5893 ** function can open a read pipe and get the output of
5894 ** printExplainQueryPlan() immediately.
5895 */
5896 fflush(stdout);
dan91da6b82010-11-15 14:51:33 +00005897 Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
5898 return TCL_OK;
5899}
5900#endif /* SQLITE_OMIT_EXPLAIN */
drha2c8a952009-10-13 18:38:34 +00005901
5902/*
danc17d6962011-06-21 12:47:30 +00005903** sqlite3_test_control VERB ARGS...
5904*/
5905static int test_test_control(
5906 void * clientData,
5907 Tcl_Interp *interp,
5908 int objc,
5909 Tcl_Obj *CONST objv[]
5910){
5911 struct Verb {
5912 const char *zName;
5913 int i;
5914 } aVerb[] = {
5915 { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
dan8930c2a2014-04-03 16:25:29 +00005916 { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP },
danc17d6962011-06-21 12:47:30 +00005917 };
5918 int iVerb;
5919 int iFlag;
5920 int rc;
5921
5922 if( objc<2 ){
5923 Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS...");
5924 return TCL_ERROR;
5925 }
5926
5927 rc = Tcl_GetIndexFromObjStruct(
5928 interp, objv[1], aVerb, sizeof(aVerb[0]), "VERB", 0, &iVerb
5929 );
5930 if( rc!=TCL_OK ) return rc;
5931
5932 iFlag = aVerb[iVerb].i;
5933 switch( iFlag ){
5934 case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
5935 int val;
5936 if( objc!=3 ){
5937 Tcl_WrongNumArgs(interp, 2, objv, "ONOFF");
5938 return TCL_ERROR;
5939 }
5940 if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
5941 sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val);
5942 break;
5943 }
dan8930c2a2014-04-03 16:25:29 +00005944
5945 case SQLITE_TESTCTRL_SORTER_MMAP: {
5946 int val;
5947 sqlite3 *db;
5948 if( objc!=4 ){
5949 Tcl_WrongNumArgs(interp, 2, objv, "DB LIMIT");
5950 return TCL_ERROR;
5951 }
5952 if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
5953 if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
5954 sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, val);
5955 break;
5956 }
danc17d6962011-06-21 12:47:30 +00005957 }
5958
5959 Tcl_ResetResult(interp);
5960 return TCL_OK;
5961}
5962
mistachkindaf9a5a2013-03-23 09:56:39 +00005963#if SQLITE_OS_UNIX
dana72014f2013-03-16 20:19:21 +00005964#include <sys/time.h>
5965#include <sys/resource.h>
5966
5967static int test_getrusage(
5968 void * clientData,
5969 Tcl_Interp *interp,
5970 int objc,
5971 Tcl_Obj *CONST objv[]
5972){
5973 char buf[1024];
5974 struct rusage r;
5975 memset(&r, 0, sizeof(r));
5976 getrusage(RUSAGE_SELF, &r);
5977
5978 sprintf(buf, "ru_utime=%d.%06d ru_stime=%d.%06d ru_minflt=%d ru_majflt=%d",
dan5d8a1372013-03-19 19:28:06 +00005979 (int)r.ru_utime.tv_sec, (int)r.ru_utime.tv_usec,
5980 (int)r.ru_stime.tv_sec, (int)r.ru_stime.tv_usec,
5981 (int)r.ru_minflt, (int)r.ru_majflt
dana72014f2013-03-16 20:19:21 +00005982 );
5983 Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
5984 return TCL_OK;
5985}
mistachkindaf9a5a2013-03-23 09:56:39 +00005986#endif
dana72014f2013-03-16 20:19:21 +00005987
drh80084ca2011-07-11 23:45:44 +00005988#if SQLITE_OS_WIN
5989/*
5990** Information passed from the main thread into the windows file locker
5991** background thread.
5992*/
5993struct win32FileLocker {
mistachkin176f1b42011-08-02 23:34:00 +00005994 char *evName; /* Name of event to signal thread startup */
drh80084ca2011-07-11 23:45:44 +00005995 HANDLE h; /* Handle of the file to be locked */
5996 int delay1; /* Delay before locking */
5997 int delay2; /* Delay before unlocking */
5998 int ok; /* Finished ok */
5999 int err; /* True if an error occurs */
6000};
6001#endif
6002
6003
6004#if SQLITE_OS_WIN
drh7da5fcb2012-03-30 14:59:43 +00006005#include <process.h>
drh80084ca2011-07-11 23:45:44 +00006006/*
6007** The background thread that does file locking.
6008*/
6009static void win32_file_locker(void *pAppData){
6010 struct win32FileLocker *p = (struct win32FileLocker*)pAppData;
mistachkin176f1b42011-08-02 23:34:00 +00006011 if( p->evName ){
6012 HANDLE ev = OpenEvent(EVENT_MODIFY_STATE, FALSE, p->evName);
6013 if ( ev ){
6014 SetEvent(ev);
6015 CloseHandle(ev);
6016 }
6017 }
drh80084ca2011-07-11 23:45:44 +00006018 if( p->delay1 ) Sleep(p->delay1);
6019 if( LockFile(p->h, 0, 0, 100000000, 0) ){
6020 Sleep(p->delay2);
6021 UnlockFile(p->h, 0, 0, 100000000, 0);
6022 p->ok = 1;
6023 }else{
6024 p->err = 1;
6025 }
6026 CloseHandle(p->h);
6027 p->h = 0;
6028 p->delay1 = 0;
6029 p->delay2 = 0;
6030}
6031#endif
6032
6033#if SQLITE_OS_WIN
6034/*
6035** lock_win32_file FILENAME DELAY1 DELAY2
6036**
6037** Get an exclusive manditory lock on file for DELAY2 milliseconds.
6038** Wait DELAY1 milliseconds before acquiring the lock.
6039*/
6040static int win32_file_lock(
6041 void * clientData,
6042 Tcl_Interp *interp,
6043 int objc,
6044 Tcl_Obj *CONST objv[]
6045){
mistachkin176f1b42011-08-02 23:34:00 +00006046 static struct win32FileLocker x = { "win32_file_lock", 0, 0, 0, 0, 0 };
drh80084ca2011-07-11 23:45:44 +00006047 const char *zFilename;
mistachkin176f1b42011-08-02 23:34:00 +00006048 char zBuf[200];
drh80084ca2011-07-11 23:45:44 +00006049 int retry = 0;
mistachkin176f1b42011-08-02 23:34:00 +00006050 HANDLE ev;
6051 DWORD wResult;
drh80084ca2011-07-11 23:45:44 +00006052
6053 if( objc!=4 && objc!=1 ){
6054 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2");
6055 return TCL_ERROR;
6056 }
6057 if( objc==1 ){
drh80084ca2011-07-11 23:45:44 +00006058 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d",
6059 x.ok, x.err, x.delay1, x.delay2, x.h);
6060 Tcl_AppendResult(interp, zBuf, (char*)0);
6061 return TCL_OK;
6062 }
drhd0cdf012011-07-13 16:03:46 +00006063 while( x.h && retry<30 ){
drh80084ca2011-07-11 23:45:44 +00006064 retry++;
6065 Sleep(100);
6066 }
6067 if( x.h ){
6068 Tcl_AppendResult(interp, "busy", (char*)0);
6069 return TCL_ERROR;
6070 }
6071 if( Tcl_GetIntFromObj(interp, objv[2], &x.delay1) ) return TCL_ERROR;
6072 if( Tcl_GetIntFromObj(interp, objv[3], &x.delay2) ) return TCL_ERROR;
6073 zFilename = Tcl_GetString(objv[1]);
6074 x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE,
6075 FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
6076 FILE_ATTRIBUTE_NORMAL, 0);
6077 if( !x.h ){
6078 Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0);
6079 return TCL_ERROR;
6080 }
mistachkin176f1b42011-08-02 23:34:00 +00006081 ev = CreateEvent(NULL, TRUE, FALSE, x.evName);
6082 if ( !ev ){
6083 Tcl_AppendResult(interp, "cannot create event: ", x.evName, (char*)0);
6084 return TCL_ERROR;
6085 }
drh80084ca2011-07-11 23:45:44 +00006086 _beginthread(win32_file_locker, 0, (void*)&x);
6087 Sleep(0);
mistachkin176f1b42011-08-02 23:34:00 +00006088 if ( (wResult = WaitForSingleObject(ev, 10000))!=WAIT_OBJECT_0 ){
6089 sqlite3_snprintf(sizeof(zBuf), zBuf, "0x%x", wResult);
6090 Tcl_AppendResult(interp, "wait failed: ", zBuf, (char*)0);
6091 CloseHandle(ev);
6092 return TCL_ERROR;
6093 }
6094 CloseHandle(ev);
drh80084ca2011-07-11 23:45:44 +00006095 return TCL_OK;
6096}
mistachkin37418272013-08-28 05:49:39 +00006097
6098/*
6099** exists_win32_path PATH
6100**
6101** Returns non-zero if the specified path exists, whose fully qualified name
mistachkin3259fe72013-08-28 17:59:38 +00006102** may exceed 260 characters if it is prefixed with "\\?\".
mistachkin37418272013-08-28 05:49:39 +00006103*/
6104static int win32_exists_path(
6105 void *clientData,
6106 Tcl_Interp *interp,
6107 int objc,
6108 Tcl_Obj *CONST objv[]
6109){
6110 if( objc!=2 ){
6111 Tcl_WrongNumArgs(interp, 1, objv, "PATH");
6112 return TCL_ERROR;
6113 }
6114 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
6115 GetFileAttributesW( Tcl_GetUnicode(objv[1]))!=INVALID_FILE_ATTRIBUTES ));
6116 return TCL_OK;
6117}
6118
6119/*
6120** find_win32_file PATTERN
6121**
6122** Returns a list of entries in a directory that match the specified pattern,
6123** whose fully qualified name may exceed 248 characters if it is prefixed with
6124** "\\?\".
6125*/
6126static int win32_find_file(
6127 void *clientData,
6128 Tcl_Interp *interp,
6129 int objc,
6130 Tcl_Obj *CONST objv[]
6131){
6132 HANDLE hFindFile = INVALID_HANDLE_VALUE;
6133 WIN32_FIND_DATAW findData;
6134 Tcl_Obj *listObj;
6135 DWORD lastErrno;
6136 if( objc!=2 ){
6137 Tcl_WrongNumArgs(interp, 1, objv, "PATTERN");
6138 return TCL_ERROR;
6139 }
6140 hFindFile = FindFirstFileW(Tcl_GetUnicode(objv[1]), &findData);
6141 if( hFindFile==INVALID_HANDLE_VALUE ){
6142 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
6143 return TCL_ERROR;
6144 }
6145 listObj = Tcl_NewObj();
6146 Tcl_IncrRefCount(listObj);
6147 do {
6148 Tcl_ListObjAppendElement(interp, listObj, Tcl_NewUnicodeObj(
6149 findData.cFileName, -1));
6150 Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(
6151 findData.dwFileAttributes));
6152 } while( FindNextFileW(hFindFile, &findData) );
6153 lastErrno = GetLastError();
6154 if( lastErrno!=NO_ERROR && lastErrno!=ERROR_NO_MORE_FILES ){
6155 FindClose(hFindFile);
6156 Tcl_DecrRefCount(listObj);
6157 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
6158 return TCL_ERROR;
6159 }
6160 FindClose(hFindFile);
6161 Tcl_SetObjResult(interp, listObj);
6162 return TCL_OK;
6163}
6164
6165/*
6166** delete_win32_file FILENAME
6167**
mistachkin3259fe72013-08-28 17:59:38 +00006168** Deletes the specified file, whose fully qualified name may exceed 260
mistachkin37418272013-08-28 05:49:39 +00006169** characters if it is prefixed with "\\?\".
6170*/
6171static int win32_delete_file(
6172 void *clientData,
6173 Tcl_Interp *interp,
6174 int objc,
6175 Tcl_Obj *CONST objv[]
6176){
6177 if( objc!=2 ){
6178 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
6179 return TCL_ERROR;
6180 }
6181 if( !DeleteFileW(Tcl_GetUnicode(objv[1])) ){
6182 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
6183 return TCL_ERROR;
6184 }
6185 Tcl_ResetResult(interp);
6186 return TCL_OK;
6187}
6188
6189/*
6190** make_win32_dir DIRECTORY
6191**
6192** Creates the specified directory, whose fully qualified name may exceed 248
6193** characters if it is prefixed with "\\?\".
6194*/
6195static int win32_mkdir(
6196 void *clientData,
6197 Tcl_Interp *interp,
6198 int objc,
6199 Tcl_Obj *CONST objv[]
6200){
6201 if( objc!=2 ){
6202 Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY");
6203 return TCL_ERROR;
6204 }
6205 if( !CreateDirectoryW(Tcl_GetUnicode(objv[1]), NULL) ){
6206 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
6207 return TCL_ERROR;
6208 }
6209 Tcl_ResetResult(interp);
6210 return TCL_OK;
6211}
6212
6213/*
6214** remove_win32_dir DIRECTORY
6215**
6216** Removes the specified directory, whose fully qualified name may exceed 248
6217** characters if it is prefixed with "\\?\".
6218*/
6219static int win32_rmdir(
6220 void *clientData,
6221 Tcl_Interp *interp,
6222 int objc,
6223 Tcl_Obj *CONST objv[]
6224){
6225 if( objc!=2 ){
6226 Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY");
6227 return TCL_ERROR;
6228 }
6229 if( !RemoveDirectoryW(Tcl_GetUnicode(objv[1])) ){
6230 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
6231 return TCL_ERROR;
6232 }
6233 Tcl_ResetResult(interp);
6234 return TCL_OK;
6235}
drh80084ca2011-07-11 23:45:44 +00006236#endif
danc17d6962011-06-21 12:47:30 +00006237
drhd0cdf012011-07-13 16:03:46 +00006238
danc17d6962011-06-21 12:47:30 +00006239/*
drhf58ee7f2010-12-06 21:06:09 +00006240** optimization_control DB OPT BOOLEAN
6241**
6242** Enable or disable query optimizations using the sqlite3_test_control()
6243** interface. Disable if BOOLEAN is false and enable if BOOLEAN is true.
6244** OPT is the name of the optimization to be disabled.
6245*/
6246static int optimization_control(
6247 void * clientData,
6248 Tcl_Interp *interp,
6249 int objc,
6250 Tcl_Obj *CONST objv[]
6251){
6252 int i;
6253 sqlite3 *db;
6254 const char *zOpt;
6255 int onoff;
drhfc30b042012-08-20 16:08:29 +00006256 int mask = 0;
drhf58ee7f2010-12-06 21:06:09 +00006257 static const struct {
6258 const char *zOptName;
6259 int mask;
6260 } aOpt[] = {
drh9d5a5792013-06-28 13:43:33 +00006261 { "all", SQLITE_AllOpts },
6262 { "none", 0 },
6263 { "query-flattener", SQLITE_QueryFlattener },
6264 { "column-cache", SQLITE_ColumnCache },
6265 { "groupby-order", SQLITE_GroupByOrder },
6266 { "factor-constants", SQLITE_FactorOutConst },
drh9d5a5792013-06-28 13:43:33 +00006267 { "distinct-opt", SQLITE_DistinctOpt },
6268 { "cover-idx-scan", SQLITE_CoverIdxScan },
6269 { "order-by-idx-join", SQLITE_OrderByIdxJoin },
6270 { "transitive", SQLITE_Transitive },
6271 { "subquery-coroutine", SQLITE_SubqCoroutine },
6272 { "omit-noop-join", SQLITE_OmitNoopJoin },
drhd7d71472014-10-22 19:57:16 +00006273 { "stat3", SQLITE_Stat34 },
6274 { "stat4", SQLITE_Stat34 },
drhf58ee7f2010-12-06 21:06:09 +00006275 };
6276
6277 if( objc!=4 ){
6278 Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN");
6279 return TCL_ERROR;
6280 }
6281 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
6282 if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR;
6283 zOpt = Tcl_GetString(objv[2]);
6284 for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
6285 if( strcmp(zOpt, aOpt[i].zOptName)==0 ){
6286 mask = aOpt[i].mask;
6287 break;
6288 }
6289 }
6290 if( onoff ) mask = ~mask;
6291 if( i>=sizeof(aOpt)/sizeof(aOpt[0]) ){
6292 Tcl_AppendResult(interp, "unknown optimization - should be one of:",
6293 (char*)0);
6294 for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
drh9d5a5792013-06-28 13:43:33 +00006295 Tcl_AppendResult(interp, " ", aOpt[i].zOptName, (char*)0);
drhf58ee7f2010-12-06 21:06:09 +00006296 }
6297 return TCL_ERROR;
6298 }
6299 sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask);
6300 return TCL_OK;
6301}
6302
drh248f2be2013-04-23 20:10:13 +00006303typedef struct sqlite3_api_routines sqlite3_api_routines;
6304/*
drhea41dc42013-04-25 19:31:33 +00006305** load_static_extension DB NAME ...
drh248f2be2013-04-23 20:10:13 +00006306**
drhea41dc42013-04-25 19:31:33 +00006307** Load one or more statically linked extensions.
drh248f2be2013-04-23 20:10:13 +00006308*/
6309static int tclLoadStaticExtensionCmd(
6310 void * clientData,
6311 Tcl_Interp *interp,
6312 int objc,
6313 Tcl_Obj *CONST objv[]
6314){
drh8416fc72013-04-25 16:42:55 +00006315 extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*);
6316 extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
drh1728bcb2014-11-10 16:49:56 +00006317 extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*);
drh51ed2982014-06-16 12:44:32 +00006318 extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
drhe50db1c2013-04-25 14:31:46 +00006319 extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
drh8416fc72013-04-25 16:42:55 +00006320 extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
drhea41dc42013-04-25 19:31:33 +00006321 extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*);
drhdef33672013-05-28 20:25:54 +00006322 extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
drh248f2be2013-04-23 20:10:13 +00006323 extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*);
drhb7045ab2013-04-25 14:59:01 +00006324 extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*);
drh5f8cdac2013-10-14 21:14:42 +00006325 extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*);
drh24b64222013-04-25 11:58:36 +00006326 extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*);
drh248f2be2013-04-23 20:10:13 +00006327 static const struct {
6328 const char *zExtName;
6329 int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*);
6330 } aExtension[] = {
drh8416fc72013-04-25 16:42:55 +00006331 { "amatch", sqlite3_amatch_init },
6332 { "closure", sqlite3_closure_init },
drh1728bcb2014-11-10 16:49:56 +00006333 { "eval", sqlite3_eval_init },
drh51ed2982014-06-16 12:44:32 +00006334 { "fileio", sqlite3_fileio_init },
drhe50db1c2013-04-25 14:31:46 +00006335 { "fuzzer", sqlite3_fuzzer_init },
drh8416fc72013-04-25 16:42:55 +00006336 { "ieee754", sqlite3_ieee_init },
drhea41dc42013-04-25 19:31:33 +00006337 { "nextchar", sqlite3_nextchar_init },
drhdef33672013-05-28 20:25:54 +00006338 { "percentile", sqlite3_percentile_init },
drh24b64222013-04-25 11:58:36 +00006339 { "regexp", sqlite3_regexp_init },
drhb7045ab2013-04-25 14:59:01 +00006340 { "spellfix", sqlite3_spellfix_init },
drh5f8cdac2013-10-14 21:14:42 +00006341 { "totype", sqlite3_totype_init },
drh24b64222013-04-25 11:58:36 +00006342 { "wholenumber", sqlite3_wholenumber_init },
drh248f2be2013-04-23 20:10:13 +00006343 };
6344 sqlite3 *db;
6345 const char *zName;
drhea41dc42013-04-25 19:31:33 +00006346 int i, j, rc;
drh248f2be2013-04-23 20:10:13 +00006347 char *zErrMsg = 0;
drhea41dc42013-04-25 19:31:33 +00006348 if( objc<3 ){
6349 Tcl_WrongNumArgs(interp, 1, objv, "DB NAME ...");
drh248f2be2013-04-23 20:10:13 +00006350 return TCL_ERROR;
6351 }
6352 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
drhea41dc42013-04-25 19:31:33 +00006353 for(j=2; j<objc; j++){
6354 zName = Tcl_GetString(objv[j]);
6355 for(i=0; i<ArraySize(aExtension); i++){
6356 if( strcmp(zName, aExtension[i].zExtName)==0 ) break;
6357 }
6358 if( i>=ArraySize(aExtension) ){
6359 Tcl_AppendResult(interp, "no such extension: ", zName, (char*)0);
6360 return TCL_ERROR;
6361 }
6362 rc = aExtension[i].pInit(db, &zErrMsg, 0);
6363 if( rc!=SQLITE_OK || zErrMsg ){
6364 Tcl_AppendResult(interp, "initialization of ", zName, " failed: ", zErrMsg,
6365 (char*)0);
6366 sqlite3_free(zErrMsg);
6367 return TCL_ERROR;
6368 }
drh248f2be2013-04-23 20:10:13 +00006369 }
6370 return TCL_OK;
6371}
6372
dan0d51def2014-05-03 14:28:14 +00006373/*
6374** sorter_test_fakeheap BOOL
6375**
6376*/
6377static int sorter_test_fakeheap(
6378 void * clientData,
6379 Tcl_Interp *interp,
6380 int objc,
6381 Tcl_Obj *CONST objv[]
6382){
6383 int bArg;
6384 if( objc!=2 ){
6385 Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
6386 return TCL_ERROR;
6387 }
6388
6389 if( Tcl_GetBooleanFromObj(interp, objv[1], &bArg) ){
6390 return TCL_ERROR;
6391 }
6392
6393 if( bArg ){
6394 if( sqlite3GlobalConfig.pHeap==0 ){
6395 sqlite3GlobalConfig.pHeap = SQLITE_INT_TO_PTR(-1);
6396 }
6397 }else{
6398 if( sqlite3GlobalConfig.pHeap==SQLITE_INT_TO_PTR(-1) ){
6399 sqlite3GlobalConfig.pHeap = 0;
6400 }
6401 }
6402
6403 Tcl_ResetResult(interp);
6404 return TCL_OK;
6405}
6406
dandfea4532014-05-06 15:38:07 +00006407/*
6408** sorter_test_sort4_helper DB SQL1 NSTEP SQL2
6409**
6410** Compile SQL statement $SQL1 and step it $NSTEP times. For each row,
6411** check that the leftmost and rightmost columns returned are both integers,
6412** and that both contain the same value.
6413**
6414** Then execute statement $SQL2. Check that the statement returns the same
6415** set of integers in the same order as in the previous step (using $SQL1).
6416*/
6417static int sorter_test_sort4_helper(
6418 void * clientData,
6419 Tcl_Interp *interp,
6420 int objc,
6421 Tcl_Obj *CONST objv[]
6422){
6423 const char *zSql1;
6424 const char *zSql2;
6425 int nStep;
6426 int iStep;
6427 int iCksum1 = 0;
6428 int iCksum2 = 0;
6429 int rc;
6430 int iB;
6431 sqlite3 *db;
6432 sqlite3_stmt *pStmt;
6433
6434 if( objc!=5 ){
6435 Tcl_WrongNumArgs(interp, 1, objv, "DB SQL1 NSTEP SQL2");
6436 return TCL_ERROR;
6437 }
6438
6439 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
6440 zSql1 = Tcl_GetString(objv[2]);
6441 if( Tcl_GetIntFromObj(interp, objv[3], &nStep) ) return TCL_ERROR;
6442 zSql2 = Tcl_GetString(objv[4]);
6443
6444 rc = sqlite3_prepare_v2(db, zSql1, -1, &pStmt, 0);
6445 if( rc!=SQLITE_OK ) goto sql_error;
6446
6447 iB = sqlite3_column_count(pStmt)-1;
6448 for(iStep=0; iStep<nStep && SQLITE_ROW==sqlite3_step(pStmt); iStep++){
6449 int a = sqlite3_column_int(pStmt, 0);
6450 if( a!=sqlite3_column_int(pStmt, iB) ){
6451 Tcl_AppendResult(interp, "data error: (a!=b)", 0);
6452 return TCL_ERROR;
6453 }
6454
6455 iCksum1 += (iCksum1 << 3) + a;
6456 }
6457 rc = sqlite3_finalize(pStmt);
6458 if( rc!=SQLITE_OK ) goto sql_error;
6459
6460 rc = sqlite3_prepare_v2(db, zSql2, -1, &pStmt, 0);
6461 if( rc!=SQLITE_OK ) goto sql_error;
6462 for(iStep=0; SQLITE_ROW==sqlite3_step(pStmt); iStep++){
6463 int a = sqlite3_column_int(pStmt, 0);
6464 iCksum2 += (iCksum2 << 3) + a;
6465 }
6466 rc = sqlite3_finalize(pStmt);
6467 if( rc!=SQLITE_OK ) goto sql_error;
6468
6469 if( iCksum1!=iCksum2 ){
6470 Tcl_AppendResult(interp, "checksum mismatch", 0);
6471 return TCL_ERROR;
6472 }
6473
6474 return TCL_OK;
6475 sql_error:
6476 Tcl_AppendResult(interp, "sql error: ", sqlite3_errmsg(db), 0);
6477 return TCL_ERROR;
6478}
6479
drh248f2be2013-04-23 20:10:13 +00006480
drhd39c40f2014-09-11 00:27:53 +00006481#ifdef SQLITE_USER_AUTHENTICATION
6482#include "sqlite3userauth.h"
6483/*
6484** tclcmd: sqlite3_user_authenticate DB USERNAME PASSWORD
6485*/
6486static int test_user_authenticate(
6487 ClientData clientData, /* Unused */
6488 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6489 int objc, /* Number of arguments */
6490 Tcl_Obj *CONST objv[] /* Command arguments */
6491){
6492 char *zUser = 0;
6493 char *zPasswd = 0;
6494 int nPasswd = 0;
6495 sqlite3 *db;
6496 int rc;
6497
6498 if( objc!=4 ){
6499 Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD");
6500 return TCL_ERROR;
6501 }
6502 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6503 return TCL_ERROR;
6504 }
6505 zUser = Tcl_GetString(objv[2]);
6506 zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
6507 rc = sqlite3_user_authenticate(db, zUser, zPasswd, nPasswd);
6508 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
6509 return TCL_OK;
6510}
6511#endif /* SQLITE_USER_AUTHENTICATION */
6512
6513#ifdef SQLITE_USER_AUTHENTICATION
6514/*
6515** tclcmd: sqlite3_user_add DB USERNAME PASSWORD ISADMIN
6516*/
6517static int test_user_add(
6518 ClientData clientData, /* Unused */
6519 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6520 int objc, /* Number of arguments */
6521 Tcl_Obj *CONST objv[] /* Command arguments */
6522){
6523 char *zUser = 0;
6524 char *zPasswd = 0;
6525 int nPasswd = 0;
6526 int isAdmin = 0;
6527 sqlite3 *db;
6528 int rc;
6529
6530 if( objc!=5 ){
6531 Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
6532 return TCL_ERROR;
6533 }
6534 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6535 return TCL_ERROR;
6536 }
6537 zUser = Tcl_GetString(objv[2]);
6538 zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
6539 Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
6540 rc = sqlite3_user_add(db, zUser, zPasswd, nPasswd, isAdmin);
6541 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
6542 return TCL_OK;
6543}
6544#endif /* SQLITE_USER_AUTHENTICATION */
6545
6546#ifdef SQLITE_USER_AUTHENTICATION
6547/*
6548** tclcmd: sqlite3_user_change DB USERNAME PASSWORD ISADMIN
6549*/
6550static int test_user_change(
6551 ClientData clientData, /* Unused */
6552 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6553 int objc, /* Number of arguments */
6554 Tcl_Obj *CONST objv[] /* Command arguments */
6555){
6556 char *zUser = 0;
6557 char *zPasswd = 0;
6558 int nPasswd = 0;
6559 int isAdmin = 0;
6560 sqlite3 *db;
6561 int rc;
6562
6563 if( objc!=5 ){
6564 Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
6565 return TCL_ERROR;
6566 }
6567 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6568 return TCL_ERROR;
6569 }
6570 zUser = Tcl_GetString(objv[2]);
6571 zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
6572 Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
6573 rc = sqlite3_user_change(db, zUser, zPasswd, nPasswd, isAdmin);
6574 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
6575 return TCL_OK;
6576}
6577#endif /* SQLITE_USER_AUTHENTICATION */
6578
6579#ifdef SQLITE_USER_AUTHENTICATION
6580/*
6581** tclcmd: sqlite3_user_delete DB USERNAME
6582*/
6583static int test_user_delete(
6584 ClientData clientData, /* Unused */
6585 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6586 int objc, /* Number of arguments */
6587 Tcl_Obj *CONST objv[] /* Command arguments */
6588){
6589 char *zUser = 0;
6590 sqlite3 *db;
6591 int rc;
6592
6593 if( objc!=3 ){
6594 Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME");
6595 return TCL_ERROR;
6596 }
6597 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6598 return TCL_ERROR;
6599 }
6600 zUser = Tcl_GetString(objv[2]);
6601 rc = sqlite3_user_delete(db, zUser);
6602 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
6603 return TCL_OK;
6604}
6605#endif /* SQLITE_USER_AUTHENTICATION */
6606
drhf58ee7f2010-12-06 21:06:09 +00006607/*
drhd1bf3512001-04-07 15:24:33 +00006608** Register commands with the TCL interpreter.
6609*/
6610int Sqlitetest1_Init(Tcl_Interp *interp){
danielk19776f8a5032004-05-10 10:34:51 +00006611 extern int sqlite3_search_count;
dan0ff297e2009-09-25 17:03:14 +00006612 extern int sqlite3_found_count;
danielk19776f8a5032004-05-10 10:34:51 +00006613 extern int sqlite3_interrupt_count;
6614 extern int sqlite3_open_file_count;
drh6bf89572004-11-03 16:27:01 +00006615 extern int sqlite3_sort_count;
danielk19776f8a5032004-05-10 10:34:51 +00006616 extern int sqlite3_current_time;
drh84a2bf62010-03-05 13:41:06 +00006617#if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
aswiftaebf4132008-11-21 00:10:35 +00006618 extern int sqlite3_hostid_num;
pweilbacheraabbed22008-11-21 23:35:02 +00006619#endif
drhae7e1512007-05-02 16:51:59 +00006620 extern int sqlite3_max_blobsize;
drh16a9b832007-05-05 18:39:25 +00006621 extern int sqlite3BtreeSharedCacheReport(void*,
6622 Tcl_Interp*,int,Tcl_Obj*CONST*);
drhc2eef3b2002-08-31 18:53:06 +00006623 static struct {
6624 char *zName;
6625 Tcl_CmdProc *xProc;
6626 } aCmd[] = {
drh27641702007-08-22 02:56:42 +00006627 { "db_enter", (Tcl_CmdProc*)db_enter },
6628 { "db_leave", (Tcl_CmdProc*)db_leave },
drhd3d39e92004-05-20 22:16:29 +00006629 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int },
drhe9707672004-06-25 01:10:48 +00006630 { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 },
drhc5cad1e2009-02-01 00:21:09 +00006631 { "sqlite3_mprintf_long", (Tcl_CmdProc*)sqlite3_mprintf_long },
drhd3d39e92004-05-20 22:16:29 +00006632 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str },
drhb3738b62007-03-31 15:02:49 +00006633 { "sqlite3_snprintf_str", (Tcl_CmdProc*)sqlite3_snprintf_str },
drhe29b1a02004-07-17 21:56:09 +00006634 { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly},
drhd3d39e92004-05-20 22:16:29 +00006635 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double },
6636 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled },
drh63782852005-08-30 19:30:59 +00006637 { "sqlite3_mprintf_hexdouble", (Tcl_CmdProc*)sqlite3_mprintf_hexdouble},
drhd3d39e92004-05-20 22:16:29 +00006638 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z },
drh05a82982006-03-19 13:00:25 +00006639 { "sqlite3_mprintf_n_test", (Tcl_CmdProc*)test_mprintf_n },
drh68853902007-05-07 11:24:30 +00006640 { "sqlite3_snprintf_int", (Tcl_CmdProc*)test_snprintf_int },
drhd3d39e92004-05-20 22:16:29 +00006641 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid },
6642 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf },
drh5bd98ae2009-01-07 18:24:03 +00006643 { "sqlite3_exec_hex", (Tcl_CmdProc*)test_exec_hex },
drhb62c3352006-11-23 09:39:16 +00006644 { "sqlite3_exec", (Tcl_CmdProc*)test_exec },
6645 { "sqlite3_exec_nr", (Tcl_CmdProc*)test_exec_nr },
shane8225f5a2008-07-31 02:05:04 +00006646#ifndef SQLITE_OMIT_GET_TABLE
drhd3d39e92004-05-20 22:16:29 +00006647 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
shane8225f5a2008-07-31 02:05:04 +00006648#endif
drhd3d39e92004-05-20 22:16:29 +00006649 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close },
dan617dc862013-05-16 11:57:28 +00006650 { "sqlite3_close_v2", (Tcl_CmdProc*)sqlite_test_close_v2 },
drhd3d39e92004-05-20 22:16:29 +00006651 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
6652 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
6653 { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
6654 { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
drh25d65432004-07-22 15:02:25 +00006655 { "sqlite_bind", (Tcl_CmdProc*)test_bind },
6656 { "breakpoint", (Tcl_CmdProc*)test_breakpoint },
6657 { "sqlite3_key", (Tcl_CmdProc*)test_key },
6658 { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey },
drhcacb2082005-01-11 15:28:33 +00006659 { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic },
drhc5cdca62005-01-11 16:54:14 +00006660 { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt },
drh3e1d8e62005-05-26 16:23:34 +00006661 { "sqlite_delete_function", (Tcl_CmdProc*)delete_function },
6662 { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation },
6663 { "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit },
drh79158e12005-09-06 21:40:45 +00006664 { "sqlite3_stack_used", (Tcl_CmdProc*)test_stack_used },
drh30867652006-07-06 10:59:57 +00006665 { "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout },
drh3c23a882007-01-09 14:01:13 +00006666 { "printf", (Tcl_CmdProc*)test_printf },
mlcreech3a00f902008-03-04 17:45:01 +00006667 { "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace },
danafcf9bd2014-01-23 14:44:08 +00006668 { "clang_sanitize_address", (Tcl_CmdProc*)clang_sanitize_address },
drhc2eef3b2002-08-31 18:53:06 +00006669 };
danielk197751e3d8e2004-05-20 01:12:34 +00006670 static struct {
6671 char *zName;
6672 Tcl_ObjCmdProc *xProc;
danielk197704f2e682004-05-27 01:04:07 +00006673 void *clientData;
danielk197751e3d8e2004-05-20 01:12:34 +00006674 } aObjCmd[] = {
drhdddca282006-01-03 00:33:50 +00006675 { "sqlite3_connection_pointer", get_sqlite_pointer, 0 },
drh241db312004-06-22 12:46:53 +00006676 { "sqlite3_bind_int", test_bind_int, 0 },
drhb026e052007-05-02 01:34:31 +00006677 { "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 },
drh241db312004-06-22 12:46:53 +00006678 { "sqlite3_bind_int64", test_bind_int64, 0 },
6679 { "sqlite3_bind_double", test_bind_double, 0 },
danielk197704f2e682004-05-27 01:04:07 +00006680 { "sqlite3_bind_null", test_bind_null ,0 },
6681 { "sqlite3_bind_text", test_bind_text ,0 },
6682 { "sqlite3_bind_text16", test_bind_text16 ,0 },
6683 { "sqlite3_bind_blob", test_bind_blob ,0 },
drh75f6a032004-07-15 14:15:00 +00006684 { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0},
drh895d7472004-08-20 16:02:39 +00006685 { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0},
drhfa6bc002004-09-07 16:19:52 +00006686 { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0},
danielk1977600dd0b2005-01-20 01:14:23 +00006687 { "sqlite3_clear_bindings", test_clear_bindings, 0},
drhf9cb7f52006-06-27 20:06:44 +00006688 { "sqlite3_sleep", test_sleep, 0},
danielk197704f2e682004-05-27 01:04:07 +00006689 { "sqlite3_errcode", test_errcode ,0 },
drh99dfe5e2008-10-30 15:03:15 +00006690 { "sqlite3_extended_errcode", test_ex_errcode ,0 },
danielk197704f2e682004-05-27 01:04:07 +00006691 { "sqlite3_errmsg", test_errmsg ,0 },
6692 { "sqlite3_errmsg16", test_errmsg16 ,0 },
6693 { "sqlite3_open", test_open ,0 },
6694 { "sqlite3_open16", test_open16 ,0 },
dan286ab7c2011-05-06 18:34:54 +00006695 { "sqlite3_open_v2", test_open_v2 ,0 },
danielk1977bc6ada42004-06-30 08:20:16 +00006696 { "sqlite3_complete16", test_complete16 ,0 },
danielk197704f2e682004-05-27 01:04:07 +00006697
6698 { "sqlite3_prepare", test_prepare ,0 },
6699 { "sqlite3_prepare16", test_prepare16 ,0 },
drhb900aaf2006-11-09 00:24:53 +00006700 { "sqlite3_prepare_v2", test_prepare_v2 ,0 },
drh4837f532008-05-23 14:49:49 +00006701 { "sqlite3_prepare_tkt3134", test_prepare_tkt3134, 0},
drhb900aaf2006-11-09 00:24:53 +00006702 { "sqlite3_prepare16_v2", test_prepare16_v2 ,0 },
danielk197704f2e682004-05-27 01:04:07 +00006703 { "sqlite3_finalize", test_finalize ,0 },
drhd1d38482008-10-07 23:46:38 +00006704 { "sqlite3_stmt_status", test_stmt_status ,0 },
danielk197704f2e682004-05-27 01:04:07 +00006705 { "sqlite3_reset", test_reset ,0 },
drhd89bd002005-01-22 03:03:54 +00006706 { "sqlite3_expired", test_expired ,0 },
drhf8db1bc2005-04-22 02:38:37 +00006707 { "sqlite3_transfer_bindings", test_transfer_bind ,0 },
danielk1977fbcd5852004-06-15 02:44:18 +00006708 { "sqlite3_changes", test_changes ,0 },
6709 { "sqlite3_step", test_step ,0 },
danielk1977404ca072009-03-16 13:19:36 +00006710 { "sqlite3_sql", test_sql ,0 },
drhbb5a9c32008-06-19 02:52:25 +00006711 { "sqlite3_next_stmt", test_next_stmt ,0 },
drhf03d9cc2010-11-16 23:10:25 +00006712 { "sqlite3_stmt_readonly", test_stmt_readonly ,0 },
drh2fb66932011-11-25 17:21:47 +00006713 { "sqlite3_stmt_busy", test_stmt_busy ,0 },
dand9495cd2011-04-27 12:08:04 +00006714 { "uses_stmt_journal", uses_stmt_journal ,0 },
danielk197704f2e682004-05-27 01:04:07 +00006715
drhb4bc7052006-01-11 23:40:33 +00006716 { "sqlite3_release_memory", test_release_memory, 0},
drh09419b42011-11-16 19:29:17 +00006717 { "sqlite3_db_release_memory", test_db_release_memory, 0},
drh283829c2011-11-17 00:56:20 +00006718 { "sqlite3_db_filename", test_db_filename, 0},
drh421377e2012-03-15 21:28:54 +00006719 { "sqlite3_db_readonly", test_db_readonly, 0},
drhb4bc7052006-01-11 23:40:33 +00006720 { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
drhb4bc7052006-01-11 23:40:33 +00006721 { "sqlite3_thread_cleanup", test_thread_cleanup, 0},
drhc6ba55f2007-04-05 17:36:18 +00006722 { "sqlite3_pager_refcounts", test_pager_refcounts, 0},
drh6aafc292006-01-05 15:50:06 +00006723
drhc2e87a32006-06-27 15:16:14 +00006724 { "sqlite3_load_extension", test_load_extension, 0},
6725 { "sqlite3_enable_load_extension", test_enable_load, 0},
drh4ac285a2006-09-15 07:28:50 +00006726 { "sqlite3_extended_result_codes", test_extended_result_codes, 0},
drhb1a6c3c2008-03-20 16:30:17 +00006727 { "sqlite3_limit", test_limit, 0},
drhc2e87a32006-06-27 15:16:14 +00006728
drh93aed5a2008-01-16 17:46:38 +00006729 { "save_prng_state", save_prng_state, 0 },
6730 { "restore_prng_state", restore_prng_state, 0 },
6731 { "reset_prng_state", reset_prng_state, 0 },
drh09fe6142013-11-29 15:06:27 +00006732 { "database_never_corrupt", database_never_corrupt, 0},
6733 { "database_may_be_corrupt", database_may_be_corrupt, 0},
drhf58ee7f2010-12-06 21:06:09 +00006734 { "optimization_control", optimization_control,0},
drh80084ca2011-07-11 23:45:44 +00006735#if SQLITE_OS_WIN
6736 { "lock_win32_file", win32_file_lock, 0 },
mistachkin37418272013-08-28 05:49:39 +00006737 { "exists_win32_path", win32_exists_path, 0 },
6738 { "find_win32_file", win32_find_file, 0 },
6739 { "delete_win32_file", win32_delete_file, 0 },
6740 { "make_win32_dir", win32_mkdir, 0 },
6741 { "remove_win32_dir", win32_rmdir, 0 },
drh80084ca2011-07-11 23:45:44 +00006742#endif
drha2c8a952009-10-13 18:38:34 +00006743 { "tcl_objproc", runAsObjProc, 0 },
drh93aed5a2008-01-16 17:46:38 +00006744
danielk197704f2e682004-05-27 01:04:07 +00006745 /* sqlite3_column_*() API */
6746 { "sqlite3_column_count", test_column_count ,0 },
6747 { "sqlite3_data_count", test_data_count ,0 },
6748 { "sqlite3_column_type", test_column_type ,0 },
danielk1977ea61b2c2004-05-27 01:49:51 +00006749 { "sqlite3_column_blob", test_column_blob ,0 },
danielk197704f2e682004-05-27 01:04:07 +00006750 { "sqlite3_column_double", test_column_double ,0 },
6751 { "sqlite3_column_int64", test_column_int64 ,0 },
danielk197744a376f2008-08-12 15:04:58 +00006752 { "sqlite3_column_text", test_stmt_utf8, (void*)sqlite3_column_text },
6753 { "sqlite3_column_name", test_stmt_utf8, (void*)sqlite3_column_name },
6754 { "sqlite3_column_int", test_stmt_int, (void*)sqlite3_column_int },
6755 { "sqlite3_column_bytes", test_stmt_int, (void*)sqlite3_column_bytes},
drh3f913572008-03-22 01:07:17 +00006756#ifndef SQLITE_OMIT_DECLTYPE
danielk197744a376f2008-08-12 15:04:58 +00006757 { "sqlite3_column_decltype",test_stmt_utf8,(void*)sqlite3_column_decltype},
drh3f913572008-03-22 01:07:17 +00006758#endif
danielk19774b1ae992006-02-10 03:06:10 +00006759#ifdef SQLITE_ENABLE_COLUMN_METADATA
danielk197744a376f2008-08-12 15:04:58 +00006760{ "sqlite3_column_database_name",test_stmt_utf8,(void*)sqlite3_column_database_name},
6761{ "sqlite3_column_table_name",test_stmt_utf8,(void*)sqlite3_column_table_name},
6762{ "sqlite3_column_origin_name",test_stmt_utf8,(void*)sqlite3_column_origin_name},
danielk19774b1ae992006-02-10 03:06:10 +00006763#endif
danielk1977955de522006-02-10 02:27:42 +00006764
drh6c626082004-11-14 21:56:29 +00006765#ifndef SQLITE_OMIT_UTF16
danielk197744a376f2008-08-12 15:04:58 +00006766 { "sqlite3_column_bytes16", test_stmt_int, (void*)sqlite3_column_bytes16 },
6767 { "sqlite3_column_text16", test_stmt_utf16, (void*)sqlite3_column_text16},
6768 { "sqlite3_column_name16", test_stmt_utf16, (void*)sqlite3_column_name16},
drh7d9bd4e2006-02-16 18:16:36 +00006769 { "add_alignment_test_collations", add_alignment_test_collations, 0 },
drh3f913572008-03-22 01:07:17 +00006770#ifndef SQLITE_OMIT_DECLTYPE
danielk197744a376f2008-08-12 15:04:58 +00006771 { "sqlite3_column_decltype16",test_stmt_utf16,(void*)sqlite3_column_decltype16},
drh3f913572008-03-22 01:07:17 +00006772#endif
danielk19774b1ae992006-02-10 03:06:10 +00006773#ifdef SQLITE_ENABLE_COLUMN_METADATA
danielk1977955de522006-02-10 02:27:42 +00006774{"sqlite3_column_database_name16",
drh7da5fcb2012-03-30 14:59:43 +00006775 test_stmt_utf16, (void*)sqlite3_column_database_name16},
danielk197744a376f2008-08-12 15:04:58 +00006776{"sqlite3_column_table_name16", test_stmt_utf16, (void*)sqlite3_column_table_name16},
6777{"sqlite3_column_origin_name16", test_stmt_utf16, (void*)sqlite3_column_origin_name16},
drh6c626082004-11-14 21:56:29 +00006778#endif
danielk19774b1ae992006-02-10 03:06:10 +00006779#endif
danielk1977a393c032007-05-07 14:58:53 +00006780 { "sqlite3_create_collation_v2", test_create_collation_v2, 0 },
danielk1977a9808b32007-05-07 09:32:45 +00006781 { "sqlite3_global_recover", test_global_recover, 0 },
6782 { "working_64bit_int", working_64bit_int, 0 },
drh9bc54492007-10-23 14:49:59 +00006783 { "vfs_unlink_test", vfs_unlink_test, 0 },
drhc8d75672008-07-08 02:12:37 +00006784 { "vfs_initfail_test", vfs_initfail_test, 0 },
drha2820972008-07-07 13:31:58 +00006785 { "vfs_unregister_all", vfs_unregister_all, 0 },
6786 { "vfs_reregister_all", vfs_reregister_all, 0 },
drh55176252008-01-22 14:50:16 +00006787 { "file_control_test", file_control_test, 0 },
aswiftaebf4132008-11-21 00:10:35 +00006788 { "file_control_lasterrno_test", file_control_lasterrno_test, 0 },
6789 { "file_control_lockproxy_test", file_control_lockproxy_test, 0 },
dan6e09d692010-07-27 18:34:15 +00006790 { "file_control_chunksize_test", file_control_chunksize_test, 0 },
drhd0cdf012011-07-13 16:03:46 +00006791 { "file_control_sizehint_test", file_control_sizehint_test, 0 },
mistachkin6b98d672014-05-30 16:42:35 +00006792#if SQLITE_OS_WIN
drhd0cdf012011-07-13 16:03:46 +00006793 { "file_control_win32_av_retry", file_control_win32_av_retry, 0 },
mistachkin6b98d672014-05-30 16:42:35 +00006794 { "file_control_win32_set_handle", file_control_win32_set_handle, 0 },
6795#endif
drh253cea52011-07-26 16:23:25 +00006796 { "file_control_persist_wal", file_control_persist_wal, 0 },
drhcb15f352011-12-23 01:04:17 +00006797 { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
drhde60fc22011-12-14 17:53:36 +00006798 { "file_control_vfsname", file_control_vfsname, 0 },
drh696b33e2012-12-06 19:01:42 +00006799 { "file_control_tempfilename", file_control_tempfilename, 0 },
danielk1977e339d652008-06-28 11:23:00 +00006800 { "sqlite3_vfs_list", vfs_list, 0 },
dand2199f02010-08-27 17:48:52 +00006801 { "sqlite3_create_function_v2", test_create_function_v2, 0 },
danielk197704f2e682004-05-27 01:04:07 +00006802
danielk19779a1d0ab2004-06-01 14:09:28 +00006803 /* Functions from os.h */
drh5436dc22004-11-14 04:04:17 +00006804#ifndef SQLITE_OMIT_UTF16
danielk1977312d6b32004-06-29 13:18:23 +00006805 { "add_test_collate", test_collate, 0 },
6806 { "add_test_collate_needed", test_collate_needed, 0 },
6807 { "add_test_function", test_function, 0 },
dan38fdead2014-04-01 10:19:02 +00006808 { "add_test_utf16bin_collate", test_utf16bin_collate, 0 },
drh5436dc22004-11-14 04:04:17 +00006809#endif
danielk1977312d6b32004-06-29 13:18:23 +00006810 { "sqlite3_test_errstr", test_errstr, 0 },
drh92febd92004-08-20 18:34:20 +00006811 { "tcl_variable_type", tcl_variable_type, 0 },
danielk1977aef0bf62005-12-30 16:28:01 +00006812#ifndef SQLITE_OMIT_SHARED_CACHE
drh6f7adc82006-01-11 21:41:20 +00006813 { "sqlite3_enable_shared_cache", test_enable_shared, 0 },
drh16a9b832007-05-05 18:39:25 +00006814 { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0},
danielk1977aef0bf62005-12-30 16:28:01 +00006815#endif
danielk1977161fb792006-01-24 10:58:21 +00006816 { "sqlite3_libversion_number", test_libversion_number, 0 },
danielk1977deb802c2006-02-09 13:43:28 +00006817 { "sqlite3_table_column_metadata", test_table_column_metadata, 0 },
danielk1977dcbb5d32007-05-04 18:36:44 +00006818#ifndef SQLITE_OMIT_INCRBLOB
dan4e76cc32010-10-20 18:56:04 +00006819 { "sqlite3_blob_reopen", test_blob_reopen, 0 },
danielk1977dcbb5d32007-05-04 18:36:44 +00006820#endif
danielk1977062d4cb2008-08-29 09:10:02 +00006821 { "pcache_stats", test_pcache_stats, 0 },
danielk1977404ca072009-03-16 13:19:36 +00006822#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
6823 { "sqlite3_unlock_notify", test_unlock_notify, 0 },
6824#endif
dan91da6b82010-11-15 14:51:33 +00006825 { "sqlite3_wal_checkpoint", test_wal_checkpoint, 0 },
dan9c5e3682011-02-07 15:12:12 +00006826 { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0 },
dan9af10622014-12-15 16:27:12 +00006827 { "sqlite3_wal_autocheckpoint",test_wal_autocheckpoint, 0 },
dan91da6b82010-11-15 14:51:33 +00006828 { "test_sqlite3_log", test_sqlite3_log, 0 },
shanehbb201342011-02-09 19:55:20 +00006829#ifndef SQLITE_OMIT_EXPLAIN
dan91da6b82010-11-15 14:51:33 +00006830 { "print_explain_query_plan", test_print_eqp, 0 },
shanehbb201342011-02-09 19:55:20 +00006831#endif
danc17d6962011-06-21 12:47:30 +00006832 { "sqlite3_test_control", test_test_control },
mistachkindaf9a5a2013-03-23 09:56:39 +00006833#if SQLITE_OS_UNIX
dana72014f2013-03-16 20:19:21 +00006834 { "getrusage", test_getrusage },
mistachkindaf9a5a2013-03-23 09:56:39 +00006835#endif
drh248f2be2013-04-23 20:10:13 +00006836 { "load_static_extension", tclLoadStaticExtensionCmd },
dan0d51def2014-05-03 14:28:14 +00006837 { "sorter_test_fakeheap", sorter_test_fakeheap },
dandfea4532014-05-06 15:38:07 +00006838 { "sorter_test_sort4_helper", sorter_test_sort4_helper },
drhd39c40f2014-09-11 00:27:53 +00006839#ifdef SQLITE_USER_AUTHENTICATION
6840 { "sqlite3_user_authenticate", test_user_authenticate, 0 },
6841 { "sqlite3_user_add", test_user_add, 0 },
6842 { "sqlite3_user_change", test_user_change, 0 },
6843 { "sqlite3_user_delete", test_user_delete, 0 },
6844#endif
dan04489b62014-10-31 20:11:32 +00006845#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
6846 { "sqlite3_stmt_scanstatus", test_stmt_scanstatus, 0 },
6847 { "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset, 0 },
6848#endif
drhd39c40f2014-09-11 00:27:53 +00006849
danielk197751e3d8e2004-05-20 01:12:34 +00006850 };
drh1398ad32005-01-19 23:24:50 +00006851 static int bitmask_size = sizeof(Bitmask)*8;
drhc2eef3b2002-08-31 18:53:06 +00006852 int i;
drhb851b2c2005-03-10 14:11:12 +00006853 extern int sqlite3_sync_count, sqlite3_fullsync_count;
drhaf6df112005-06-07 02:12:30 +00006854 extern int sqlite3_opentemp_count;
drh55ef4d92005-08-14 01:20:37 +00006855 extern int sqlite3_like_count;
drhdd735212007-02-24 13:53:05 +00006856 extern int sqlite3_xferopt_count;
drh538f5702007-04-13 02:14:30 +00006857 extern int sqlite3_pager_readdb_count;
6858 extern int sqlite3_pager_writedb_count;
6859 extern int sqlite3_pager_writej_count;
danielk197729bafea2008-06-26 10:41:19 +00006860#if SQLITE_OS_WIN
mistachkin202cb642014-07-31 18:54:01 +00006861 extern LONG volatile sqlite3_os_type;
drhc0929982005-09-05 19:08:29 +00006862#endif
drh8b3d9902005-08-19 00:14:42 +00006863#ifdef SQLITE_DEBUG
mlcreech3a00f902008-03-04 17:45:01 +00006864 extern int sqlite3WhereTrace;
6865 extern int sqlite3OSTrace;
drhc74c3332010-05-31 12:15:19 +00006866 extern int sqlite3WalTrace;
drh549c8b62005-09-19 13:15:23 +00006867#endif
6868#ifdef SQLITE_TEST
danielk197733e89032008-12-17 15:18:17 +00006869#ifdef SQLITE_ENABLE_FTS3
6870 extern int sqlite3_fts3_enable_parentheses;
6871#endif
drh48083ce2005-09-19 12:37:27 +00006872#endif
drhc2eef3b2002-08-31 18:53:06 +00006873
6874 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
6875 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
6876 }
danielk197751e3d8e2004-05-20 01:12:34 +00006877 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
danielk1977c572ef72004-05-27 09:28:41 +00006878 Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
6879 aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
danielk197751e3d8e2004-05-20 01:12:34 +00006880 }
danielk19776490beb2004-05-11 06:17:21 +00006881 Tcl_LinkVar(interp, "sqlite_search_count",
danielk19776f8a5032004-05-10 10:34:51 +00006882 (char*)&sqlite3_search_count, TCL_LINK_INT);
dan0ff297e2009-09-25 17:03:14 +00006883 Tcl_LinkVar(interp, "sqlite_found_count",
6884 (char*)&sqlite3_found_count, TCL_LINK_INT);
drh6bf89572004-11-03 16:27:01 +00006885 Tcl_LinkVar(interp, "sqlite_sort_count",
6886 (char*)&sqlite3_sort_count, TCL_LINK_INT);
drhae7e1512007-05-02 16:51:59 +00006887 Tcl_LinkVar(interp, "sqlite3_max_blobsize",
6888 (char*)&sqlite3_max_blobsize, TCL_LINK_INT);
drh55ef4d92005-08-14 01:20:37 +00006889 Tcl_LinkVar(interp, "sqlite_like_count",
6890 (char*)&sqlite3_like_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00006891 Tcl_LinkVar(interp, "sqlite_interrupt_count",
danielk19776f8a5032004-05-10 10:34:51 +00006892 (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00006893 Tcl_LinkVar(interp, "sqlite_open_file_count",
danielk19776f8a5032004-05-10 10:34:51 +00006894 (char*)&sqlite3_open_file_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00006895 Tcl_LinkVar(interp, "sqlite_current_time",
danielk19776f8a5032004-05-10 10:34:51 +00006896 (char*)&sqlite3_current_time, TCL_LINK_INT);
drh84a2bf62010-03-05 13:41:06 +00006897#if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
aswiftaebf4132008-11-21 00:10:35 +00006898 Tcl_LinkVar(interp, "sqlite_hostid_num",
6899 (char*)&sqlite3_hostid_num, TCL_LINK_INT);
pweilbacheraabbed22008-11-21 23:35:02 +00006900#endif
drhdd735212007-02-24 13:53:05 +00006901 Tcl_LinkVar(interp, "sqlite3_xferopt_count",
6902 (char*)&sqlite3_xferopt_count, TCL_LINK_INT);
drh538f5702007-04-13 02:14:30 +00006903 Tcl_LinkVar(interp, "sqlite3_pager_readdb_count",
6904 (char*)&sqlite3_pager_readdb_count, TCL_LINK_INT);
6905 Tcl_LinkVar(interp, "sqlite3_pager_writedb_count",
6906 (char*)&sqlite3_pager_writedb_count, TCL_LINK_INT);
6907 Tcl_LinkVar(interp, "sqlite3_pager_writej_count",
6908 (char*)&sqlite3_pager_writej_count, TCL_LINK_INT);
danielk19774b2688a2006-06-20 11:01:07 +00006909#ifndef SQLITE_OMIT_UTF16
drh7d9bd4e2006-02-16 18:16:36 +00006910 Tcl_LinkVar(interp, "unaligned_string_counter",
6911 (char*)&unaligned_string_counter, TCL_LINK_INT);
danielk19774b2688a2006-06-20 11:01:07 +00006912#endif
drh268803a2005-12-14 20:11:30 +00006913#ifndef SQLITE_OMIT_UTF16
6914 Tcl_LinkVar(interp, "sqlite_last_needed_collation",
6915 (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
6916#endif
danielk197729bafea2008-06-26 10:41:19 +00006917#if SQLITE_OS_WIN
drhc0929982005-09-05 19:08:29 +00006918 Tcl_LinkVar(interp, "sqlite_os_type",
mistachkin202cb642014-07-31 18:54:01 +00006919 (char*)&sqlite3_os_type, TCL_LINK_LONG);
drhc0929982005-09-05 19:08:29 +00006920#endif
drh549c8b62005-09-19 13:15:23 +00006921#ifdef SQLITE_TEST
drh6fa978d2013-05-30 19:29:19 +00006922 {
6923 static const char *query_plan = "*** OBSOLETE VARIABLE ***";
6924 Tcl_LinkVar(interp, "sqlite_query_plan",
6925 (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
6926 }
drh549c8b62005-09-19 13:15:23 +00006927#endif
drh8b3d9902005-08-19 00:14:42 +00006928#ifdef SQLITE_DEBUG
drh48083ce2005-09-19 12:37:27 +00006929 Tcl_LinkVar(interp, "sqlite_where_trace",
mlcreech3a00f902008-03-04 17:45:01 +00006930 (char*)&sqlite3WhereTrace, TCL_LINK_INT);
drh73be5012007-08-08 12:11:21 +00006931 Tcl_LinkVar(interp, "sqlite_os_trace",
mlcreech3a00f902008-03-04 17:45:01 +00006932 (char*)&sqlite3OSTrace, TCL_LINK_INT);
dan38e1a272010-06-28 11:23:09 +00006933#ifndef SQLITE_OMIT_WAL
drhc74c3332010-05-31 12:15:19 +00006934 Tcl_LinkVar(interp, "sqlite_wal_trace",
6935 (char*)&sqlite3WalTrace, TCL_LINK_INT);
drh8b3d9902005-08-19 00:14:42 +00006936#endif
dan38e1a272010-06-28 11:23:09 +00006937#endif
danielk1977cbe21be2005-06-07 07:58:48 +00006938#ifndef SQLITE_OMIT_DISKIO
drhaf6df112005-06-07 02:12:30 +00006939 Tcl_LinkVar(interp, "sqlite_opentemp_count",
6940 (char*)&sqlite3_opentemp_count, TCL_LINK_INT);
danielk1977cbe21be2005-06-07 07:58:48 +00006941#endif
drh7c972de2003-09-06 22:18:07 +00006942 Tcl_LinkVar(interp, "sqlite_static_bind_value",
6943 (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
drhf0313812006-09-04 15:53:53 +00006944 Tcl_LinkVar(interp, "sqlite_static_bind_nbyte",
6945 (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT);
drhab3f9fe2004-08-14 17:10:10 +00006946 Tcl_LinkVar(interp, "sqlite_temp_directory",
drheffd02b2004-08-29 23:42:13 +00006947 (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
mistachkina112d142012-03-14 00:44:01 +00006948 Tcl_LinkVar(interp, "sqlite_data_directory",
6949 (char*)&sqlite3_data_directory, TCL_LINK_STRING);
drh1398ad32005-01-19 23:24:50 +00006950 Tcl_LinkVar(interp, "bitmask_size",
6951 (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
drhb851b2c2005-03-10 14:11:12 +00006952 Tcl_LinkVar(interp, "sqlite_sync_count",
6953 (char*)&sqlite3_sync_count, TCL_LINK_INT);
6954 Tcl_LinkVar(interp, "sqlite_fullsync_count",
6955 (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
drhd1fa7bc2009-01-10 13:24:50 +00006956#if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST)
danielk197733e89032008-12-17 15:18:17 +00006957 Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses",
6958 (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT);
6959#endif
drhd1bf3512001-04-07 15:24:33 +00006960 return TCL_OK;
6961}