xref: /sqlite-3.40.0/src/test1.c (revision f71a243a)
1 /*
2 ** 2001 September 15
3 **
4 ** The author disclaims copyright to this source code.  In place of
5 ** a legal notice, here is a blessing:
6 **
7 **    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.
10 **
11 *************************************************************************
12 ** Code for testing all sorts of SQLite interfaces.  This code
13 ** is not included in the SQLite library.  It is used for automated
14 ** testing of the SQLite library.
15 */
16 #include "sqliteInt.h"
17 #if SQLITE_OS_WIN
18 #  include "os_win.h"
19 #endif
20 
21 #include "vdbeInt.h"
22 #if defined(INCLUDE_SQLITE_TCL_H)
23 #  include "sqlite_tcl.h"
24 #else
25 #  include "tcl.h"
26 #endif
27 #include <stdlib.h>
28 #include <string.h>
29 
30 /*
31 ** This is a copy of the first part of the SqliteDb structure in
32 ** tclsqlite.c.  We need it here so that the get_sqlite_pointer routine
33 ** can extract the sqlite3* pointer from an existing Tcl SQLite
34 ** connection.
35 */
36 struct SqliteDb {
37   sqlite3 *db;
38 };
39 
40 /*
41 ** Convert text generated by the "%p" conversion format back into
42 ** a pointer.
43 */
44 static int testHexToInt(int h){
45   if( h>='0' && h<='9' ){
46     return h - '0';
47   }else if( h>='a' && h<='f' ){
48     return h - 'a' + 10;
49   }else{
50     assert( h>='A' && h<='F' );
51     return h - 'A' + 10;
52   }
53 }
54 void *sqlite3TestTextToPtr(const char *z){
55   void *p;
56   u64 v;
57   u32 v2;
58   if( z[0]=='0' && z[1]=='x' ){
59     z += 2;
60   }
61   v = 0;
62   while( *z ){
63     v = (v<<4) + testHexToInt(*z);
64     z++;
65   }
66   if( sizeof(p)==sizeof(v) ){
67     memcpy(&p, &v, sizeof(p));
68   }else{
69     assert( sizeof(p)==sizeof(v2) );
70     v2 = (u32)v;
71     memcpy(&p, &v2, sizeof(p));
72   }
73   return p;
74 }
75 
76 
77 /*
78 ** A TCL command that returns the address of the sqlite* pointer
79 ** for an sqlite connection instance.  Bad things happen if the
80 ** input is not an sqlite connection.
81 */
82 static int SQLITE_TCLAPI get_sqlite_pointer(
83   void * clientData,
84   Tcl_Interp *interp,
85   int objc,
86   Tcl_Obj *CONST objv[]
87 ){
88   struct SqliteDb *p;
89   Tcl_CmdInfo cmdInfo;
90   char zBuf[100];
91   if( objc!=2 ){
92     Tcl_WrongNumArgs(interp, 1, objv, "SQLITE-CONNECTION");
93     return TCL_ERROR;
94   }
95   if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
96     Tcl_AppendResult(interp, "command not found: ",
97            Tcl_GetString(objv[1]), (char*)0);
98     return TCL_ERROR;
99   }
100   p = (struct SqliteDb*)cmdInfo.objClientData;
101   sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", p->db);
102   Tcl_AppendResult(interp, zBuf, 0);
103   return TCL_OK;
104 }
105 
106 /*
107 ** Decode a pointer to an sqlite3 object.
108 */
109 int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
110   struct SqliteDb *p;
111   Tcl_CmdInfo cmdInfo;
112   if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){
113     p = (struct SqliteDb*)cmdInfo.objClientData;
114     *ppDb = p->db;
115   }else{
116     *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA);
117   }
118   return TCL_OK;
119 }
120 
121 #if SQLITE_OS_WIN
122 /*
123 ** Decode a Win32 HANDLE object.
124 */
125 int getWin32Handle(Tcl_Interp *interp, const char *zA, LPHANDLE phFile){
126   *phFile = (HANDLE)sqlite3TestTextToPtr(zA);
127   return TCL_OK;
128 }
129 #endif
130 
131 extern const char *sqlite3ErrName(int);
132 #define t1ErrorName sqlite3ErrName
133 
134 /*
135 ** Convert an sqlite3_stmt* into an sqlite3*.  This depends on the
136 ** fact that the sqlite3* is the first field in the Vdbe structure.
137 */
138 #define StmtToDb(X)   sqlite3_db_handle(X)
139 
140 /*
141 ** Check a return value to make sure it agrees with the results
142 ** from sqlite3_errcode.
143 */
144 int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
145   if( sqlite3_threadsafe()==0 && rc!=SQLITE_MISUSE && rc!=SQLITE_OK
146    && sqlite3_errcode(db)!=rc ){
147     char zBuf[200];
148     int r2 = sqlite3_errcode(db);
149     sqlite3_snprintf(sizeof(zBuf), zBuf,
150        "error code %s (%d) does not match sqlite3_errcode %s (%d)",
151        t1ErrorName(rc), rc, t1ErrorName(r2), r2);
152     Tcl_ResetResult(interp);
153     Tcl_AppendResult(interp, zBuf, 0);
154     return 1;
155   }
156   return 0;
157 }
158 
159 /*
160 ** Decode a pointer to an sqlite3_stmt object.
161 */
162 static int getStmtPointer(
163   Tcl_Interp *interp,
164   const char *zArg,
165   sqlite3_stmt **ppStmt
166 ){
167   *ppStmt = (sqlite3_stmt*)sqlite3TestTextToPtr(zArg);
168   return TCL_OK;
169 }
170 
171 /*
172 ** Generate a text representation of a pointer that can be understood
173 ** by the getDbPointer and getVmPointer routines above.
174 **
175 ** The problem is, on some machines (Solaris) if you do a printf with
176 ** "%p" you cannot turn around and do a scanf with the same "%p" and
177 ** get your pointer back.  You have to prepend a "0x" before it will
178 ** work.  Or at least that is what is reported to me (drh).  But this
179 ** behavior varies from machine to machine.  The solution used her is
180 ** to test the string right after it is generated to see if it can be
181 ** understood by scanf, and if not, try prepending an "0x" to see if
182 ** that helps.  If nothing works, a fatal error is generated.
183 */
184 int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
185   sqlite3_snprintf(100, zPtr, "%p", p);
186   return TCL_OK;
187 }
188 
189 /*
190 ** The callback routine for sqlite3_exec_printf().
191 */
192 static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
193   Tcl_DString *str = (Tcl_DString*)pArg;
194   int i;
195 
196   if( Tcl_DStringLength(str)==0 ){
197     for(i=0; i<argc; i++){
198       Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
199     }
200   }
201   for(i=0; i<argc; i++){
202     Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
203   }
204   return 0;
205 }
206 
207 /*
208 ** The I/O tracing callback.
209 */
210 #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
211 static FILE *iotrace_file = 0;
212 static void io_trace_callback(const char *zFormat, ...){
213   va_list ap;
214   va_start(ap, zFormat);
215   vfprintf(iotrace_file, zFormat, ap);
216   va_end(ap);
217   fflush(iotrace_file);
218 }
219 #endif
220 
221 /*
222 ** Usage:  io_trace FILENAME
223 **
224 ** Turn I/O tracing on or off.  If FILENAME is not an empty string,
225 ** I/O tracing begins going into FILENAME. If FILENAME is an empty
226 ** string, I/O tracing is turned off.
227 */
228 static int SQLITE_TCLAPI test_io_trace(
229   void *NotUsed,
230   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
231   int argc,              /* Number of arguments */
232   char **argv            /* Text of each argument */
233 ){
234 #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
235   if( argc!=2 ){
236     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
237           " FILENAME\"", 0);
238     return TCL_ERROR;
239   }
240   if( iotrace_file ){
241     if( iotrace_file!=stdout && iotrace_file!=stderr ){
242       fclose(iotrace_file);
243     }
244     iotrace_file = 0;
245     sqlite3IoTrace = 0;
246   }
247   if( argv[1][0] ){
248     if( strcmp(argv[1],"stdout")==0 ){
249       iotrace_file = stdout;
250     }else if( strcmp(argv[1],"stderr")==0 ){
251       iotrace_file = stderr;
252     }else{
253       iotrace_file = fopen(argv[1], "w");
254     }
255     sqlite3IoTrace = io_trace_callback;
256   }
257 #endif
258   return TCL_OK;
259 }
260 
261 /*
262 ** Usage:  clang_sanitize_address
263 **
264 ** Returns true if the program was compiled using clang with the
265 ** -fsanitize=address switch on the command line. False otherwise.
266 **
267 ** Also return true if the OMIT_MISUSE environment variable exists.
268 */
269 static int SQLITE_TCLAPI clang_sanitize_address(
270   void *NotUsed,
271   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
272   int argc,              /* Number of arguments */
273   char **argv            /* Text of each argument */
274 ){
275   int res = 0;
276 #if defined(__has_feature)
277 # if __has_feature(address_sanitizer)
278   res = 1;
279 # endif
280 #endif
281 #ifdef __SANITIZE_ADDRESS__
282   res = 1;
283 #endif
284   if( res==0 && getenv("OMIT_MISUSE")!=0 ) res = 1;
285   Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
286   return TCL_OK;
287 }
288 
289 /*
290 ** Usage:  sqlite3_exec_printf  DB  FORMAT  STRING
291 **
292 ** Invoke the sqlite3_exec_printf() interface using the open database
293 ** DB.  The SQL is the string FORMAT.  The format string should contain
294 ** one %s or %q.  STRING is the value inserted into %s or %q.
295 */
296 static int SQLITE_TCLAPI test_exec_printf(
297   void *NotUsed,
298   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
299   int argc,              /* Number of arguments */
300   char **argv            /* Text of each argument */
301 ){
302   sqlite3 *db;
303   Tcl_DString str;
304   int rc;
305   char *zErr = 0;
306   char *zSql;
307   char zBuf[30];
308   if( argc!=4 ){
309     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
310        " DB FORMAT STRING", 0);
311     return TCL_ERROR;
312   }
313   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
314   Tcl_DStringInit(&str);
315   zSql = sqlite3_mprintf(argv[2], argv[3]);
316   rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
317   sqlite3_free(zSql);
318   sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
319   Tcl_AppendElement(interp, zBuf);
320   Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
321   Tcl_DStringFree(&str);
322   if( zErr ) sqlite3_free(zErr);
323   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
324   return TCL_OK;
325 }
326 
327 /*
328 ** Usage:  sqlite3_exec_hex  DB  HEX
329 **
330 ** Invoke the sqlite3_exec() on a string that is obtained by translating
331 ** HEX into ASCII.  Most characters are translated as is.  %HH becomes
332 ** a hex character.
333 */
334 static int SQLITE_TCLAPI test_exec_hex(
335   void *NotUsed,
336   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
337   int argc,              /* Number of arguments */
338   char **argv            /* Text of each argument */
339 ){
340   sqlite3 *db;
341   Tcl_DString str;
342   int rc, i, j;
343   char *zErr = 0;
344   char *zHex;
345   char zSql[501];
346   char zBuf[30];
347   if( argc!=3 ){
348     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
349        " DB HEX", 0);
350     return TCL_ERROR;
351   }
352   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
353   zHex = argv[2];
354   for(i=j=0; i<(sizeof(zSql)-1) && zHex[j]; i++, j++){
355     if( zHex[j]=='%' && zHex[j+2] && zHex[j+2] ){
356       zSql[i] = (testHexToInt(zHex[j+1])<<4) + testHexToInt(zHex[j+2]);
357       j += 2;
358     }else{
359       zSql[i] = zHex[j];
360     }
361   }
362   zSql[i] = 0;
363   Tcl_DStringInit(&str);
364   rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
365   sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
366   Tcl_AppendElement(interp, zBuf);
367   Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
368   Tcl_DStringFree(&str);
369   if( zErr ) sqlite3_free(zErr);
370   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
371   return TCL_OK;
372 }
373 
374 /*
375 ** Usage:  db_enter DB
376 **         db_leave DB
377 **
378 ** Enter or leave the mutex on a database connection.
379 */
380 static int SQLITE_TCLAPI db_enter(
381   void *NotUsed,
382   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
383   int argc,              /* Number of arguments */
384   char **argv            /* Text of each argument */
385 ){
386   sqlite3 *db;
387   if( argc!=2 ){
388     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
389        " DB", 0);
390     return TCL_ERROR;
391   }
392   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
393   sqlite3_mutex_enter(db->mutex);
394   return TCL_OK;
395 }
396 static int SQLITE_TCLAPI db_leave(
397   void *NotUsed,
398   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
399   int argc,              /* Number of arguments */
400   char **argv            /* Text of each argument */
401 ){
402   sqlite3 *db;
403   if( argc!=2 ){
404     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
405        " DB", 0);
406     return TCL_ERROR;
407   }
408   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
409   sqlite3_mutex_leave(db->mutex);
410   return TCL_OK;
411 }
412 
413 /*
414 ** Usage:  sqlite3_exec  DB  SQL
415 **
416 ** Invoke the sqlite3_exec interface using the open database DB
417 */
418 static int SQLITE_TCLAPI test_exec(
419   void *NotUsed,
420   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
421   int argc,              /* Number of arguments */
422   char **argv            /* Text of each argument */
423 ){
424   sqlite3 *db;
425   Tcl_DString str;
426   int rc;
427   char *zErr = 0;
428   char *zSql;
429   int i, j;
430   char zBuf[30];
431   if( argc!=3 ){
432     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
433        " DB SQL", 0);
434     return TCL_ERROR;
435   }
436   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
437   Tcl_DStringInit(&str);
438   zSql = sqlite3_mprintf("%s", argv[2]);
439   for(i=j=0; zSql[i];){
440     if( zSql[i]=='%' ){
441       zSql[j++] = (testHexToInt(zSql[i+1])<<4) + testHexToInt(zSql[i+2]);
442       i += 3;
443     }else{
444       zSql[j++] = zSql[i++];
445     }
446   }
447   zSql[j] = 0;
448   rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
449   sqlite3_free(zSql);
450   sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
451   Tcl_AppendElement(interp, zBuf);
452   Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
453   Tcl_DStringFree(&str);
454   if( zErr ) sqlite3_free(zErr);
455   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
456   return TCL_OK;
457 }
458 
459 /*
460 ** Usage:  sqlite3_exec_nr  DB  SQL
461 **
462 ** Invoke the sqlite3_exec interface using the open database DB.  Discard
463 ** all results
464 */
465 static int SQLITE_TCLAPI test_exec_nr(
466   void *NotUsed,
467   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
468   int argc,              /* Number of arguments */
469   char **argv            /* Text of each argument */
470 ){
471   sqlite3 *db;
472   int rc;
473   char *zErr = 0;
474   if( argc!=3 ){
475     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
476        " DB SQL", 0);
477     return TCL_ERROR;
478   }
479   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
480   rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
481   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
482   return TCL_OK;
483 }
484 
485 /*
486 ** Usage:  sqlite3_mprintf_z_test  SEPARATOR  ARG0  ARG1 ...
487 **
488 ** Test the %z format of sqlite_mprintf().  Use multiple mprintf() calls to
489 ** concatenate arg0 through argn using separator as the separator.
490 ** Return the result.
491 */
492 static int SQLITE_TCLAPI test_mprintf_z(
493   void *NotUsed,
494   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
495   int argc,              /* Number of arguments */
496   char **argv            /* Text of each argument */
497 ){
498   char *zResult = 0;
499   int i;
500 
501   for(i=2; i<argc && (i==2 || zResult); i++){
502     zResult = sqlite3_mprintf("%z%s%s", zResult, argv[1], argv[i]);
503   }
504   Tcl_AppendResult(interp, zResult, 0);
505   sqlite3_free(zResult);
506   return TCL_OK;
507 }
508 
509 /*
510 ** Usage:  sqlite3_mprintf_n_test  STRING
511 **
512 ** Test the %n format of sqlite_mprintf().  Return the length of the
513 ** input string.
514 */
515 static int SQLITE_TCLAPI test_mprintf_n(
516   void *NotUsed,
517   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
518   int argc,              /* Number of arguments */
519   char **argv            /* Text of each argument */
520 ){
521   char *zStr;
522   int n = 0;
523   zStr = sqlite3_mprintf("%s%n", argv[1], &n);
524   sqlite3_free(zStr);
525   Tcl_SetObjResult(interp, Tcl_NewIntObj(n));
526   return TCL_OK;
527 }
528 
529 /*
530 ** Usage:  sqlite3_snprintf_int  SIZE FORMAT  INT
531 **
532 ** Test the of sqlite3_snprintf() routine.  SIZE is the size of the
533 ** output buffer in bytes.  The maximum size is 100.  FORMAT is the
534 ** format string.  INT is a single integer argument.  The FORMAT
535 ** string must require no more than this one integer argument.  If
536 ** You pass in a format string that requires more than one argument,
537 ** bad things will happen.
538 */
539 static int SQLITE_TCLAPI test_snprintf_int(
540   void *NotUsed,
541   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
542   int argc,              /* Number of arguments */
543   char **argv            /* Text of each argument */
544 ){
545   char zStr[100];
546   int n = atoi(argv[1]);
547   const char *zFormat = argv[2];
548   int a1 = atoi(argv[3]);
549   if( n>sizeof(zStr) ) n = sizeof(zStr);
550   sqlite3_snprintf(sizeof(zStr), zStr, "abcdefghijklmnopqrstuvwxyz");
551   sqlite3_snprintf(n, zStr, zFormat, a1);
552   Tcl_AppendResult(interp, zStr, 0);
553   return TCL_OK;
554 }
555 
556 #ifndef SQLITE_OMIT_GET_TABLE
557 
558 /*
559 ** Usage:  sqlite3_get_table_printf  DB  FORMAT  STRING  ?--no-counts?
560 **
561 ** Invoke the sqlite3_get_table_printf() interface using the open database
562 ** DB.  The SQL is the string FORMAT.  The format string should contain
563 ** one %s or %q.  STRING is the value inserted into %s or %q.
564 */
565 static int SQLITE_TCLAPI test_get_table_printf(
566   void *NotUsed,
567   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
568   int argc,              /* Number of arguments */
569   char **argv            /* Text of each argument */
570 ){
571   sqlite3 *db;
572   Tcl_DString str;
573   int rc;
574   char *zErr = 0;
575   int nRow = 0, nCol = 0;
576   char **aResult;
577   int i;
578   char zBuf[30];
579   char *zSql;
580   int resCount = -1;
581   if( argc==5 ){
582     if( Tcl_GetInt(interp, argv[4], &resCount) ) return TCL_ERROR;
583   }
584   if( argc!=4 && argc!=5 ){
585     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
586        " DB FORMAT STRING ?COUNT?", 0);
587     return TCL_ERROR;
588   }
589   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
590   Tcl_DStringInit(&str);
591   zSql = sqlite3_mprintf(argv[2],argv[3]);
592   if( argc==5 ){
593     rc = sqlite3_get_table(db, zSql, &aResult, 0, 0, &zErr);
594   }else{
595     rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
596     resCount = (nRow+1)*nCol;
597   }
598   sqlite3_free(zSql);
599   sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
600   Tcl_AppendElement(interp, zBuf);
601   if( rc==SQLITE_OK ){
602     if( argc==4 ){
603       sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nRow);
604       Tcl_AppendElement(interp, zBuf);
605       sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nCol);
606       Tcl_AppendElement(interp, zBuf);
607     }
608     for(i=0; i<resCount; i++){
609       Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
610     }
611   }else{
612     Tcl_AppendElement(interp, zErr);
613   }
614   sqlite3_free_table(aResult);
615   if( zErr ) sqlite3_free(zErr);
616   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
617   return TCL_OK;
618 }
619 
620 #endif /* SQLITE_OMIT_GET_TABLE */
621 
622 
623 /*
624 ** Usage:  sqlite3_last_insert_rowid DB
625 **
626 ** Returns the integer ROWID of the most recent insert.
627 */
628 static int SQLITE_TCLAPI test_last_rowid(
629   void *NotUsed,
630   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
631   int argc,              /* Number of arguments */
632   char **argv            /* Text of each argument */
633 ){
634   sqlite3 *db;
635   char zBuf[30];
636 
637   if( argc!=2 ){
638     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
639     return TCL_ERROR;
640   }
641   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
642   sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", sqlite3_last_insert_rowid(db));
643   Tcl_AppendResult(interp, zBuf, 0);
644   return SQLITE_OK;
645 }
646 
647 /*
648 ** Usage:  sqlite3_key DB KEY
649 **
650 ** Set the codec key.
651 */
652 static int SQLITE_TCLAPI test_key(
653   void *NotUsed,
654   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
655   int argc,              /* Number of arguments */
656   char **argv            /* Text of each argument */
657 ){
658 #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
659   sqlite3 *db;
660   const char *zKey;
661   int nKey;
662   if( argc!=3 ){
663     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
664        " FILENAME\"", 0);
665     return TCL_ERROR;
666   }
667   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
668   zKey = argv[2];
669   nKey = strlen(zKey);
670   sqlite3_key(db, zKey, nKey);
671 #endif
672   return TCL_OK;
673 }
674 
675 /*
676 ** Usage:  sqlite3_rekey DB KEY
677 **
678 ** Change the codec key.
679 */
680 static int SQLITE_TCLAPI test_rekey(
681   void *NotUsed,
682   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
683   int argc,              /* Number of arguments */
684   char **argv            /* Text of each argument */
685 ){
686 #ifdef SQLITE_HAS_CODEC
687   sqlite3 *db;
688   const char *zKey;
689   int nKey;
690   if( argc!=3 ){
691     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
692        " FILENAME\"", 0);
693     return TCL_ERROR;
694   }
695   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
696   zKey = argv[2];
697   nKey = strlen(zKey);
698   sqlite3_rekey(db, zKey, nKey);
699 #endif
700   return TCL_OK;
701 }
702 
703 /*
704 ** Usage:  sqlite3_close DB
705 **
706 ** Closes the database opened by sqlite3_open.
707 */
708 static int SQLITE_TCLAPI sqlite_test_close(
709   void *NotUsed,
710   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
711   int argc,              /* Number of arguments */
712   char **argv            /* Text of each argument */
713 ){
714   sqlite3 *db;
715   int rc;
716   if( argc!=2 ){
717     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
718        " FILENAME\"", 0);
719     return TCL_ERROR;
720   }
721   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
722   rc = sqlite3_close(db);
723   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
724   return TCL_OK;
725 }
726 
727 /*
728 ** Usage:  sqlite3_close_v2 DB
729 **
730 ** Closes the database opened by sqlite3_open.
731 */
732 static int SQLITE_TCLAPI sqlite_test_close_v2(
733   void *NotUsed,
734   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
735   int argc,              /* Number of arguments */
736   char **argv            /* Text of each argument */
737 ){
738   sqlite3 *db;
739   int rc;
740   if( argc!=2 ){
741     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
742        " FILENAME\"", 0);
743     return TCL_ERROR;
744   }
745   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
746   rc = sqlite3_close_v2(db);
747   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
748   return TCL_OK;
749 }
750 
751 /*
752 ** Implementation of the x_coalesce() function.
753 ** Return the first argument non-NULL argument.
754 */
755 static void t1_ifnullFunc(
756   sqlite3_context *context,
757   int argc,
758   sqlite3_value **argv
759 ){
760   int i;
761   for(i=0; i<argc; i++){
762     if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
763       int n = sqlite3_value_bytes(argv[i]);
764       sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]),
765           n, SQLITE_TRANSIENT);
766       break;
767     }
768   }
769 }
770 
771 /*
772 ** These are test functions.    hex8() interprets its argument as
773 ** UTF8 and returns a hex encoding.  hex16le() interprets its argument
774 ** as UTF16le and returns a hex encoding.
775 */
776 static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){
777   const unsigned char *z;
778   int i;
779   char zBuf[200];
780   z = sqlite3_value_text(argv[0]);
781   for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){
782     sqlite3_snprintf(sizeof(zBuf)-i*2, &zBuf[i*2], "%02x", z[i]);
783   }
784   zBuf[i*2] = 0;
785   sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
786 }
787 #ifndef SQLITE_OMIT_UTF16
788 static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){
789   const unsigned short int *z;
790   int i;
791   char zBuf[400];
792   z = sqlite3_value_text16(argv[0]);
793   for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){
794     sqlite3_snprintf(sizeof(zBuf)-i*4, &zBuf[i*4],"%04x", z[i]&0xff);
795   }
796   zBuf[i*4] = 0;
797   sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
798 }
799 #endif
800 
801 /*
802 ** A structure into which to accumulate text.
803 */
804 struct dstr {
805   int nAlloc;  /* Space allocated */
806   int nUsed;   /* Space used */
807   char *z;     /* The space */
808 };
809 
810 /*
811 ** Append text to a dstr
812 */
813 static void dstrAppend(struct dstr *p, const char *z, int divider){
814   int n = (int)strlen(z);
815   if( p->nUsed + n + 2 > p->nAlloc ){
816     char *zNew;
817     p->nAlloc = p->nAlloc*2 + n + 200;
818     zNew = sqlite3_realloc(p->z, p->nAlloc);
819     if( zNew==0 ){
820       sqlite3_free(p->z);
821       memset(p, 0, sizeof(*p));
822       return;
823     }
824     p->z = zNew;
825   }
826   if( divider && p->nUsed>0 ){
827     p->z[p->nUsed++] = divider;
828   }
829   memcpy(&p->z[p->nUsed], z, n+1);
830   p->nUsed += n;
831 }
832 
833 /*
834 ** Invoked for each callback from sqlite3ExecFunc
835 */
836 static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
837   struct dstr *p = (struct dstr*)pData;
838   int i;
839   for(i=0; i<argc; i++){
840     if( argv[i]==0 ){
841       dstrAppend(p, "NULL", ' ');
842     }else{
843       dstrAppend(p, argv[i], ' ');
844     }
845   }
846   return 0;
847 }
848 
849 /*
850 ** Implementation of the x_sqlite_exec() function.  This function takes
851 ** a single argument and attempts to execute that argument as SQL code.
852 ** This is illegal and should set the SQLITE_MISUSE flag on the database.
853 **
854 ** 2004-Jan-07:  We have changed this to make it legal to call sqlite3_exec()
855 ** from within a function call.
856 **
857 ** This routine simulates the effect of having two threads attempt to
858 ** use the same database at the same time.
859 */
860 static void sqlite3ExecFunc(
861   sqlite3_context *context,
862   int argc,
863   sqlite3_value **argv
864 ){
865   struct dstr x;
866   memset(&x, 0, sizeof(x));
867   (void)sqlite3_exec((sqlite3*)sqlite3_user_data(context),
868       (char*)sqlite3_value_text(argv[0]),
869       execFuncCallback, &x, 0);
870   sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
871   sqlite3_free(x.z);
872 }
873 
874 /*
875 ** Implementation of tkt2213func(), a scalar function that takes exactly
876 ** one argument. It has two interesting features:
877 **
878 ** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*.
879 **   If the three pointers returned are not the same an SQL error is raised.
880 **
881 ** * Otherwise it returns a copy of the text representation of its
882 **   argument in such a way as the VDBE representation is a Mem* cell
883 **   with the MEM_Term flag clear.
884 **
885 ** Ticket #2213 can therefore be tested by evaluating the following
886 ** SQL expression:
887 **
888 **   tkt2213func(tkt2213func('a string'));
889 */
890 static void tkt2213Function(
891   sqlite3_context *context,
892   int argc,
893   sqlite3_value **argv
894 ){
895   int nText;
896   unsigned char const *zText1;
897   unsigned char const *zText2;
898   unsigned char const *zText3;
899 
900   nText = sqlite3_value_bytes(argv[0]);
901   zText1 = sqlite3_value_text(argv[0]);
902   zText2 = sqlite3_value_text(argv[0]);
903   zText3 = sqlite3_value_text(argv[0]);
904 
905   if( zText1!=zText2 || zText2!=zText3 ){
906     sqlite3_result_error(context, "tkt2213 is not fixed", -1);
907   }else{
908     char *zCopy = (char *)sqlite3_malloc(nText);
909     memcpy(zCopy, zText1, nText);
910     sqlite3_result_text(context, zCopy, nText, sqlite3_free);
911   }
912 }
913 
914 /*
915 ** The following SQL function takes 4 arguments.  The 2nd and
916 ** 4th argument must be one of these strings:  'text', 'text16',
917 ** or 'blob' corresponding to API functions
918 **
919 **      sqlite3_value_text()
920 **      sqlite3_value_text16()
921 **      sqlite3_value_blob()
922 **
923 ** The third argument is a string, either 'bytes' or 'bytes16' or 'noop',
924 ** corresponding to APIs:
925 **
926 **      sqlite3_value_bytes()
927 **      sqlite3_value_bytes16()
928 **      noop
929 **
930 ** The APIs designated by the 2nd through 4th arguments are applied
931 ** to the first argument in order.  If the pointers returned by the
932 ** second and fourth are different, this routine returns 1.  Otherwise,
933 ** this routine returns 0.
934 **
935 ** This function is used to test to see when returned pointers from
936 ** the _text(), _text16() and _blob() APIs become invalidated.
937 */
938 static void ptrChngFunction(
939   sqlite3_context *context,
940   int argc,
941   sqlite3_value **argv
942 ){
943   const void *p1, *p2;
944   const char *zCmd;
945   if( argc!=4 ) return;
946   zCmd = (const char*)sqlite3_value_text(argv[1]);
947   if( zCmd==0 ) return;
948   if( strcmp(zCmd,"text")==0 ){
949     p1 = (const void*)sqlite3_value_text(argv[0]);
950 #ifndef SQLITE_OMIT_UTF16
951   }else if( strcmp(zCmd, "text16")==0 ){
952     p1 = (const void*)sqlite3_value_text16(argv[0]);
953 #endif
954   }else if( strcmp(zCmd, "blob")==0 ){
955     p1 = (const void*)sqlite3_value_blob(argv[0]);
956   }else{
957     return;
958   }
959   zCmd = (const char*)sqlite3_value_text(argv[2]);
960   if( zCmd==0 ) return;
961   if( strcmp(zCmd,"bytes")==0 ){
962     sqlite3_value_bytes(argv[0]);
963 #ifndef SQLITE_OMIT_UTF16
964   }else if( strcmp(zCmd, "bytes16")==0 ){
965     sqlite3_value_bytes16(argv[0]);
966 #endif
967   }else if( strcmp(zCmd, "noop")==0 ){
968     /* do nothing */
969   }else{
970     return;
971   }
972   zCmd = (const char*)sqlite3_value_text(argv[3]);
973   if( zCmd==0 ) return;
974   if( strcmp(zCmd,"text")==0 ){
975     p2 = (const void*)sqlite3_value_text(argv[0]);
976 #ifndef SQLITE_OMIT_UTF16
977   }else if( strcmp(zCmd, "text16")==0 ){
978     p2 = (const void*)sqlite3_value_text16(argv[0]);
979 #endif
980   }else if( strcmp(zCmd, "blob")==0 ){
981     p2 = (const void*)sqlite3_value_blob(argv[0]);
982   }else{
983     return;
984   }
985   sqlite3_result_int(context, p1!=p2);
986 }
987 
988 /*
989 ** This SQL function returns a different answer each time it is called, even if
990 ** the arguments are the same.
991 */
992 static void nondeterministicFunction(
993   sqlite3_context *context,
994   int argc,
995   sqlite3_value **argv
996 ){
997   static int cnt = 0;
998   sqlite3_result_int(context, cnt++);
999 }
1000 
1001 /*
1002 ** This SQL function returns the integer value of its argument as a MEM_IntReal
1003 ** value.
1004 */
1005 static void intrealFunction(
1006   sqlite3_context *context,
1007   int argc,
1008   sqlite3_value **argv
1009 ){
1010   sqlite3_int64 v = sqlite3_value_int64(argv[0]);
1011   sqlite3_result_int64(context, v);
1012   sqlite3_test_control(SQLITE_TESTCTRL_RESULT_INTREAL, context);
1013 }
1014 
1015 /*
1016 ** Usage:  sqlite3_create_function DB
1017 **
1018 ** Call the sqlite3_create_function API on the given database in order
1019 ** to create a function named "x_coalesce".  This function does the same thing
1020 ** as the "coalesce" function.  This function also registers an SQL function
1021 ** named "x_sqlite_exec" that invokes sqlite3_exec().  Invoking sqlite3_exec()
1022 ** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
1023 ** The effect is similar to trying to use the same database connection from
1024 ** two threads at the same time.
1025 **
1026 ** The original motivation for this routine was to be able to call the
1027 ** sqlite3_create_function function while a query is in progress in order
1028 ** to test the SQLITE_MISUSE detection logic.
1029 */
1030 static int SQLITE_TCLAPI test_create_function(
1031   void *NotUsed,
1032   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1033   int argc,              /* Number of arguments */
1034   char **argv            /* Text of each argument */
1035 ){
1036   int rc;
1037   sqlite3 *db;
1038 
1039   if( argc!=2 ){
1040     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1041        " DB\"", 0);
1042     return TCL_ERROR;
1043   }
1044   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
1045   rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_UTF8, 0,
1046         t1_ifnullFunc, 0, 0);
1047   if( rc==SQLITE_OK ){
1048     rc = sqlite3_create_function(db, "hex8", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
1049           0, hex8Func, 0, 0);
1050   }
1051 #ifndef SQLITE_OMIT_UTF16
1052   if( rc==SQLITE_OK ){
1053     rc = sqlite3_create_function(db, "hex16", 1, SQLITE_UTF16 | SQLITE_DETERMINISTIC,
1054           0, hex16Func, 0, 0);
1055   }
1056 #endif
1057   if( rc==SQLITE_OK ){
1058     rc = sqlite3_create_function(db, "tkt2213func", 1, SQLITE_ANY, 0,
1059           tkt2213Function, 0, 0);
1060   }
1061   if( rc==SQLITE_OK ){
1062     rc = sqlite3_create_function(db, "pointer_change", 4, SQLITE_ANY, 0,
1063           ptrChngFunction, 0, 0);
1064   }
1065 
1066   /* Functions counter1() and counter2() have the same implementation - they
1067   ** both return an ascending integer with each call.  But counter1() is marked
1068   ** as non-deterministic and counter2() is marked as deterministic.
1069   */
1070   if( rc==SQLITE_OK ){
1071     rc = sqlite3_create_function(db, "counter1", -1, SQLITE_UTF8,
1072           0, nondeterministicFunction, 0, 0);
1073   }
1074   if( rc==SQLITE_OK ){
1075     rc = sqlite3_create_function(db, "counter2", -1, SQLITE_UTF8|SQLITE_DETERMINISTIC,
1076           0, nondeterministicFunction, 0, 0);
1077   }
1078 
1079   /* The intreal() function converts its argument to an integer and returns
1080   ** it as a MEM_IntReal.
1081   */
1082   if( rc==SQLITE_OK ){
1083     rc = sqlite3_create_function(db, "intreal", 1, SQLITE_UTF8,
1084           0, intrealFunction, 0, 0);
1085   }
1086 
1087 #ifndef SQLITE_OMIT_UTF16
1088   /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
1089   ** because it is not tested anywhere else. */
1090   if( rc==SQLITE_OK ){
1091     const void *zUtf16;
1092     sqlite3_value *pVal;
1093     sqlite3_mutex_enter(db->mutex);
1094     pVal = sqlite3ValueNew(db);
1095     sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
1096     zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
1097     if( db->mallocFailed ){
1098       rc = SQLITE_NOMEM;
1099     }else{
1100       rc = sqlite3_create_function16(db, zUtf16,
1101                 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
1102     }
1103     sqlite3ValueFree(pVal);
1104     sqlite3_mutex_leave(db->mutex);
1105   }
1106 #endif
1107 
1108   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
1109   Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
1110   return TCL_OK;
1111 }
1112 
1113 /*
1114 ** Routines to implement the x_count() aggregate function.
1115 **
1116 ** x_count() counts the number of non-null arguments.  But there are
1117 ** some twists for testing purposes.
1118 **
1119 ** If the argument to x_count() is 40 then a UTF-8 error is reported
1120 ** on the step function.  If x_count(41) is seen, then a UTF-16 error
1121 ** is reported on the step function.  If the total count is 42, then
1122 ** a UTF-8 error is reported on the finalize function.
1123 */
1124 typedef struct t1CountCtx t1CountCtx;
1125 struct t1CountCtx {
1126   int n;
1127 };
1128 static void t1CountStep(
1129   sqlite3_context *context,
1130   int argc,
1131   sqlite3_value **argv
1132 ){
1133   t1CountCtx *p;
1134   p = sqlite3_aggregate_context(context, sizeof(*p));
1135   if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
1136     p->n++;
1137   }
1138   if( argc>0 ){
1139     int v = sqlite3_value_int(argv[0]);
1140     if( v==40 ){
1141       sqlite3_result_error(context, "value of 40 handed to x_count", -1);
1142 #ifndef SQLITE_OMIT_UTF16
1143     }else if( v==41 ){
1144       const char zUtf16ErrMsg[] = { 0, 0x61, 0, 0x62, 0, 0x63, 0, 0, 0};
1145       sqlite3_result_error16(context, &zUtf16ErrMsg[1-SQLITE_BIGENDIAN], -1);
1146 #endif
1147     }
1148   }
1149 }
1150 static void t1CountFinalize(sqlite3_context *context){
1151   t1CountCtx *p;
1152   p = sqlite3_aggregate_context(context, sizeof(*p));
1153   if( p ){
1154     if( p->n==42 ){
1155       sqlite3_result_error(context, "x_count totals to 42", -1);
1156     }else{
1157       sqlite3_result_int(context, p ? p->n : 0);
1158     }
1159   }
1160 }
1161 
1162 #ifndef SQLITE_OMIT_DEPRECATED
1163 static void legacyCountStep(
1164   sqlite3_context *context,
1165   int argc,
1166   sqlite3_value **argv
1167 ){
1168   /* no-op */
1169 }
1170 
1171 static void legacyCountFinalize(sqlite3_context *context){
1172   sqlite3_result_int(context, sqlite3_aggregate_count(context));
1173 }
1174 #endif
1175 
1176 /*
1177 ** Usage:  sqlite3_create_aggregate DB
1178 **
1179 ** Call the sqlite3_create_function API on the given database in order
1180 ** to create a function named "x_count".  This function is similar
1181 ** to the built-in count() function, with a few special quirks
1182 ** for testing the sqlite3_result_error() APIs.
1183 **
1184 ** The original motivation for this routine was to be able to call the
1185 ** sqlite3_create_aggregate function while a query is in progress in order
1186 ** to test the SQLITE_MISUSE detection logic.  See misuse.test.
1187 **
1188 ** This routine was later extended to test the use of sqlite3_result_error()
1189 ** within aggregate functions.
1190 **
1191 ** Later: It is now also extended to register the aggregate function
1192 ** "legacy_count()" with the supplied database handle. This is used
1193 ** to test the deprecated sqlite3_aggregate_count() API.
1194 */
1195 static int SQLITE_TCLAPI test_create_aggregate(
1196   void *NotUsed,
1197   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1198   int argc,              /* Number of arguments */
1199   char **argv            /* Text of each argument */
1200 ){
1201   sqlite3 *db;
1202   int rc;
1203   if( argc!=2 ){
1204     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1205        " FILENAME\"", 0);
1206     return TCL_ERROR;
1207   }
1208   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
1209   rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
1210       t1CountStep,t1CountFinalize);
1211   if( rc==SQLITE_OK ){
1212     rc = sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
1213         t1CountStep,t1CountFinalize);
1214   }
1215 #ifndef SQLITE_OMIT_DEPRECATED
1216   if( rc==SQLITE_OK ){
1217     rc = sqlite3_create_function(db, "legacy_count", 0, SQLITE_ANY, 0, 0,
1218         legacyCountStep, legacyCountFinalize
1219     );
1220   }
1221 #endif
1222   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
1223   Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
1224   return TCL_OK;
1225 }
1226 
1227 
1228 /*
1229 ** Usage:  printf TEXT
1230 **
1231 ** Send output to printf.  Use this rather than puts to merge the output
1232 ** in the correct sequence with debugging printfs inserted into C code.
1233 ** Puts uses a separate buffer and debugging statements will be out of
1234 ** sequence if it is used.
1235 */
1236 static int SQLITE_TCLAPI test_printf(
1237   void *NotUsed,
1238   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1239   int argc,              /* Number of arguments */
1240   char **argv            /* Text of each argument */
1241 ){
1242   if( argc!=2 ){
1243     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1244        " TEXT\"", 0);
1245     return TCL_ERROR;
1246   }
1247   printf("%s\n", argv[1]);
1248   return TCL_OK;
1249 }
1250 
1251 
1252 
1253 /*
1254 ** Usage:  sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
1255 **
1256 ** Call mprintf with three integer arguments
1257 */
1258 static int SQLITE_TCLAPI sqlite3_mprintf_int(
1259   void *NotUsed,
1260   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1261   int argc,              /* Number of arguments */
1262   char **argv            /* Text of each argument */
1263 ){
1264   int a[3], i;
1265   char *z;
1266   if( argc!=5 ){
1267     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1268        " FORMAT INT INT INT\"", 0);
1269     return TCL_ERROR;
1270   }
1271   for(i=2; i<5; i++){
1272     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
1273   }
1274   z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
1275   Tcl_AppendResult(interp, z, 0);
1276   sqlite3_free(z);
1277   return TCL_OK;
1278 }
1279 
1280 /*
1281 ** Usage:  sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
1282 **
1283 ** Call mprintf with three 64-bit integer arguments
1284 */
1285 static int SQLITE_TCLAPI sqlite3_mprintf_int64(
1286   void *NotUsed,
1287   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1288   int argc,              /* Number of arguments */
1289   char **argv            /* Text of each argument */
1290 ){
1291   int i;
1292   sqlite_int64 a[3];
1293   char *z;
1294   if( argc!=5 ){
1295     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1296        " FORMAT INT INT INT\"", 0);
1297     return TCL_ERROR;
1298   }
1299   for(i=2; i<5; i++){
1300     if( sqlite3Atoi64(argv[i], &a[i-2], sqlite3Strlen30(argv[i]), SQLITE_UTF8) ){
1301       Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
1302       return TCL_ERROR;
1303     }
1304   }
1305   z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
1306   Tcl_AppendResult(interp, z, 0);
1307   sqlite3_free(z);
1308   return TCL_OK;
1309 }
1310 
1311 /*
1312 ** Usage:  sqlite3_mprintf_long FORMAT INTEGER INTEGER INTEGER
1313 **
1314 ** Call mprintf with three long integer arguments.   This might be the
1315 ** same as sqlite3_mprintf_int or sqlite3_mprintf_int64, depending on
1316 ** platform.
1317 */
1318 static int SQLITE_TCLAPI sqlite3_mprintf_long(
1319   void *NotUsed,
1320   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1321   int argc,              /* Number of arguments */
1322   char **argv            /* Text of each argument */
1323 ){
1324   int i;
1325   long int a[3];
1326   int b[3];
1327   char *z;
1328   if( argc!=5 ){
1329     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1330        " FORMAT INT INT INT\"", 0);
1331     return TCL_ERROR;
1332   }
1333   for(i=2; i<5; i++){
1334     if( Tcl_GetInt(interp, argv[i], &b[i-2]) ) return TCL_ERROR;
1335     a[i-2] = (long int)b[i-2];
1336     a[i-2] &= (((u64)1)<<(sizeof(int)*8))-1;
1337   }
1338   z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
1339   Tcl_AppendResult(interp, z, 0);
1340   sqlite3_free(z);
1341   return TCL_OK;
1342 }
1343 
1344 /*
1345 ** Usage:  sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
1346 **
1347 ** Call mprintf with two integer arguments and one string argument
1348 */
1349 static int SQLITE_TCLAPI sqlite3_mprintf_str(
1350   void *NotUsed,
1351   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1352   int argc,              /* Number of arguments */
1353   char **argv            /* Text of each argument */
1354 ){
1355   int a[3], i;
1356   char *z;
1357   if( argc<4 || argc>5 ){
1358     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1359        " FORMAT INT INT ?STRING?\"", 0);
1360     return TCL_ERROR;
1361   }
1362   for(i=2; i<4; i++){
1363     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
1364   }
1365   z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
1366   Tcl_AppendResult(interp, z, 0);
1367   sqlite3_free(z);
1368   return TCL_OK;
1369 }
1370 
1371 /*
1372 ** Usage:  sqlite3_snprintf_str INTEGER FORMAT INTEGER INTEGER STRING
1373 **
1374 ** Call mprintf with two integer arguments and one string argument
1375 */
1376 static int SQLITE_TCLAPI sqlite3_snprintf_str(
1377   void *NotUsed,
1378   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1379   int argc,              /* Number of arguments */
1380   char **argv            /* Text of each argument */
1381 ){
1382   int a[3], i;
1383   int n;
1384   char *z;
1385   if( argc<5 || argc>6 ){
1386     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1387        " INT FORMAT INT INT ?STRING?\"", 0);
1388     return TCL_ERROR;
1389   }
1390   if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
1391   if( n<0 ){
1392     Tcl_AppendResult(interp, "N must be non-negative", 0);
1393     return TCL_ERROR;
1394   }
1395   for(i=3; i<5; i++){
1396     if( Tcl_GetInt(interp, argv[i], &a[i-3]) ) return TCL_ERROR;
1397   }
1398   z = sqlite3_malloc( n+1 );
1399   sqlite3_snprintf(n, z, argv[2], a[0], a[1], argc>4 ? argv[5] : NULL);
1400   Tcl_AppendResult(interp, z, 0);
1401   sqlite3_free(z);
1402   return TCL_OK;
1403 }
1404 
1405 /*
1406 ** Usage:  sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE
1407 **
1408 ** Call mprintf with two integer arguments and one double argument
1409 */
1410 static int SQLITE_TCLAPI sqlite3_mprintf_double(
1411   void *NotUsed,
1412   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1413   int argc,              /* Number of arguments */
1414   char **argv            /* Text of each argument */
1415 ){
1416   int a[3], i;
1417   double r;
1418   char *z;
1419   if( argc!=5 ){
1420     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1421        " FORMAT INT INT DOUBLE\"", 0);
1422     return TCL_ERROR;
1423   }
1424   for(i=2; i<4; i++){
1425     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
1426   }
1427   if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
1428   z = sqlite3_mprintf(argv[1], a[0], a[1], r);
1429   Tcl_AppendResult(interp, z, 0);
1430   sqlite3_free(z);
1431   return TCL_OK;
1432 }
1433 
1434 /*
1435 ** Usage:  sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE
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 */
1441 static int SQLITE_TCLAPI sqlite3_mprintf_scaled(
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   int i;
1448   double r[2];
1449   char *z;
1450   if( argc!=4 ){
1451     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1452        " FORMAT DOUBLE DOUBLE\"", 0);
1453     return TCL_ERROR;
1454   }
1455   for(i=2; i<4; i++){
1456     if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
1457   }
1458   z = sqlite3_mprintf(argv[1], r[0]*r[1]);
1459   Tcl_AppendResult(interp, z, 0);
1460   sqlite3_free(z);
1461   return TCL_OK;
1462 }
1463 
1464 /*
1465 ** Usage:  sqlite3_mprintf_stronly FORMAT STRING
1466 **
1467 ** Call mprintf with a single double argument which is the product of the
1468 ** two arguments given above.  This is used to generate overflow and underflow
1469 ** doubles to test that they are converted properly.
1470 */
1471 static int SQLITE_TCLAPI sqlite3_mprintf_stronly(
1472   void *NotUsed,
1473   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1474   int argc,              /* Number of arguments */
1475   char **argv            /* Text of each argument */
1476 ){
1477   char *z;
1478   if( argc!=3 ){
1479     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1480        " FORMAT STRING\"", 0);
1481     return TCL_ERROR;
1482   }
1483   z = sqlite3_mprintf(argv[1], argv[2]);
1484   Tcl_AppendResult(interp, z, 0);
1485   sqlite3_free(z);
1486   return TCL_OK;
1487 }
1488 
1489 /*
1490 ** Usage:  sqlite3_mprintf_hexdouble FORMAT HEX
1491 **
1492 ** Call mprintf with a single double argument which is derived from the
1493 ** hexadecimal encoding of an IEEE double.
1494 */
1495 static int SQLITE_TCLAPI sqlite3_mprintf_hexdouble(
1496   void *NotUsed,
1497   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1498   int argc,              /* Number of arguments */
1499   char **argv            /* Text of each argument */
1500 ){
1501   char *z;
1502   double r;
1503   unsigned int x1, x2;
1504   sqlite_uint64 d;
1505   if( argc!=3 ){
1506     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1507        " FORMAT STRING\"", 0);
1508     return TCL_ERROR;
1509   }
1510   if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){
1511     Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0);
1512     return TCL_ERROR;
1513   }
1514   d = x2;
1515   d = (d<<32) + x1;
1516   memcpy(&r, &d, sizeof(r));
1517   z = sqlite3_mprintf(argv[1], r);
1518   Tcl_AppendResult(interp, z, 0);
1519   sqlite3_free(z);
1520   return TCL_OK;
1521 }
1522 
1523 /*
1524 ** Usage: sqlite3_enable_shared_cache ?BOOLEAN?
1525 **
1526 */
1527 #if !defined(SQLITE_OMIT_SHARED_CACHE)
1528 static int SQLITE_TCLAPI test_enable_shared(
1529   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1530   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1531   int objc,              /* Number of arguments */
1532   Tcl_Obj *CONST objv[]  /* Command arguments */
1533 ){
1534   int rc;
1535   int enable;
1536   int ret = 0;
1537 
1538   if( objc!=2 && objc!=1 ){
1539     Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?");
1540     return TCL_ERROR;
1541   }
1542   ret = sqlite3GlobalConfig.sharedCacheEnabled;
1543 
1544   if( objc==2 ){
1545     if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){
1546       return TCL_ERROR;
1547     }
1548     rc = sqlite3_enable_shared_cache(enable);
1549     if( rc!=SQLITE_OK ){
1550       Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
1551       return TCL_ERROR;
1552     }
1553   }
1554   Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret));
1555   return TCL_OK;
1556 }
1557 #endif
1558 
1559 
1560 
1561 /*
1562 ** Usage: sqlite3_extended_result_codes   DB    BOOLEAN
1563 **
1564 */
1565 static int SQLITE_TCLAPI test_extended_result_codes(
1566   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1567   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1568   int objc,              /* Number of arguments */
1569   Tcl_Obj *CONST objv[]  /* Command arguments */
1570 ){
1571   int enable;
1572   sqlite3 *db;
1573 
1574   if( objc!=3 ){
1575     Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN");
1576     return TCL_ERROR;
1577   }
1578   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1579   if( Tcl_GetBooleanFromObj(interp, objv[2], &enable) ) return TCL_ERROR;
1580   sqlite3_extended_result_codes(db, enable);
1581   return TCL_OK;
1582 }
1583 
1584 /*
1585 ** Usage: sqlite3_libversion_number
1586 **
1587 */
1588 static int SQLITE_TCLAPI test_libversion_number(
1589   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1590   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1591   int objc,              /* Number of arguments */
1592   Tcl_Obj *CONST objv[]  /* Command arguments */
1593 ){
1594   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_libversion_number()));
1595   return TCL_OK;
1596 }
1597 
1598 /*
1599 ** Usage: sqlite3_table_column_metadata DB dbname tblname colname
1600 **
1601 */
1602 static int SQLITE_TCLAPI test_table_column_metadata(
1603   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1604   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1605   int objc,              /* Number of arguments */
1606   Tcl_Obj *CONST objv[]  /* Command arguments */
1607 ){
1608   sqlite3 *db;
1609   const char *zDb;
1610   const char *zTbl;
1611   const char *zCol;
1612   int rc;
1613   Tcl_Obj *pRet;
1614 
1615   const char *zDatatype;
1616   const char *zCollseq;
1617   int notnull;
1618   int primarykey;
1619   int autoincrement;
1620 
1621   if( objc!=5 && objc!=4 ){
1622     Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname");
1623     return TCL_ERROR;
1624   }
1625   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1626   zDb = Tcl_GetString(objv[2]);
1627   zTbl = Tcl_GetString(objv[3]);
1628   zCol = objc==5 ? Tcl_GetString(objv[4]) : 0;
1629 
1630   if( strlen(zDb)==0 ) zDb = 0;
1631 
1632   rc = sqlite3_table_column_metadata(db, zDb, zTbl, zCol,
1633       &zDatatype, &zCollseq, &notnull, &primarykey, &autoincrement);
1634 
1635   if( rc!=SQLITE_OK ){
1636     Tcl_AppendResult(interp, sqlite3_errmsg(db), 0);
1637     return TCL_ERROR;
1638   }
1639 
1640   pRet = Tcl_NewObj();
1641   Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zDatatype, -1));
1642   Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zCollseq, -1));
1643   Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(notnull));
1644   Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(primarykey));
1645   Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(autoincrement));
1646   Tcl_SetObjResult(interp, pRet);
1647 
1648   return TCL_OK;
1649 }
1650 
1651 #ifndef SQLITE_OMIT_INCRBLOB
1652 
1653 static int SQLITE_TCLAPI blobHandleFromObj(
1654   Tcl_Interp *interp,
1655   Tcl_Obj *pObj,
1656   sqlite3_blob **ppBlob
1657 ){
1658   char *z;
1659   int n;
1660 
1661   z = Tcl_GetStringFromObj(pObj, &n);
1662   if( n==0 ){
1663     *ppBlob = 0;
1664   }else{
1665     int notUsed;
1666     Tcl_Channel channel;
1667     ClientData instanceData;
1668 
1669     channel = Tcl_GetChannel(interp, z, &notUsed);
1670     if( !channel ) return TCL_ERROR;
1671 
1672     Tcl_Flush(channel);
1673     Tcl_Seek(channel, 0, SEEK_SET);
1674 
1675     instanceData = Tcl_GetChannelInstanceData(channel);
1676     *ppBlob = *((sqlite3_blob **)instanceData);
1677   }
1678 
1679   return TCL_OK;
1680 }
1681 
1682 static int SQLITE_TCLAPI test_blob_reopen(
1683   ClientData clientData, /* Not used */
1684   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1685   int objc,              /* Number of arguments */
1686   Tcl_Obj *CONST objv[]  /* Command arguments */
1687 ){
1688   Tcl_WideInt iRowid;
1689   sqlite3_blob *pBlob;
1690   int rc;
1691 
1692   if( objc!=3 ){
1693     Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL ROWID");
1694     return TCL_ERROR;
1695   }
1696 
1697   if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
1698   if( Tcl_GetWideIntFromObj(interp, objv[2], &iRowid) ) return TCL_ERROR;
1699 
1700   rc = sqlite3_blob_reopen(pBlob, iRowid);
1701   if( rc!=SQLITE_OK ){
1702     Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1703   }
1704 
1705   return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
1706 }
1707 
1708 #endif
1709 
1710 /*
1711 ** Usage: sqlite3_create_collation_v2 DB-HANDLE NAME CMP-PROC DEL-PROC
1712 **
1713 **   This Tcl proc is used for testing the experimental
1714 **   sqlite3_create_collation_v2() interface.
1715 */
1716 struct TestCollationX {
1717   Tcl_Interp *interp;
1718   Tcl_Obj *pCmp;
1719   Tcl_Obj *pDel;
1720 };
1721 typedef struct TestCollationX TestCollationX;
1722 static void testCreateCollationDel(void *pCtx){
1723   TestCollationX *p = (TestCollationX *)pCtx;
1724 
1725   int rc = Tcl_EvalObjEx(p->interp, p->pDel, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL);
1726   if( rc!=TCL_OK ){
1727     Tcl_BackgroundError(p->interp);
1728   }
1729 
1730   Tcl_DecrRefCount(p->pCmp);
1731   Tcl_DecrRefCount(p->pDel);
1732   sqlite3_free((void *)p);
1733 }
1734 static int testCreateCollationCmp(
1735   void *pCtx,
1736   int nLeft,
1737   const void *zLeft,
1738   int nRight,
1739   const void *zRight
1740 ){
1741   TestCollationX *p = (TestCollationX *)pCtx;
1742   Tcl_Obj *pScript = Tcl_DuplicateObj(p->pCmp);
1743   int iRes = 0;
1744 
1745   Tcl_IncrRefCount(pScript);
1746   Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zLeft, nLeft));
1747   Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zRight,nRight));
1748 
1749   if( TCL_OK!=Tcl_EvalObjEx(p->interp, pScript, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL)
1750    || TCL_OK!=Tcl_GetIntFromObj(p->interp, Tcl_GetObjResult(p->interp), &iRes)
1751   ){
1752     Tcl_BackgroundError(p->interp);
1753   }
1754   Tcl_DecrRefCount(pScript);
1755 
1756   return iRes;
1757 }
1758 static int SQLITE_TCLAPI test_create_collation_v2(
1759   ClientData clientData, /* Not used */
1760   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1761   int objc,              /* Number of arguments */
1762   Tcl_Obj *CONST objv[]  /* Command arguments */
1763 ){
1764   TestCollationX *p;
1765   sqlite3 *db;
1766   int rc;
1767 
1768   if( objc!=5 ){
1769     Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE NAME CMP-PROC DEL-PROC");
1770     return TCL_ERROR;
1771   }
1772   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1773 
1774   p = (TestCollationX *)sqlite3_malloc(sizeof(TestCollationX));
1775   p->pCmp = objv[3];
1776   p->pDel = objv[4];
1777   p->interp = interp;
1778   Tcl_IncrRefCount(p->pCmp);
1779   Tcl_IncrRefCount(p->pDel);
1780 
1781   rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), 16,
1782       (void *)p, testCreateCollationCmp, testCreateCollationDel
1783   );
1784   if( rc!=SQLITE_MISUSE ){
1785     Tcl_AppendResult(interp, "sqlite3_create_collate_v2() failed to detect "
1786       "an invalid encoding", (char*)0);
1787     return TCL_ERROR;
1788   }
1789   rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), SQLITE_UTF8,
1790       (void *)p, testCreateCollationCmp, testCreateCollationDel
1791   );
1792   return TCL_OK;
1793 }
1794 
1795 /*
1796 ** USAGE: sqlite3_create_function_v2 DB NAME NARG ENC ?SWITCHES?
1797 **
1798 ** Available switches are:
1799 **
1800 **   -func    SCRIPT
1801 **   -step    SCRIPT
1802 **   -final   SCRIPT
1803 **   -destroy SCRIPT
1804 */
1805 typedef struct CreateFunctionV2 CreateFunctionV2;
1806 struct CreateFunctionV2 {
1807   Tcl_Interp *interp;
1808   Tcl_Obj *pFunc;                 /* Script for function invocation */
1809   Tcl_Obj *pStep;                 /* Script for agg. step invocation */
1810   Tcl_Obj *pFinal;                /* Script for agg. finalization invocation */
1811   Tcl_Obj *pDestroy;              /* Destructor script */
1812 };
1813 static void cf2Func(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
1814 }
1815 static void cf2Step(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
1816 }
1817 static void cf2Final(sqlite3_context *ctx){
1818 }
1819 static void cf2Destroy(void *pUser){
1820   CreateFunctionV2 *p = (CreateFunctionV2 *)pUser;
1821 
1822   if( p->interp && p->pDestroy ){
1823     int rc = Tcl_EvalObjEx(p->interp, p->pDestroy, 0);
1824     if( rc!=TCL_OK ) Tcl_BackgroundError(p->interp);
1825   }
1826 
1827   if( p->pFunc ) Tcl_DecrRefCount(p->pFunc);
1828   if( p->pStep ) Tcl_DecrRefCount(p->pStep);
1829   if( p->pFinal ) Tcl_DecrRefCount(p->pFinal);
1830   if( p->pDestroy ) Tcl_DecrRefCount(p->pDestroy);
1831   sqlite3_free(p);
1832 }
1833 static int SQLITE_TCLAPI test_create_function_v2(
1834   ClientData clientData,          /* Not used */
1835   Tcl_Interp *interp,             /* The invoking TCL interpreter */
1836   int objc,                       /* Number of arguments */
1837   Tcl_Obj *CONST objv[]           /* Command arguments */
1838 ){
1839   sqlite3 *db;
1840   const char *zFunc;
1841   int nArg;
1842   int enc;
1843   CreateFunctionV2 *p;
1844   int i;
1845   int rc;
1846 
1847   struct EncTable {
1848     const char *zEnc;
1849     int enc;
1850   } aEnc[] = {
1851     {"utf8",    SQLITE_UTF8 },
1852     {"utf16",   SQLITE_UTF16 },
1853     {"utf16le", SQLITE_UTF16LE },
1854     {"utf16be", SQLITE_UTF16BE },
1855     {"any",     SQLITE_ANY },
1856     {"0", 0 }
1857   };
1858 
1859   if( objc<5 || (objc%2)==0 ){
1860     Tcl_WrongNumArgs(interp, 1, objv, "DB NAME NARG ENC SWITCHES...");
1861     return TCL_ERROR;
1862   }
1863 
1864   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1865   zFunc = Tcl_GetString(objv[2]);
1866   if( Tcl_GetIntFromObj(interp, objv[3], &nArg) ) return TCL_ERROR;
1867   if( Tcl_GetIndexFromObjStruct(interp, objv[4], aEnc, sizeof(aEnc[0]),
1868           "encoding", 0, &enc)
1869   ){
1870     return TCL_ERROR;
1871   }
1872   enc = aEnc[enc].enc;
1873 
1874   p = sqlite3_malloc(sizeof(CreateFunctionV2));
1875   assert( p );
1876   memset(p, 0, sizeof(CreateFunctionV2));
1877   p->interp = interp;
1878 
1879   for(i=5; i<objc; i+=2){
1880     int iSwitch;
1881     const char *azSwitch[] = {"-func", "-step", "-final", "-destroy", 0};
1882     if( Tcl_GetIndexFromObj(interp, objv[i], azSwitch, "switch", 0, &iSwitch) ){
1883       sqlite3_free(p);
1884       return TCL_ERROR;
1885     }
1886 
1887     switch( iSwitch ){
1888       case 0: p->pFunc = objv[i+1];      break;
1889       case 1: p->pStep = objv[i+1];      break;
1890       case 2: p->pFinal = objv[i+1];     break;
1891       case 3: p->pDestroy = objv[i+1];   break;
1892     }
1893   }
1894   if( p->pFunc ) p->pFunc = Tcl_DuplicateObj(p->pFunc);
1895   if( p->pStep ) p->pStep = Tcl_DuplicateObj(p->pStep);
1896   if( p->pFinal ) p->pFinal = Tcl_DuplicateObj(p->pFinal);
1897   if( p->pDestroy ) p->pDestroy = Tcl_DuplicateObj(p->pDestroy);
1898 
1899   if( p->pFunc ) Tcl_IncrRefCount(p->pFunc);
1900   if( p->pStep ) Tcl_IncrRefCount(p->pStep);
1901   if( p->pFinal ) Tcl_IncrRefCount(p->pFinal);
1902   if( p->pDestroy ) Tcl_IncrRefCount(p->pDestroy);
1903 
1904   rc = sqlite3_create_function_v2(db, zFunc, nArg, enc, (void *)p,
1905       (p->pFunc ? cf2Func : 0),
1906       (p->pStep ? cf2Step : 0),
1907       (p->pFinal ? cf2Final : 0),
1908       cf2Destroy
1909   );
1910   if( rc!=SQLITE_OK ){
1911     Tcl_ResetResult(interp);
1912     Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
1913     return TCL_ERROR;
1914   }
1915   return TCL_OK;
1916 }
1917 
1918 /*
1919 ** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC?
1920 */
1921 static int SQLITE_TCLAPI test_load_extension(
1922   ClientData clientData, /* Not used */
1923   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1924   int objc,              /* Number of arguments */
1925   Tcl_Obj *CONST objv[]  /* Command arguments */
1926 ){
1927   Tcl_CmdInfo cmdInfo;
1928   sqlite3 *db;
1929   int rc;
1930   char *zDb;
1931   char *zFile;
1932   char *zProc = 0;
1933   char *zErr = 0;
1934 
1935   if( objc!=4 && objc!=3 ){
1936     Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?");
1937     return TCL_ERROR;
1938   }
1939   zDb = Tcl_GetString(objv[1]);
1940   zFile = Tcl_GetString(objv[2]);
1941   if( objc==4 ){
1942     zProc = Tcl_GetString(objv[3]);
1943   }
1944 
1945   /* Extract the C database handle from the Tcl command name */
1946   if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
1947     Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
1948     return TCL_ERROR;
1949   }
1950   db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
1951   assert(db);
1952 
1953   /* Call the underlying C function. If an error occurs, set rc to
1954   ** TCL_ERROR and load any error string into the interpreter. If no
1955   ** error occurs, set rc to TCL_OK.
1956   */
1957 #ifdef SQLITE_OMIT_LOAD_EXTENSION
1958   rc = SQLITE_ERROR;
1959   zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()");
1960   (void)zProc;
1961   (void)zFile;
1962 #else
1963   rc = sqlite3_load_extension(db, zFile, zProc, &zErr);
1964 #endif
1965   if( rc!=SQLITE_OK ){
1966     Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE);
1967     rc = TCL_ERROR;
1968   }else{
1969     rc = TCL_OK;
1970   }
1971   sqlite3_free(zErr);
1972 
1973   return rc;
1974 }
1975 
1976 /*
1977 ** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF
1978 */
1979 static int SQLITE_TCLAPI test_enable_load(
1980   ClientData clientData, /* Not used */
1981   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1982   int objc,              /* Number of arguments */
1983   Tcl_Obj *CONST objv[]  /* Command arguments */
1984 ){
1985   Tcl_CmdInfo cmdInfo;
1986   sqlite3 *db;
1987   char *zDb;
1988   int onoff;
1989 
1990   if( objc!=3 ){
1991     Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF");
1992     return TCL_ERROR;
1993   }
1994   zDb = Tcl_GetString(objv[1]);
1995 
1996   /* Extract the C database handle from the Tcl command name */
1997   if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
1998     Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
1999     return TCL_ERROR;
2000   }
2001   db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
2002   assert(db);
2003 
2004   /* Get the onoff parameter */
2005   if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){
2006     return TCL_ERROR;
2007   }
2008 
2009 #ifdef SQLITE_OMIT_LOAD_EXTENSION
2010   Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()");
2011   return TCL_ERROR;
2012 #else
2013   sqlite3_enable_load_extension(db, onoff);
2014   return TCL_OK;
2015 #endif
2016 }
2017 
2018 /*
2019 ** Usage:  sqlite_abort
2020 **
2021 ** Shutdown the process immediately.  This is not a clean shutdown.
2022 ** This command is used to test the recoverability of a database in
2023 ** the event of a program crash.
2024 */
2025 static int SQLITE_TCLAPI sqlite_abort(
2026   void *NotUsed,
2027   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
2028   int argc,              /* Number of arguments */
2029   char **argv            /* Text of each argument */
2030 ){
2031 #if defined(_MSC_VER)
2032   /* We do this, otherwise the test will halt with a popup message
2033    * that we have to click away before the test will continue.
2034    */
2035   _set_abort_behavior( 0, _CALL_REPORTFAULT );
2036 #endif
2037   exit(255);
2038   assert( interp==0 );   /* This will always fail */
2039   return TCL_OK;
2040 }
2041 
2042 /*
2043 ** The following routine is a user-defined SQL function whose purpose
2044 ** is to test the sqlite_set_result() API.
2045 */
2046 static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
2047   while( argc>=2 ){
2048     const char *zArg0 = (char*)sqlite3_value_text(argv[0]);
2049     if( zArg0 ){
2050       if( 0==sqlite3StrICmp(zArg0, "int") ){
2051         sqlite3_result_int(context, sqlite3_value_int(argv[1]));
2052       }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
2053         sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
2054       }else if( sqlite3StrICmp(zArg0,"string")==0 ){
2055         sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1,
2056             SQLITE_TRANSIENT);
2057       }else if( sqlite3StrICmp(zArg0,"double")==0 ){
2058         sqlite3_result_double(context, sqlite3_value_double(argv[1]));
2059       }else if( sqlite3StrICmp(zArg0,"null")==0 ){
2060         sqlite3_result_null(context);
2061       }else if( sqlite3StrICmp(zArg0,"value")==0 ){
2062         sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
2063       }else{
2064         goto error_out;
2065       }
2066     }else{
2067       goto error_out;
2068     }
2069     argc -= 2;
2070     argv += 2;
2071   }
2072   return;
2073 
2074 error_out:
2075   sqlite3_result_error(context,"first argument should be one of: "
2076       "int int64 string double null value", -1);
2077 }
2078 
2079 /*
2080 ** Usage:   sqlite_register_test_function  DB  NAME
2081 **
2082 ** Register the test SQL function on the database DB under the name NAME.
2083 */
2084 static int SQLITE_TCLAPI test_register_func(
2085   void *NotUsed,
2086   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
2087   int argc,              /* Number of arguments */
2088   char **argv            /* Text of each argument */
2089 ){
2090   sqlite3 *db;
2091   int rc;
2092   if( argc!=3 ){
2093     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2094        " DB FUNCTION-NAME", 0);
2095     return TCL_ERROR;
2096   }
2097   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2098   rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
2099       testFunc, 0, 0);
2100   if( rc!=0 ){
2101     Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
2102     return TCL_ERROR;
2103   }
2104   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
2105   return TCL_OK;
2106 }
2107 
2108 /*
2109 ** Usage:  sqlite3_finalize  STMT
2110 **
2111 ** Finalize a statement handle.
2112 */
2113 static int SQLITE_TCLAPI test_finalize(
2114   void * clientData,
2115   Tcl_Interp *interp,
2116   int objc,
2117   Tcl_Obj *CONST objv[]
2118 ){
2119   sqlite3_stmt *pStmt;
2120   int rc;
2121   sqlite3 *db = 0;
2122 
2123   if( objc!=2 ){
2124     Tcl_AppendResult(interp, "wrong # args: should be \"",
2125         Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
2126     return TCL_ERROR;
2127   }
2128 
2129   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2130 
2131   if( pStmt ){
2132     db = StmtToDb(pStmt);
2133   }
2134   rc = sqlite3_finalize(pStmt);
2135   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
2136   if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
2137   return TCL_OK;
2138 }
2139 
2140 /*
2141 ** Usage:  sqlite3_stmt_status  STMT  CODE  RESETFLAG
2142 **
2143 ** Get the value of a status counter from a statement.
2144 */
2145 static int SQLITE_TCLAPI test_stmt_status(
2146   void * clientData,
2147   Tcl_Interp *interp,
2148   int objc,
2149   Tcl_Obj *CONST objv[]
2150 ){
2151   int iValue;
2152   int i, op = 0, resetFlag;
2153   const char *zOpName;
2154   sqlite3_stmt *pStmt;
2155 
2156   static const struct {
2157     const char *zName;
2158     int op;
2159   } aOp[] = {
2160     { "SQLITE_STMTSTATUS_FULLSCAN_STEP",   SQLITE_STMTSTATUS_FULLSCAN_STEP   },
2161     { "SQLITE_STMTSTATUS_SORT",            SQLITE_STMTSTATUS_SORT            },
2162     { "SQLITE_STMTSTATUS_AUTOINDEX",       SQLITE_STMTSTATUS_AUTOINDEX       },
2163     { "SQLITE_STMTSTATUS_VM_STEP",         SQLITE_STMTSTATUS_VM_STEP         },
2164     { "SQLITE_STMTSTATUS_REPREPARE",       SQLITE_STMTSTATUS_REPREPARE       },
2165     { "SQLITE_STMTSTATUS_RUN",             SQLITE_STMTSTATUS_RUN             },
2166     { "SQLITE_STMTSTATUS_MEMUSED",         SQLITE_STMTSTATUS_MEMUSED         },
2167   };
2168   if( objc!=4 ){
2169     Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG");
2170     return TCL_ERROR;
2171   }
2172   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2173   zOpName = Tcl_GetString(objv[2]);
2174   for(i=0; i<ArraySize(aOp); i++){
2175     if( strcmp(aOp[i].zName, zOpName)==0 ){
2176       op = aOp[i].op;
2177       break;
2178     }
2179   }
2180   if( i>=ArraySize(aOp) ){
2181     if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR;
2182   }
2183   if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR;
2184   iValue = sqlite3_stmt_status(pStmt, op, resetFlag);
2185   Tcl_SetObjResult(interp, Tcl_NewIntObj(iValue));
2186   return TCL_OK;
2187 }
2188 
2189 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
2190 /*
2191 ** Usage:  sqlite3_stmt_scanstatus STMT IDX
2192 */
2193 static int SQLITE_TCLAPI test_stmt_scanstatus(
2194   void * clientData,
2195   Tcl_Interp *interp,
2196   int objc,
2197   Tcl_Obj *CONST objv[]
2198 ){
2199   sqlite3_stmt *pStmt;            /* First argument */
2200   int idx;                        /* Second argument */
2201 
2202   const char *zName;
2203   const char *zExplain;
2204   sqlite3_int64 nLoop;
2205   sqlite3_int64 nVisit;
2206   double rEst;
2207   int res;
2208 
2209   if( objc!=3 ){
2210     Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX");
2211     return TCL_ERROR;
2212   }
2213   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2214   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
2215 
2216   res = sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop);
2217   if( res==0 ){
2218     Tcl_Obj *pRet = Tcl_NewObj();
2219     Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nLoop", -1));
2220     Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nLoop));
2221     sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
2222     Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nVisit", -1));
2223     Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nVisit));
2224     sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EST, (void*)&rEst);
2225     Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nEst", -1));
2226     Tcl_ListObjAppendElement(0, pRet, Tcl_NewDoubleObj(rEst));
2227     sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NAME, (void*)&zName);
2228     Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zName", -1));
2229     Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zName, -1));
2230     sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
2231     Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zExplain", -1));
2232     Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zExplain, -1));
2233     Tcl_SetObjResult(interp, pRet);
2234   }else{
2235     Tcl_ResetResult(interp);
2236   }
2237   return TCL_OK;
2238 }
2239 
2240 /*
2241 ** Usage:  sqlite3_stmt_scanstatus_reset  STMT
2242 */
2243 static int SQLITE_TCLAPI test_stmt_scanstatus_reset(
2244   void * clientData,
2245   Tcl_Interp *interp,
2246   int objc,
2247   Tcl_Obj *CONST objv[]
2248 ){
2249   sqlite3_stmt *pStmt;            /* First argument */
2250   if( objc!=2 ){
2251     Tcl_WrongNumArgs(interp, 1, objv, "STMT");
2252     return TCL_ERROR;
2253   }
2254   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2255   sqlite3_stmt_scanstatus_reset(pStmt);
2256   return TCL_OK;
2257 }
2258 #endif
2259 
2260 #ifdef SQLITE_ENABLE_SQLLOG
2261 /*
2262 ** Usage:  sqlite3_config_sqllog
2263 **
2264 ** Zero the SQLITE_CONFIG_SQLLOG configuration
2265 */
2266 static int SQLITE_TCLAPI test_config_sqllog(
2267   void * clientData,
2268   Tcl_Interp *interp,
2269   int objc,
2270   Tcl_Obj *CONST objv[]
2271 ){
2272   if( objc!=1 ){
2273     Tcl_WrongNumArgs(interp, 1, objv, "");
2274     return TCL_ERROR;
2275   }
2276   sqlite3_config(SQLITE_CONFIG_SQLLOG, 0, 0);
2277   return TCL_OK;
2278 }
2279 #endif
2280 
2281 /*
2282 ** Usage:  sqlite3_config_sorterref
2283 **
2284 ** Set the SQLITE_CONFIG_SORTERREF_SIZE configuration option
2285 */
2286 static int SQLITE_TCLAPI test_config_sorterref(
2287   void * clientData,
2288   Tcl_Interp *interp,
2289   int objc,
2290   Tcl_Obj *CONST objv[]
2291 ){
2292   int iVal;
2293   if( objc!=2 ){
2294     Tcl_WrongNumArgs(interp, 1, objv, "NBYTE");
2295     return TCL_ERROR;
2296   }
2297   if( Tcl_GetIntFromObj(interp, objv[1], &iVal) ) return TCL_ERROR;
2298   sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, iVal);
2299   return TCL_OK;
2300 }
2301 
2302 /*
2303 ** Usage: vfs_current_time_int64
2304 **
2305 ** Return the value returned by the default VFS's xCurrentTimeInt64 method.
2306 */
2307 static int SQLITE_TCLAPI vfsCurrentTimeInt64(
2308   void * clientData,
2309   Tcl_Interp *interp,
2310   int objc,
2311   Tcl_Obj *CONST objv[]
2312 ){
2313   i64 t;
2314   sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
2315   if( objc!=1 ){
2316     Tcl_WrongNumArgs(interp, 1, objv, "");
2317     return TCL_ERROR;
2318   }
2319   pVfs->xCurrentTimeInt64(pVfs, &t);
2320   Tcl_SetObjResult(interp, Tcl_NewWideIntObj(t));
2321   return TCL_OK;
2322 }
2323 
2324 #ifdef SQLITE_ENABLE_SNAPSHOT
2325 /*
2326 ** Usage: sqlite3_snapshot_get DB DBNAME
2327 */
2328 static int SQLITE_TCLAPI test_snapshot_get(
2329   void * clientData,
2330   Tcl_Interp *interp,
2331   int objc,
2332   Tcl_Obj *CONST objv[]
2333 ){
2334   int rc;
2335   sqlite3 *db;
2336   char *zName;
2337   sqlite3_snapshot *pSnapshot = 0;
2338 
2339   if( objc!=3 ){
2340     Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
2341     return TCL_ERROR;
2342   }
2343   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2344   zName = Tcl_GetString(objv[2]);
2345 
2346   rc = sqlite3_snapshot_get(db, zName, &pSnapshot);
2347   if( rc!=SQLITE_OK ){
2348     Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
2349     return TCL_ERROR;
2350   }else{
2351     char zBuf[100];
2352     if( sqlite3TestMakePointerStr(interp, zBuf, pSnapshot) ) return TCL_ERROR;
2353     Tcl_SetObjResult(interp, Tcl_NewStringObj(zBuf, -1));
2354   }
2355   return TCL_OK;
2356 }
2357 #endif /* SQLITE_ENABLE_SNAPSHOT */
2358 
2359 #ifdef SQLITE_ENABLE_SNAPSHOT
2360 /*
2361 ** Usage: sqlite3_snapshot_recover DB DBNAME
2362 */
2363 static int SQLITE_TCLAPI test_snapshot_recover(
2364   void * clientData,
2365   Tcl_Interp *interp,
2366   int objc,
2367   Tcl_Obj *CONST objv[]
2368 ){
2369   int rc;
2370   sqlite3 *db;
2371   char *zName;
2372 
2373   if( objc!=3 ){
2374     Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
2375     return TCL_ERROR;
2376   }
2377   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2378   zName = Tcl_GetString(objv[2]);
2379 
2380   rc = sqlite3_snapshot_recover(db, zName);
2381   if( rc!=SQLITE_OK ){
2382     Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
2383     return TCL_ERROR;
2384   }else{
2385     Tcl_ResetResult(interp);
2386   }
2387   return TCL_OK;
2388 }
2389 #endif /* SQLITE_ENABLE_SNAPSHOT */
2390 
2391 #ifdef SQLITE_ENABLE_SNAPSHOT
2392 /*
2393 ** Usage: sqlite3_snapshot_open DB DBNAME SNAPSHOT
2394 */
2395 static int SQLITE_TCLAPI test_snapshot_open(
2396   void * clientData,
2397   Tcl_Interp *interp,
2398   int objc,
2399   Tcl_Obj *CONST objv[]
2400 ){
2401   int rc;
2402   sqlite3 *db;
2403   char *zName;
2404   sqlite3_snapshot *pSnapshot;
2405 
2406   if( objc!=4 ){
2407     Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SNAPSHOT");
2408     return TCL_ERROR;
2409   }
2410   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2411   zName = Tcl_GetString(objv[2]);
2412   pSnapshot = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[3]));
2413 
2414   rc = sqlite3_snapshot_open(db, zName, pSnapshot);
2415   if( rc!=SQLITE_OK ){
2416     Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
2417     return TCL_ERROR;
2418   }else{
2419     Tcl_ResetResult(interp);
2420   }
2421   return TCL_OK;
2422 }
2423 #endif /* SQLITE_ENABLE_SNAPSHOT */
2424 
2425 #ifdef SQLITE_ENABLE_SNAPSHOT
2426 /*
2427 ** Usage: sqlite3_snapshot_free SNAPSHOT
2428 */
2429 static int SQLITE_TCLAPI test_snapshot_free(
2430   void * clientData,
2431   Tcl_Interp *interp,
2432   int objc,
2433   Tcl_Obj *CONST objv[]
2434 ){
2435   sqlite3_snapshot *pSnapshot;
2436   if( objc!=2 ){
2437     Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT");
2438     return TCL_ERROR;
2439   }
2440   pSnapshot = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
2441   sqlite3_snapshot_free(pSnapshot);
2442   return TCL_OK;
2443 }
2444 #endif /* SQLITE_ENABLE_SNAPSHOT */
2445 
2446 #ifdef SQLITE_ENABLE_SNAPSHOT
2447 /*
2448 ** Usage: sqlite3_snapshot_cmp SNAPSHOT1 SNAPSHOT2
2449 */
2450 static int SQLITE_TCLAPI test_snapshot_cmp(
2451   void * clientData,
2452   Tcl_Interp *interp,
2453   int objc,
2454   Tcl_Obj *CONST objv[]
2455 ){
2456   int res;
2457   sqlite3_snapshot *p1;
2458   sqlite3_snapshot *p2;
2459   if( objc!=3 ){
2460     Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT1 SNAPSHOT2");
2461     return TCL_ERROR;
2462   }
2463   p1 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
2464   p2 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[2]));
2465   res = sqlite3_snapshot_cmp(p1, p2);
2466   Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
2467   return TCL_OK;
2468 }
2469 #endif /* SQLITE_ENABLE_SNAPSHOT */
2470 
2471 #ifdef SQLITE_ENABLE_SNAPSHOT
2472 /*
2473 ** Usage: sqlite3_snapshot_get_blob DB DBNAME
2474 */
2475 static int SQLITE_TCLAPI test_snapshot_get_blob(
2476   void * clientData,
2477   Tcl_Interp *interp,
2478   int objc,
2479   Tcl_Obj *CONST objv[]
2480 ){
2481   int rc;
2482   sqlite3 *db;
2483   char *zName;
2484   sqlite3_snapshot *pSnapshot = 0;
2485 
2486   if( objc!=3 ){
2487     Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
2488     return TCL_ERROR;
2489   }
2490   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2491   zName = Tcl_GetString(objv[2]);
2492 
2493   rc = sqlite3_snapshot_get(db, zName, &pSnapshot);
2494   if( rc!=SQLITE_OK ){
2495     Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
2496     return TCL_ERROR;
2497   }else{
2498     Tcl_SetObjResult(interp,
2499         Tcl_NewByteArrayObj((unsigned char*)pSnapshot, sizeof(sqlite3_snapshot))
2500     );
2501     sqlite3_snapshot_free(pSnapshot);
2502   }
2503   return TCL_OK;
2504 }
2505 #endif /* SQLITE_ENABLE_SNAPSHOT */
2506 
2507 #ifdef SQLITE_ENABLE_SNAPSHOT
2508   /*
2509   ** Usage: sqlite3_snapshot_open_blob DB DBNAME SNAPSHOT
2510 */
2511 static int SQLITE_TCLAPI test_snapshot_open_blob(
2512   void * clientData,
2513   Tcl_Interp *interp,
2514   int objc,
2515   Tcl_Obj *CONST objv[]
2516 ){
2517   int rc;
2518   sqlite3 *db;
2519   char *zName;
2520   unsigned char *pBlob;
2521   int nBlob;
2522 
2523   if( objc!=4 ){
2524     Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SNAPSHOT");
2525     return TCL_ERROR;
2526   }
2527   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2528   zName = Tcl_GetString(objv[2]);
2529   pBlob = Tcl_GetByteArrayFromObj(objv[3], &nBlob);
2530   if( nBlob!=sizeof(sqlite3_snapshot) ){
2531     Tcl_AppendResult(interp, "bad SNAPSHOT", 0);
2532     return TCL_ERROR;
2533   }
2534   rc = sqlite3_snapshot_open(db, zName, (sqlite3_snapshot*)pBlob);
2535   if( rc!=SQLITE_OK ){
2536     Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
2537     return TCL_ERROR;
2538   }
2539   return TCL_OK;
2540 }
2541 #endif /* SQLITE_ENABLE_SNAPSHOT */
2542 
2543 #ifdef SQLITE_ENABLE_SNAPSHOT
2544 /*
2545 ** Usage: sqlite3_snapshot_cmp_blob SNAPSHOT1 SNAPSHOT2
2546 */
2547 static int SQLITE_TCLAPI test_snapshot_cmp_blob(
2548   void * clientData,
2549   Tcl_Interp *interp,
2550   int objc,
2551   Tcl_Obj *CONST objv[]
2552 ){
2553   int res;
2554   unsigned char *p1;
2555   unsigned char *p2;
2556   int n1;
2557   int n2;
2558 
2559   if( objc!=3 ){
2560     Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT1 SNAPSHOT2");
2561     return TCL_ERROR;
2562   }
2563 
2564   p1 = Tcl_GetByteArrayFromObj(objv[1], &n1);
2565   p2 = Tcl_GetByteArrayFromObj(objv[2], &n2);
2566 
2567   if( n1!=sizeof(sqlite3_snapshot) || n1!=n2 ){
2568     Tcl_AppendResult(interp, "bad SNAPSHOT", 0);
2569     return TCL_ERROR;
2570   }
2571 
2572   res = sqlite3_snapshot_cmp((sqlite3_snapshot*)p1, (sqlite3_snapshot*)p2);
2573   Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
2574   return TCL_OK;
2575 }
2576 #endif /* SQLITE_ENABLE_SNAPSHOT */
2577 
2578 /*
2579 ** Usage: sqlite3_delete_database FILENAME
2580 */
2581 int sqlite3_delete_database(const char*);   /* in test_delete.c */
2582 static int SQLITE_TCLAPI test_delete_database(
2583   void * clientData,
2584   Tcl_Interp *interp,
2585   int objc,
2586   Tcl_Obj *CONST objv[]
2587 ){
2588   int rc;
2589   const char *zFile;
2590   if( objc!=2 ){
2591     Tcl_WrongNumArgs(interp, 1, objv, "FILE");
2592     return TCL_ERROR;
2593   }
2594   zFile = (const char*)Tcl_GetString(objv[1]);
2595   rc = sqlite3_delete_database(zFile);
2596 
2597   Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
2598   return TCL_OK;
2599 }
2600 
2601 /*
2602 ** Usage: atomic_batch_write PATH
2603 */
2604 static int SQLITE_TCLAPI test_atomic_batch_write(
2605   void * clientData,
2606   Tcl_Interp *interp,
2607   int objc,
2608   Tcl_Obj *CONST objv[]
2609 ){
2610   char *zFile = 0;                /* Path to file to test */
2611   sqlite3 *db = 0;                /* Database handle */
2612   sqlite3_file *pFd = 0;          /* SQLite fd open on zFile */
2613   int bRes = 0;                   /* Integer result of this command */
2614   int dc = 0;                     /* Device-characteristics mask */
2615   int rc;                         /* sqlite3_open() return code */
2616 
2617   if( objc!=2 ){
2618     Tcl_WrongNumArgs(interp, 1, objv, "PATH");
2619     return TCL_ERROR;
2620   }
2621   zFile = Tcl_GetString(objv[1]);
2622 
2623   rc = sqlite3_open(zFile, &db);
2624   if( rc!=SQLITE_OK ){
2625     Tcl_AppendResult(interp, sqlite3_errmsg(db), 0);
2626     sqlite3_close(db);
2627     return TCL_ERROR;
2628   }
2629 
2630   rc = sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, (void*)&pFd);
2631   dc = pFd->pMethods->xDeviceCharacteristics(pFd);
2632   if( dc & SQLITE_IOCAP_BATCH_ATOMIC ){
2633     bRes = 1;
2634   }
2635 
2636   Tcl_SetObjResult(interp, Tcl_NewIntObj(bRes));
2637   sqlite3_close(db);
2638   return TCL_OK;
2639 }
2640 
2641 /*
2642 ** Usage:  sqlite3_next_stmt  DB  STMT
2643 **
2644 ** Return the next statment in sequence after STMT.
2645 */
2646 static int SQLITE_TCLAPI test_next_stmt(
2647   void * clientData,
2648   Tcl_Interp *interp,
2649   int objc,
2650   Tcl_Obj *CONST objv[]
2651 ){
2652   sqlite3_stmt *pStmt;
2653   sqlite3 *db = 0;
2654   char zBuf[50];
2655 
2656   if( objc!=3 ){
2657     Tcl_AppendResult(interp, "wrong # args: should be \"",
2658         Tcl_GetStringFromObj(objv[0], 0), " DB STMT", 0);
2659     return TCL_ERROR;
2660   }
2661 
2662   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2663   if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt) ) return TCL_ERROR;
2664   pStmt = sqlite3_next_stmt(db, pStmt);
2665   if( pStmt ){
2666     if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
2667     Tcl_AppendResult(interp, zBuf, 0);
2668   }
2669   return TCL_OK;
2670 }
2671 
2672 /*
2673 ** Usage:  sqlite3_stmt_readonly  STMT
2674 **
2675 ** Return true if STMT is a NULL pointer or a pointer to a statement
2676 ** that is guaranteed to leave the database unmodified.
2677 */
2678 static int SQLITE_TCLAPI test_stmt_readonly(
2679   void * clientData,
2680   Tcl_Interp *interp,
2681   int objc,
2682   Tcl_Obj *CONST objv[]
2683 ){
2684   sqlite3_stmt *pStmt;
2685   int rc;
2686 
2687   if( objc!=2 ){
2688     Tcl_AppendResult(interp, "wrong # args: should be \"",
2689         Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
2690     return TCL_ERROR;
2691   }
2692 
2693   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2694   rc = sqlite3_stmt_readonly(pStmt);
2695   Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
2696   return TCL_OK;
2697 }
2698 
2699 /*
2700 ** Usage:  sqlite3_stmt_isexplain  STMT
2701 **
2702 ** Return 1, 2, or 0 respectively if STMT is an EXPLAIN statement, an
2703 ** EXPLAIN QUERY PLAN statement or an ordinary statement or NULL pointer.
2704 */
2705 static int SQLITE_TCLAPI test_stmt_isexplain(
2706   void * clientData,
2707   Tcl_Interp *interp,
2708   int objc,
2709   Tcl_Obj *CONST objv[]
2710 ){
2711   sqlite3_stmt *pStmt;
2712   int rc;
2713 
2714   if( objc!=2 ){
2715     Tcl_AppendResult(interp, "wrong # args: should be \"",
2716         Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
2717     return TCL_ERROR;
2718   }
2719 
2720   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2721   rc = sqlite3_stmt_isexplain(pStmt);
2722   Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
2723   return TCL_OK;
2724 }
2725 
2726 /*
2727 ** Usage:  sqlite3_stmt_busy  STMT
2728 **
2729 ** Return true if STMT is a non-NULL pointer to a statement
2730 ** that has been stepped but not to completion.
2731 */
2732 static int SQLITE_TCLAPI test_stmt_busy(
2733   void * clientData,
2734   Tcl_Interp *interp,
2735   int objc,
2736   Tcl_Obj *CONST objv[]
2737 ){
2738   sqlite3_stmt *pStmt;
2739   int rc;
2740 
2741   if( objc!=2 ){
2742     Tcl_AppendResult(interp, "wrong # args: should be \"",
2743         Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
2744     return TCL_ERROR;
2745   }
2746 
2747   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2748   rc = sqlite3_stmt_busy(pStmt);
2749   Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
2750   return TCL_OK;
2751 }
2752 
2753 /*
2754 ** Usage:  uses_stmt_journal  STMT
2755 **
2756 ** Return true if STMT uses a statement journal.
2757 */
2758 static int SQLITE_TCLAPI uses_stmt_journal(
2759   void * clientData,
2760   Tcl_Interp *interp,
2761   int objc,
2762   Tcl_Obj *CONST objv[]
2763 ){
2764   sqlite3_stmt *pStmt;
2765 
2766   if( objc!=2 ){
2767     Tcl_AppendResult(interp, "wrong # args: should be \"",
2768         Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
2769     return TCL_ERROR;
2770   }
2771 
2772   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2773   sqlite3_stmt_readonly(pStmt);
2774   Tcl_SetObjResult(interp, Tcl_NewBooleanObj(((Vdbe *)pStmt)->usesStmtJournal));
2775   return TCL_OK;
2776 }
2777 
2778 
2779 /*
2780 ** Usage:  sqlite3_reset  STMT
2781 **
2782 ** Reset a statement handle.
2783 */
2784 static int SQLITE_TCLAPI test_reset(
2785   void * clientData,
2786   Tcl_Interp *interp,
2787   int objc,
2788   Tcl_Obj *CONST objv[]
2789 ){
2790   sqlite3_stmt *pStmt;
2791   int rc;
2792 
2793   if( objc!=2 ){
2794     Tcl_AppendResult(interp, "wrong # args: should be \"",
2795         Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
2796     return TCL_ERROR;
2797   }
2798 
2799   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2800 
2801   rc = sqlite3_reset(pStmt);
2802   if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){
2803     return TCL_ERROR;
2804   }
2805   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
2806 /*
2807   if( rc ){
2808     return TCL_ERROR;
2809   }
2810 */
2811   return TCL_OK;
2812 }
2813 
2814 /*
2815 ** Usage:  sqlite3_expired STMT
2816 **
2817 ** Return TRUE if a recompilation of the statement is recommended.
2818 */
2819 static int SQLITE_TCLAPI test_expired(
2820   void * clientData,
2821   Tcl_Interp *interp,
2822   int objc,
2823   Tcl_Obj *CONST objv[]
2824 ){
2825 #ifndef SQLITE_OMIT_DEPRECATED
2826   sqlite3_stmt *pStmt;
2827   if( objc!=2 ){
2828     Tcl_AppendResult(interp, "wrong # args: should be \"",
2829         Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
2830     return TCL_ERROR;
2831   }
2832   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2833   Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt)));
2834 #endif
2835   return TCL_OK;
2836 }
2837 
2838 /*
2839 ** Usage:  sqlite3_transfer_bindings FROMSTMT TOSTMT
2840 **
2841 ** Transfer all bindings from FROMSTMT over to TOSTMT
2842 */
2843 static int SQLITE_TCLAPI test_transfer_bind(
2844   void * clientData,
2845   Tcl_Interp *interp,
2846   int objc,
2847   Tcl_Obj *CONST objv[]
2848 ){
2849 #ifndef SQLITE_OMIT_DEPRECATED
2850   sqlite3_stmt *pStmt1, *pStmt2;
2851   if( objc!=3 ){
2852     Tcl_AppendResult(interp, "wrong # args: should be \"",
2853         Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0);
2854     return TCL_ERROR;
2855   }
2856   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR;
2857   if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR;
2858   Tcl_SetObjResult(interp,
2859      Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2)));
2860 #endif
2861   return TCL_OK;
2862 }
2863 
2864 /*
2865 ** Usage:  sqlite3_changes DB
2866 **
2867 ** Return the number of changes made to the database by the last SQL
2868 ** execution.
2869 */
2870 static int SQLITE_TCLAPI test_changes(
2871   void * clientData,
2872   Tcl_Interp *interp,
2873   int objc,
2874   Tcl_Obj *CONST objv[]
2875 ){
2876   sqlite3 *db;
2877   if( objc!=2 ){
2878     Tcl_AppendResult(interp, "wrong # args: should be \"",
2879        Tcl_GetString(objv[0]), " DB", 0);
2880     return TCL_ERROR;
2881   }
2882   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2883   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
2884   return TCL_OK;
2885 }
2886 
2887 /*
2888 ** This is the "static_bind_value" that variables are bound to when
2889 ** the FLAG option of sqlite3_bind is "static"
2890 */
2891 static char *sqlite_static_bind_value = 0;
2892 static int sqlite_static_bind_nbyte = 0;
2893 
2894 /*
2895 ** Usage:  sqlite3_bind  VM  IDX  VALUE  FLAGS
2896 **
2897 ** Sets the value of the IDX-th occurrence of "?" in the original SQL
2898 ** string.  VALUE is the new value.  If FLAGS=="null" then VALUE is
2899 ** ignored and the value is set to NULL.  If FLAGS=="static" then
2900 ** the value is set to the value of a static variable named
2901 ** "sqlite_static_bind_value".  If FLAGS=="normal" then a copy
2902 ** of the VALUE is made.  If FLAGS=="blob10" then a VALUE is ignored
2903 ** an a 10-byte blob "abc\000xyz\000pq" is inserted.
2904 */
2905 static int SQLITE_TCLAPI test_bind(
2906   void *NotUsed,
2907   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
2908   int argc,              /* Number of arguments */
2909   char **argv            /* Text of each argument */
2910 ){
2911   sqlite3_stmt *pStmt;
2912   int rc;
2913   int idx;
2914   if( argc!=5 ){
2915     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2916        " VM IDX VALUE (null|static|normal)\"", 0);
2917     return TCL_ERROR;
2918   }
2919   if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
2920   if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
2921   if( strcmp(argv[4],"null")==0 ){
2922     rc = sqlite3_bind_null(pStmt, idx);
2923   }else if( strcmp(argv[4],"static")==0 ){
2924     rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
2925   }else if( strcmp(argv[4],"static-nbytes")==0 ){
2926     rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value,
2927                                        sqlite_static_bind_nbyte, 0);
2928   }else if( strcmp(argv[4],"normal")==0 ){
2929     rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
2930   }else if( strcmp(argv[4],"blob10")==0 ){
2931     rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC);
2932   }else{
2933     Tcl_AppendResult(interp, "4th argument should be "
2934         "\"null\" or \"static\" or \"normal\"", 0);
2935     return TCL_ERROR;
2936   }
2937   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
2938   if( rc ){
2939     char zBuf[50];
2940     sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
2941     Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
2942     return TCL_ERROR;
2943   }
2944   return TCL_OK;
2945 }
2946 
2947 #ifndef SQLITE_OMIT_UTF16
2948 /*
2949 ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
2950 **
2951 ** This function is used to test that SQLite selects the correct collation
2952 ** sequence callback when multiple versions (for different text encodings)
2953 ** are available.
2954 **
2955 ** Calling this routine registers the collation sequence "test_collate"
2956 ** with database handle <db>. The second argument must be a list of three
2957 ** boolean values. If the first is true, then a version of test_collate is
2958 ** registered for UTF-8, if the second is true, a version is registered for
2959 ** UTF-16le, if the third is true, a UTF-16be version is available.
2960 ** Previous versions of test_collate are deleted.
2961 **
2962 ** The collation sequence test_collate is implemented by calling the
2963 ** following TCL script:
2964 **
2965 **   "test_collate <enc> <lhs> <rhs>"
2966 **
2967 ** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
2968 ** The <enc> parameter is the encoding of the collation function that
2969 ** SQLite selected to call. The TCL test script implements the
2970 ** "test_collate" proc.
2971 **
2972 ** Note that this will only work with one interpreter at a time, as the
2973 ** interp pointer to use when evaluating the TCL script is stored in
2974 ** pTestCollateInterp.
2975 */
2976 static Tcl_Interp* pTestCollateInterp;
2977 static int test_collate_func(
2978   void *pCtx,
2979   int nA, const void *zA,
2980   int nB, const void *zB
2981 ){
2982   Tcl_Interp *i = pTestCollateInterp;
2983   int encin = SQLITE_PTR_TO_INT(pCtx);
2984   int res;
2985   int n;
2986 
2987   sqlite3_value *pVal;
2988   Tcl_Obj *pX;
2989 
2990   pX = Tcl_NewStringObj("test_collate", -1);
2991   Tcl_IncrRefCount(pX);
2992 
2993   switch( encin ){
2994     case SQLITE_UTF8:
2995       Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
2996       break;
2997     case SQLITE_UTF16LE:
2998       Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
2999       break;
3000     case SQLITE_UTF16BE:
3001       Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
3002       break;
3003     default:
3004       assert(0);
3005   }
3006 
3007   sqlite3BeginBenignMalloc();
3008   pVal = sqlite3ValueNew(0);
3009   if( pVal ){
3010     sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
3011     n = sqlite3_value_bytes(pVal);
3012     Tcl_ListObjAppendElement(i,pX,
3013         Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
3014     sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
3015     n = sqlite3_value_bytes(pVal);
3016     Tcl_ListObjAppendElement(i,pX,
3017         Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
3018     sqlite3ValueFree(pVal);
3019   }
3020   sqlite3EndBenignMalloc();
3021 
3022   Tcl_EvalObjEx(i, pX, 0);
3023   Tcl_DecrRefCount(pX);
3024   Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
3025   return res;
3026 }
3027 static int SQLITE_TCLAPI test_collate(
3028   void * clientData,
3029   Tcl_Interp *interp,
3030   int objc,
3031   Tcl_Obj *CONST objv[]
3032 ){
3033   sqlite3 *db;
3034   int val;
3035   sqlite3_value *pVal;
3036   int rc;
3037 
3038   if( objc!=5 ) goto bad_args;
3039   pTestCollateInterp = interp;
3040   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3041 
3042   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
3043   rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
3044           (void *)SQLITE_UTF8, val?test_collate_func:0);
3045   if( rc==SQLITE_OK ){
3046     const void *zUtf16;
3047     if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
3048     rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
3049             (void *)SQLITE_UTF16LE, val?test_collate_func:0);
3050     if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
3051 
3052 #if 0
3053     if( sqlite3_iMallocFail>0 ){
3054       sqlite3_iMallocFail++;
3055     }
3056 #endif
3057     sqlite3_mutex_enter(db->mutex);
3058     pVal = sqlite3ValueNew(db);
3059     sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
3060     zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
3061     if( db->mallocFailed ){
3062       rc = SQLITE_NOMEM;
3063     }else{
3064       rc = sqlite3_create_collation16(db, zUtf16, SQLITE_UTF16BE,
3065           (void *)SQLITE_UTF16BE, val?test_collate_func:0);
3066     }
3067     sqlite3ValueFree(pVal);
3068     sqlite3_mutex_leave(db->mutex);
3069   }
3070   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
3071 
3072   if( rc!=SQLITE_OK ){
3073     Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
3074     return TCL_ERROR;
3075   }
3076   return TCL_OK;
3077 
3078 bad_args:
3079   Tcl_AppendResult(interp, "wrong # args: should be \"",
3080       Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
3081   return TCL_ERROR;
3082 }
3083 
3084 /*
3085 ** Usage: add_test_utf16bin_collate <db ptr>
3086 **
3087 ** Add a utf-16 collation sequence named "utf16bin" to the database
3088 ** handle. This collation sequence compares arguments in the same way as the
3089 ** built-in collation "binary".
3090 */
3091 static int test_utf16bin_collate_func(
3092   void *pCtx,
3093   int nA, const void *zA,
3094   int nB, const void *zB
3095 ){
3096   int nCmp = (nA>nB ? nB : nA);
3097   int res = memcmp(zA, zB, nCmp);
3098   if( res==0 ) res = nA - nB;
3099   return res;
3100 }
3101 static int SQLITE_TCLAPI test_utf16bin_collate(
3102   void * clientData,
3103   Tcl_Interp *interp,
3104   int objc,
3105   Tcl_Obj *CONST objv[]
3106 ){
3107   sqlite3 *db;
3108   int rc;
3109 
3110   if( objc!=2 ) goto bad_args;
3111   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3112 
3113   rc = sqlite3_create_collation(db, "utf16bin", SQLITE_UTF16, 0,
3114       test_utf16bin_collate_func
3115   );
3116   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
3117   return TCL_OK;
3118 
3119 bad_args:
3120   Tcl_WrongNumArgs(interp, 1, objv, "DB");
3121   return TCL_ERROR;
3122 }
3123 
3124 /*
3125 ** When the collation needed callback is invoked, record the name of
3126 ** the requested collating function here.  The recorded name is linked
3127 ** to a TCL variable and used to make sure that the requested collation
3128 ** name is correct.
3129 */
3130 static char zNeededCollation[200];
3131 static char *pzNeededCollation = zNeededCollation;
3132 
3133 
3134 /*
3135 ** Called when a collating sequence is needed.  Registered using
3136 ** sqlite3_collation_needed16().
3137 */
3138 static void test_collate_needed_cb(
3139   void *pCtx,
3140   sqlite3 *db,
3141   int eTextRep,
3142   const void *pName
3143 ){
3144   int enc = ENC(db);
3145   int i;
3146   char *z;
3147   for(z = (char*)pName, i=0; *z || z[1]; z++){
3148     if( *z ) zNeededCollation[i++] = *z;
3149   }
3150   zNeededCollation[i] = 0;
3151   sqlite3_create_collation(
3152       db, "test_collate", ENC(db), SQLITE_INT_TO_PTR(enc), test_collate_func);
3153 }
3154 
3155 /*
3156 ** Usage: add_test_collate_needed DB
3157 */
3158 static int SQLITE_TCLAPI test_collate_needed(
3159   void * clientData,
3160   Tcl_Interp *interp,
3161   int objc,
3162   Tcl_Obj *CONST objv[]
3163 ){
3164   sqlite3 *db;
3165   int rc;
3166 
3167   if( objc!=2 ) goto bad_args;
3168   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3169   rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
3170   zNeededCollation[0] = 0;
3171   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
3172   return TCL_OK;
3173 
3174 bad_args:
3175   Tcl_WrongNumArgs(interp, 1, objv, "DB");
3176   return TCL_ERROR;
3177 }
3178 
3179 /*
3180 ** tclcmd:   add_alignment_test_collations  DB
3181 **
3182 ** Add two new collating sequences to the database DB
3183 **
3184 **     utf16_aligned
3185 **     utf16_unaligned
3186 **
3187 ** Both collating sequences use the same sort order as BINARY.
3188 ** The only difference is that the utf16_aligned collating
3189 ** sequence is declared with the SQLITE_UTF16_ALIGNED flag.
3190 ** Both collating functions increment the unaligned utf16 counter
3191 ** whenever they see a string that begins on an odd byte boundary.
3192 */
3193 static int unaligned_string_counter = 0;
3194 static int alignmentCollFunc(
3195   void *NotUsed,
3196   int nKey1, const void *pKey1,
3197   int nKey2, const void *pKey2
3198 ){
3199   int rc, n;
3200   n = nKey1<nKey2 ? nKey1 : nKey2;
3201   if( nKey1>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey1))) ) unaligned_string_counter++;
3202   if( nKey2>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey2))) ) unaligned_string_counter++;
3203   rc = memcmp(pKey1, pKey2, n);
3204   if( rc==0 ){
3205     rc = nKey1 - nKey2;
3206   }
3207   return rc;
3208 }
3209 static int SQLITE_TCLAPI add_alignment_test_collations(
3210   void * clientData,
3211   Tcl_Interp *interp,
3212   int objc,
3213   Tcl_Obj *CONST objv[]
3214 ){
3215   sqlite3 *db;
3216   if( objc>=2 ){
3217     if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3218     sqlite3_create_collation(db, "utf16_unaligned", SQLITE_UTF16,
3219         0, alignmentCollFunc);
3220     sqlite3_create_collation(db, "utf16_aligned", SQLITE_UTF16_ALIGNED,
3221         0, alignmentCollFunc);
3222   }
3223   return SQLITE_OK;
3224 }
3225 #endif /* !defined(SQLITE_OMIT_UTF16) */
3226 
3227 /*
3228 ** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
3229 **
3230 ** This function is used to test that SQLite selects the correct user
3231 ** function callback when multiple versions (for different text encodings)
3232 ** are available.
3233 **
3234 ** Calling this routine registers up to three versions of the user function
3235 ** "test_function" with database handle <db>.  If the second argument is
3236 ** true, then a version of test_function is registered for UTF-8, if the
3237 ** third is true, a version is registered for UTF-16le, if the fourth is
3238 ** true, a UTF-16be version is available.  Previous versions of
3239 ** test_function are deleted.
3240 **
3241 ** The user function is implemented by calling the following TCL script:
3242 **
3243 **   "test_function <enc> <arg>"
3244 **
3245 ** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
3246 ** single argument passed to the SQL function. The value returned by
3247 ** the TCL script is used as the return value of the SQL function. It
3248 ** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
3249 ** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
3250 ** prefers UTF-16BE.
3251 */
3252 #ifndef SQLITE_OMIT_UTF16
3253 static void test_function_utf8(
3254   sqlite3_context *pCtx,
3255   int nArg,
3256   sqlite3_value **argv
3257 ){
3258   Tcl_Interp *interp;
3259   Tcl_Obj *pX;
3260   sqlite3_value *pVal;
3261   interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
3262   pX = Tcl_NewStringObj("test_function", -1);
3263   Tcl_IncrRefCount(pX);
3264   Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
3265   Tcl_ListObjAppendElement(interp, pX,
3266       Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
3267   Tcl_EvalObjEx(interp, pX, 0);
3268   Tcl_DecrRefCount(pX);
3269   sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
3270   pVal = sqlite3ValueNew(0);
3271   sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
3272       SQLITE_UTF8, SQLITE_STATIC);
3273   sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
3274       -1, SQLITE_TRANSIENT);
3275   sqlite3ValueFree(pVal);
3276 }
3277 static void test_function_utf16le(
3278   sqlite3_context *pCtx,
3279   int nArg,
3280   sqlite3_value **argv
3281 ){
3282   Tcl_Interp *interp;
3283   Tcl_Obj *pX;
3284   sqlite3_value *pVal;
3285   interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
3286   pX = Tcl_NewStringObj("test_function", -1);
3287   Tcl_IncrRefCount(pX);
3288   Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
3289   Tcl_ListObjAppendElement(interp, pX,
3290       Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
3291   Tcl_EvalObjEx(interp, pX, 0);
3292   Tcl_DecrRefCount(pX);
3293   pVal = sqlite3ValueNew(0);
3294   sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
3295       SQLITE_UTF8, SQLITE_STATIC);
3296   sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
3297   sqlite3ValueFree(pVal);
3298 }
3299 static void test_function_utf16be(
3300   sqlite3_context *pCtx,
3301   int nArg,
3302   sqlite3_value **argv
3303 ){
3304   Tcl_Interp *interp;
3305   Tcl_Obj *pX;
3306   sqlite3_value *pVal;
3307   interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
3308   pX = Tcl_NewStringObj("test_function", -1);
3309   Tcl_IncrRefCount(pX);
3310   Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
3311   Tcl_ListObjAppendElement(interp, pX,
3312       Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
3313   Tcl_EvalObjEx(interp, pX, 0);
3314   Tcl_DecrRefCount(pX);
3315   pVal = sqlite3ValueNew(0);
3316   sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
3317       SQLITE_UTF8, SQLITE_STATIC);
3318   sqlite3_result_text16(pCtx, sqlite3_value_text16le(pVal),
3319       -1, SQLITE_TRANSIENT);
3320   sqlite3_result_text16be(pCtx, sqlite3_value_text16le(pVal),
3321       -1, SQLITE_TRANSIENT);
3322   sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
3323       -1, SQLITE_TRANSIENT);
3324   sqlite3ValueFree(pVal);
3325 }
3326 #endif /* SQLITE_OMIT_UTF16 */
3327 static int SQLITE_TCLAPI test_function(
3328   void * clientData,
3329   Tcl_Interp *interp,
3330   int objc,
3331   Tcl_Obj *CONST objv[]
3332 ){
3333 #ifndef SQLITE_OMIT_UTF16
3334   sqlite3 *db;
3335   int val;
3336 
3337   if( objc!=5 ) goto bad_args;
3338   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3339 
3340   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
3341   if( val ){
3342     sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
3343         interp, test_function_utf8, 0, 0);
3344   }
3345   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
3346   if( val ){
3347     sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
3348         interp, test_function_utf16le, 0, 0);
3349   }
3350   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
3351   if( val ){
3352     sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
3353         interp, test_function_utf16be, 0, 0);
3354   }
3355 
3356   return TCL_OK;
3357 bad_args:
3358   Tcl_AppendResult(interp, "wrong # args: should be \"",
3359       Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
3360 #endif /* SQLITE_OMIT_UTF16 */
3361   return TCL_ERROR;
3362 }
3363 
3364 /*
3365 ** Usage:         sqlite3_test_errstr <err code>
3366 **
3367 ** Test that the english language string equivalents for sqlite error codes
3368 ** are sane. The parameter is an integer representing an sqlite error code.
3369 ** The result is a list of two elements, the string representation of the
3370 ** error code and the english language explanation.
3371 */
3372 static int SQLITE_TCLAPI test_errstr(
3373   void * clientData,
3374   Tcl_Interp *interp,
3375   int objc,
3376   Tcl_Obj *CONST objv[]
3377 ){
3378   char *zCode;
3379   int i;
3380   if( objc!=1 ){
3381     Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
3382   }
3383 
3384   zCode = Tcl_GetString(objv[1]);
3385   for(i=0; i<200; i++){
3386     if( 0==strcmp(t1ErrorName(i), zCode) ) break;
3387   }
3388   Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
3389   return TCL_OK;
3390 }
3391 
3392 /*
3393 ** Usage:    breakpoint
3394 **
3395 ** This routine exists for one purpose - to provide a place to put a
3396 ** breakpoint with GDB that can be triggered using TCL code.  The use
3397 ** for this is when a particular test fails on (say) the 1485th iteration.
3398 ** In the TCL test script, we can add code like this:
3399 **
3400 **     if {$i==1485} breakpoint
3401 **
3402 ** Then run testfixture in the debugger and wait for the breakpoint to
3403 ** fire.  Then additional breakpoints can be set to trace down the bug.
3404 */
3405 static int SQLITE_TCLAPI test_breakpoint(
3406   void *NotUsed,
3407   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
3408   int argc,              /* Number of arguments */
3409   char **argv            /* Text of each argument */
3410 ){
3411   return TCL_OK;         /* Do nothing */
3412 }
3413 
3414 /*
3415 ** Usage:   sqlite3_bind_zeroblob  STMT IDX N
3416 **
3417 ** Test the sqlite3_bind_zeroblob interface.  STMT is a prepared statement.
3418 ** IDX is the index of a wildcard in the prepared statement.  This command
3419 ** binds a N-byte zero-filled BLOB to the wildcard.
3420 */
3421 static int SQLITE_TCLAPI test_bind_zeroblob(
3422   void * clientData,
3423   Tcl_Interp *interp,
3424   int objc,
3425   Tcl_Obj *CONST objv[]
3426 ){
3427   sqlite3_stmt *pStmt;
3428   int idx;
3429   int n;
3430   int rc;
3431 
3432   if( objc!=4 ){
3433     Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N");
3434     return TCL_ERROR;
3435   }
3436 
3437   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3438   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3439   if( Tcl_GetIntFromObj(interp, objv[3], &n) ) return TCL_ERROR;
3440 
3441   rc = sqlite3_bind_zeroblob(pStmt, idx, n);
3442   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3443   if( rc!=SQLITE_OK ){
3444     return TCL_ERROR;
3445   }
3446 
3447   return TCL_OK;
3448 }
3449 
3450 /*
3451 ** Usage:   sqlite3_bind_zeroblob64  STMT IDX N
3452 **
3453 ** Test the sqlite3_bind_zeroblob64 interface.  STMT is a prepared statement.
3454 ** IDX is the index of a wildcard in the prepared statement.  This command
3455 ** binds a N-byte zero-filled BLOB to the wildcard.
3456 */
3457 static int SQLITE_TCLAPI test_bind_zeroblob64(
3458   void * clientData,
3459   Tcl_Interp *interp,
3460   int objc,
3461   Tcl_Obj *CONST objv[]
3462 ){
3463   sqlite3_stmt *pStmt;
3464   int idx;
3465   Tcl_WideInt n;
3466   int rc;
3467 
3468   if( objc!=4 ){
3469     Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N");
3470     return TCL_ERROR;
3471   }
3472 
3473   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3474   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3475   if( Tcl_GetWideIntFromObj(interp, objv[3], &n) ) return TCL_ERROR;
3476 
3477   rc = sqlite3_bind_zeroblob64(pStmt, idx, n);
3478   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3479   if( rc!=SQLITE_OK ){
3480     Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
3481     return TCL_ERROR;
3482   }
3483 
3484   return TCL_OK;
3485 }
3486 
3487 /*
3488 ** Usage:   sqlite3_bind_int  STMT N VALUE
3489 **
3490 ** Test the sqlite3_bind_int interface.  STMT is a prepared statement.
3491 ** N is the index of a wildcard in the prepared statement.  This command
3492 ** binds a 32-bit integer VALUE to that wildcard.
3493 */
3494 static int SQLITE_TCLAPI test_bind_int(
3495   void * clientData,
3496   Tcl_Interp *interp,
3497   int objc,
3498   Tcl_Obj *CONST objv[]
3499 ){
3500   sqlite3_stmt *pStmt;
3501   int idx;
3502   int value;
3503   int rc;
3504 
3505   if( objc!=4 ){
3506     Tcl_AppendResult(interp, "wrong # args: should be \"",
3507         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
3508     return TCL_ERROR;
3509   }
3510 
3511   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3512   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3513   if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
3514 
3515   rc = sqlite3_bind_int(pStmt, idx, value);
3516   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3517   if( rc!=SQLITE_OK ){
3518     return TCL_ERROR;
3519   }
3520 
3521   return TCL_OK;
3522 }
3523 
3524 
3525 /*
3526 ** Usage:   intarray_addr  INT  ...
3527 **
3528 ** Return the address of a C-language array of 32-bit integers.
3529 **
3530 ** Space to hold the array is obtained from malloc().  Call this procedure once
3531 ** with no arguments in order to release memory.  Each call to this procedure
3532 ** overwrites the previous array.
3533 */
3534 static int SQLITE_TCLAPI test_intarray_addr(
3535   void * clientData,
3536   Tcl_Interp *interp,
3537   int objc,
3538   Tcl_Obj *CONST objv[]
3539 ){
3540   int i;
3541   static int *p = 0;
3542 
3543   sqlite3_free(p);
3544   p = 0;
3545   if( objc>1 ){
3546     p = sqlite3_malloc( sizeof(p[0])*(objc-1) );
3547     if( p==0 ) return TCL_ERROR;
3548     for(i=0; i<objc-1; i++){
3549       if( Tcl_GetIntFromObj(interp, objv[1+i], &p[i]) ){
3550         sqlite3_free(p);
3551         p = 0;
3552         return TCL_ERROR;
3553       }
3554     }
3555   }
3556   Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p));
3557   return TCL_OK;
3558 }
3559 /*
3560 ** Usage:   intarray_addr  INT  ...
3561 **
3562 ** Return the address of a C-language array of 32-bit integers.
3563 **
3564 ** Space to hold the array is obtained from malloc().  Call this procedure once
3565 ** with no arguments in order to release memory.  Each call to this procedure
3566 ** overwrites the previous array.
3567 */
3568 static int SQLITE_TCLAPI test_int64array_addr(
3569   void * clientData,
3570   Tcl_Interp *interp,
3571   int objc,
3572   Tcl_Obj *CONST objv[]
3573 ){
3574   int i;
3575   static sqlite3_int64 *p = 0;
3576 
3577   sqlite3_free(p);
3578   p = 0;
3579   if( objc>1 ){
3580     p = sqlite3_malloc( sizeof(p[0])*(objc-1) );
3581     if( p==0 ) return TCL_ERROR;
3582     for(i=0; i<objc-1; i++){
3583       Tcl_WideInt v;
3584       if( Tcl_GetWideIntFromObj(interp, objv[1+i], &v) ){
3585         sqlite3_free(p);
3586         p = 0;
3587         return TCL_ERROR;
3588       }
3589       p[i] = v;
3590     }
3591   }
3592   Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p));
3593   return TCL_OK;
3594 }
3595 /*
3596 ** Usage:   doublearray_addr  INT  ...
3597 **
3598 ** Return the address of a C-language array of doubles.
3599 **
3600 ** Space to hold the array is obtained from malloc().  Call this procedure once
3601 ** with no arguments in order to release memory.  Each call to this procedure
3602 ** overwrites the previous array.
3603 */
3604 static int SQLITE_TCLAPI test_doublearray_addr(
3605   void * clientData,
3606   Tcl_Interp *interp,
3607   int objc,
3608   Tcl_Obj *CONST objv[]
3609 ){
3610   int i;
3611   static double *p = 0;
3612 
3613   sqlite3_free(p);
3614   p = 0;
3615   if( objc>1 ){
3616     p = sqlite3_malloc( sizeof(p[0])*(objc-1) );
3617     if( p==0 ) return TCL_ERROR;
3618     for(i=0; i<objc-1; i++){
3619       if( Tcl_GetDoubleFromObj(interp, objv[1+i], &p[i]) ){
3620         sqlite3_free(p);
3621         p = 0;
3622         return TCL_ERROR;
3623       }
3624     }
3625   }
3626   Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p));
3627   return TCL_OK;
3628 }
3629 /*
3630 ** Usage:   textarray_addr  TEXT ...
3631 **
3632 ** Return the address of a C-language array of strings.
3633 **
3634 ** Space to hold the array is obtained from malloc().  Call this procedure once
3635 ** with no arguments in order to release memory.  Each call to this procedure
3636 ** overwrites the previous array.
3637 */
3638 static int SQLITE_TCLAPI test_textarray_addr(
3639   void * clientData,
3640   Tcl_Interp *interp,
3641   int objc,
3642   Tcl_Obj *CONST objv[]
3643 ){
3644   int i;
3645   static int n = 0;
3646   static char **p = 0;
3647 
3648   for(i=0; i<n; i++) sqlite3_free(p[i]);
3649   sqlite3_free(p);
3650   p = 0;
3651   if( objc>1 ){
3652     p = sqlite3_malloc( sizeof(p[0])*(objc-1) );
3653     if( p==0 ) return TCL_ERROR;
3654     for(i=0; i<objc-1; i++){
3655       p[i] = sqlite3_mprintf("%s", Tcl_GetString(objv[1+i]));
3656     }
3657   }
3658   n = objc-1;
3659   Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p));
3660   return TCL_OK;
3661 }
3662 
3663 
3664 /*
3665 ** Usage:   sqlite3_bind_int64  STMT N VALUE
3666 **
3667 ** Test the sqlite3_bind_int64 interface.  STMT is a prepared statement.
3668 ** N is the index of a wildcard in the prepared statement.  This command
3669 ** binds a 64-bit integer VALUE to that wildcard.
3670 */
3671 static int SQLITE_TCLAPI test_bind_int64(
3672   void * clientData,
3673   Tcl_Interp *interp,
3674   int objc,
3675   Tcl_Obj *CONST objv[]
3676 ){
3677   sqlite3_stmt *pStmt;
3678   int idx;
3679   Tcl_WideInt value;
3680   int rc;
3681 
3682   if( objc!=4 ){
3683     Tcl_AppendResult(interp, "wrong # args: should be \"",
3684         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
3685     return TCL_ERROR;
3686   }
3687 
3688   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3689   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3690   if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
3691 
3692   rc = sqlite3_bind_int64(pStmt, idx, value);
3693   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3694   if( rc!=SQLITE_OK ){
3695     return TCL_ERROR;
3696   }
3697 
3698   return TCL_OK;
3699 }
3700 
3701 
3702 /*
3703 ** Usage:   sqlite3_bind_double  STMT N VALUE
3704 **
3705 ** Test the sqlite3_bind_double interface.  STMT is a prepared statement.
3706 ** N is the index of a wildcard in the prepared statement.  This command
3707 ** binds a 64-bit integer VALUE to that wildcard.
3708 */
3709 static int SQLITE_TCLAPI test_bind_double(
3710   void * clientData,
3711   Tcl_Interp *interp,
3712   int objc,
3713   Tcl_Obj *CONST objv[]
3714 ){
3715   sqlite3_stmt *pStmt;
3716   int idx;
3717   double value = 0;
3718   int rc;
3719   const char *zVal;
3720   int i;
3721   static const struct {
3722     const char *zName;     /* Name of the special floating point value */
3723     unsigned int iUpper;   /* Upper 32 bits */
3724     unsigned int iLower;   /* Lower 32 bits */
3725   } aSpecialFp[] = {
3726     {  "NaN",      0x7fffffff, 0xffffffff },
3727     {  "SNaN",     0x7ff7ffff, 0xffffffff },
3728     {  "-NaN",     0xffffffff, 0xffffffff },
3729     {  "-SNaN",    0xfff7ffff, 0xffffffff },
3730     {  "+Inf",     0x7ff00000, 0x00000000 },
3731     {  "-Inf",     0xfff00000, 0x00000000 },
3732     {  "Epsilon",  0x00000000, 0x00000001 },
3733     {  "-Epsilon", 0x80000000, 0x00000001 },
3734     {  "NaN0",     0x7ff80000, 0x00000000 },
3735     {  "-NaN0",    0xfff80000, 0x00000000 },
3736   };
3737 
3738   if( objc!=4 ){
3739     Tcl_AppendResult(interp, "wrong # args: should be \"",
3740         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
3741     return TCL_ERROR;
3742   }
3743 
3744   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3745   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3746 
3747   /* Intercept the string "NaN" and generate a NaN value for it.
3748   ** All other strings are passed through to Tcl_GetDoubleFromObj().
3749   ** Tcl_GetDoubleFromObj() should understand "NaN" but some versions
3750   ** contain a bug.
3751   */
3752   zVal = Tcl_GetString(objv[3]);
3753   for(i=0; i<sizeof(aSpecialFp)/sizeof(aSpecialFp[0]); i++){
3754     if( strcmp(aSpecialFp[i].zName, zVal)==0 ){
3755       sqlite3_uint64 x;
3756       x = aSpecialFp[i].iUpper;
3757       x <<= 32;
3758       x |= aSpecialFp[i].iLower;
3759       assert( sizeof(value)==8 );
3760       assert( sizeof(x)==8 );
3761       memcpy(&value, &x, 8);
3762       break;
3763     }
3764   }
3765   if( i>=sizeof(aSpecialFp)/sizeof(aSpecialFp[0]) &&
3766          Tcl_GetDoubleFromObj(interp, objv[3], &value) ){
3767     return TCL_ERROR;
3768   }
3769   rc = sqlite3_bind_double(pStmt, idx, value);
3770   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3771   if( rc!=SQLITE_OK ){
3772     return TCL_ERROR;
3773   }
3774 
3775   return TCL_OK;
3776 }
3777 
3778 /*
3779 ** Usage:   sqlite3_bind_null  STMT N
3780 **
3781 ** Test the sqlite3_bind_null interface.  STMT is a prepared statement.
3782 ** N is the index of a wildcard in the prepared statement.  This command
3783 ** binds a NULL to the wildcard.
3784 */
3785 static int SQLITE_TCLAPI test_bind_null(
3786   void * clientData,
3787   Tcl_Interp *interp,
3788   int objc,
3789   Tcl_Obj *CONST objv[]
3790 ){
3791   sqlite3_stmt *pStmt;
3792   int idx;
3793   int rc;
3794 
3795   if( objc!=3 ){
3796     Tcl_AppendResult(interp, "wrong # args: should be \"",
3797         Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
3798     return TCL_ERROR;
3799   }
3800 
3801   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3802   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3803 
3804   rc = sqlite3_bind_null(pStmt, idx);
3805   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3806   if( rc!=SQLITE_OK ){
3807     return TCL_ERROR;
3808   }
3809 
3810   return TCL_OK;
3811 }
3812 
3813 /*
3814 ** Usage:   sqlite3_bind_text  STMT N STRING BYTES
3815 **
3816 ** Test the sqlite3_bind_text interface.  STMT is a prepared statement.
3817 ** N is the index of a wildcard in the prepared statement.  This command
3818 ** binds a UTF-8 string STRING to the wildcard.  The string is BYTES bytes
3819 ** long.
3820 */
3821 static int SQLITE_TCLAPI test_bind_text(
3822   void * clientData,
3823   Tcl_Interp *interp,
3824   int objc,
3825   Tcl_Obj *CONST objv[]
3826 ){
3827   sqlite3_stmt *pStmt;
3828   int idx;
3829   int bytes;
3830   char *value;
3831   int rc;
3832 
3833   if( objc!=5 ){
3834     Tcl_AppendResult(interp, "wrong # args: should be \"",
3835         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
3836     return TCL_ERROR;
3837   }
3838 
3839   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3840   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3841   value = (char*)Tcl_GetByteArrayFromObj(objv[3], &bytes);
3842   if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
3843 
3844   rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
3845   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3846   if( rc!=SQLITE_OK ){
3847     Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
3848     return TCL_ERROR;
3849   }
3850 
3851   return TCL_OK;
3852 }
3853 
3854 /*
3855 ** Usage:   sqlite3_bind_text16 ?-static? STMT N STRING BYTES
3856 **
3857 ** Test the sqlite3_bind_text16 interface.  STMT is a prepared statement.
3858 ** N is the index of a wildcard in the prepared statement.  This command
3859 ** binds a UTF-16 string STRING to the wildcard.  The string is BYTES bytes
3860 ** long.
3861 */
3862 static int SQLITE_TCLAPI test_bind_text16(
3863   void * clientData,
3864   Tcl_Interp *interp,
3865   int objc,
3866   Tcl_Obj *CONST objv[]
3867 ){
3868 #ifndef SQLITE_OMIT_UTF16
3869   sqlite3_stmt *pStmt;
3870   int idx;
3871   int bytes;
3872   char *value;
3873   int rc;
3874 
3875   void (*xDel)(void*) = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
3876   Tcl_Obj *oStmt    = objv[objc-4];
3877   Tcl_Obj *oN       = objv[objc-3];
3878   Tcl_Obj *oString  = objv[objc-2];
3879   Tcl_Obj *oBytes   = objv[objc-1];
3880 
3881   if( objc!=5 && objc!=6){
3882     Tcl_AppendResult(interp, "wrong # args: should be \"",
3883         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
3884     return TCL_ERROR;
3885   }
3886 
3887   if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR;
3888   if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR;
3889   value = (char*)Tcl_GetByteArrayFromObj(oString, 0);
3890   if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR;
3891 
3892   rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel);
3893   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3894   if( rc!=SQLITE_OK ){
3895     Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
3896     return TCL_ERROR;
3897   }
3898 
3899 #endif /* SQLITE_OMIT_UTF16 */
3900   return TCL_OK;
3901 }
3902 
3903 /*
3904 ** Usage:   sqlite3_bind_blob ?-static? STMT N DATA BYTES
3905 **
3906 ** Test the sqlite3_bind_blob interface.  STMT is a prepared statement.
3907 ** N is the index of a wildcard in the prepared statement.  This command
3908 ** binds a BLOB to the wildcard.  The BLOB is BYTES bytes in size.
3909 */
3910 static int SQLITE_TCLAPI test_bind_blob(
3911   void * clientData,
3912   Tcl_Interp *interp,
3913   int objc,
3914   Tcl_Obj *CONST objv[]
3915 ){
3916   sqlite3_stmt *pStmt;
3917   int len, idx;
3918   int bytes;
3919   char *value;
3920   int rc;
3921   sqlite3_destructor_type xDestructor = SQLITE_TRANSIENT;
3922 
3923   if( objc!=5 && objc!=6 ){
3924     Tcl_AppendResult(interp, "wrong # args: should be \"",
3925         Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
3926     return TCL_ERROR;
3927   }
3928 
3929   if( objc==6 ){
3930     xDestructor = SQLITE_STATIC;
3931     objv++;
3932   }
3933 
3934   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3935   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3936 
3937   value = (char*)Tcl_GetByteArrayFromObj(objv[3], &len);
3938   if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
3939 
3940   if( bytes>len ){
3941     char zBuf[200];
3942     sqlite3_snprintf(sizeof(zBuf), zBuf,
3943                      "cannot use %d blob bytes, have %d", bytes, len);
3944     Tcl_AppendResult(interp, zBuf, -1);
3945     return TCL_ERROR;
3946   }
3947 
3948   rc = sqlite3_bind_blob(pStmt, idx, value, bytes, xDestructor);
3949   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3950   if( rc!=SQLITE_OK ){
3951     return TCL_ERROR;
3952   }
3953 
3954   return TCL_OK;
3955 }
3956 
3957 /*
3958 ** Usage:   sqlite3_bind_parameter_count  STMT
3959 **
3960 ** Return the number of wildcards in the given statement.
3961 */
3962 static int SQLITE_TCLAPI test_bind_parameter_count(
3963   void * clientData,
3964   Tcl_Interp *interp,
3965   int objc,
3966   Tcl_Obj *CONST objv[]
3967 ){
3968   sqlite3_stmt *pStmt;
3969 
3970   if( objc!=2 ){
3971     Tcl_WrongNumArgs(interp, 1, objv, "STMT");
3972     return TCL_ERROR;
3973   }
3974   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3975   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
3976   return TCL_OK;
3977 }
3978 
3979 /*
3980 ** Usage:   sqlite3_bind_parameter_name  STMT  N
3981 **
3982 ** Return the name of the Nth wildcard.  The first wildcard is 1.
3983 ** An empty string is returned if N is out of range or if the wildcard
3984 ** is nameless.
3985 */
3986 static int SQLITE_TCLAPI test_bind_parameter_name(
3987   void * clientData,
3988   Tcl_Interp *interp,
3989   int objc,
3990   Tcl_Obj *CONST objv[]
3991 ){
3992   sqlite3_stmt *pStmt;
3993   int i;
3994 
3995   if( objc!=3 ){
3996     Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
3997     return TCL_ERROR;
3998   }
3999   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4000   if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
4001   Tcl_SetObjResult(interp,
4002      Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
4003   );
4004   return TCL_OK;
4005 }
4006 
4007 /*
4008 ** Usage:   sqlite3_bind_parameter_index  STMT  NAME
4009 **
4010 ** Return the index of the wildcard called NAME.  Return 0 if there is
4011 ** no such wildcard.
4012 */
4013 static int SQLITE_TCLAPI test_bind_parameter_index(
4014   void * clientData,
4015   Tcl_Interp *interp,
4016   int objc,
4017   Tcl_Obj *CONST objv[]
4018 ){
4019   sqlite3_stmt *pStmt;
4020 
4021   if( objc!=3 ){
4022     Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
4023     return TCL_ERROR;
4024   }
4025   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4026   Tcl_SetObjResult(interp,
4027      Tcl_NewIntObj(
4028        sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
4029      )
4030   );
4031   return TCL_OK;
4032 }
4033 
4034 /*
4035 ** Usage:   sqlite3_clear_bindings STMT
4036 **
4037 */
4038 static int SQLITE_TCLAPI test_clear_bindings(
4039   void * clientData,
4040   Tcl_Interp *interp,
4041   int objc,
4042   Tcl_Obj *CONST objv[]
4043 ){
4044   sqlite3_stmt *pStmt;
4045 
4046   if( objc!=2 ){
4047     Tcl_WrongNumArgs(interp, 1, objv, "STMT");
4048     return TCL_ERROR;
4049   }
4050   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4051   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
4052   return TCL_OK;
4053 }
4054 
4055 /*
4056 ** Usage:   sqlite3_sleep MILLISECONDS
4057 */
4058 static int SQLITE_TCLAPI test_sleep(
4059   void * clientData,
4060   Tcl_Interp *interp,
4061   int objc,
4062   Tcl_Obj *CONST objv[]
4063 ){
4064   int ms;
4065 
4066   if( objc!=2 ){
4067     Tcl_WrongNumArgs(interp, 1, objv, "MILLISECONDS");
4068     return TCL_ERROR;
4069   }
4070   if( Tcl_GetIntFromObj(interp, objv[1], &ms) ){
4071     return TCL_ERROR;
4072   }
4073   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(ms)));
4074   return TCL_OK;
4075 }
4076 
4077 /*
4078 ** Usage: sqlite3_extended_errcode DB
4079 **
4080 ** Return the string representation of the most recent sqlite3_* API
4081 ** error code. e.g. "SQLITE_ERROR".
4082 */
4083 static int SQLITE_TCLAPI test_ex_errcode(
4084   void * clientData,
4085   Tcl_Interp *interp,
4086   int objc,
4087   Tcl_Obj *CONST objv[]
4088 ){
4089   sqlite3 *db;
4090   int rc;
4091 
4092   if( objc!=2 ){
4093     Tcl_AppendResult(interp, "wrong # args: should be \"",
4094        Tcl_GetString(objv[0]), " DB", 0);
4095     return TCL_ERROR;
4096   }
4097   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4098   rc = sqlite3_extended_errcode(db);
4099   Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0);
4100   return TCL_OK;
4101 }
4102 
4103 
4104 /*
4105 ** Usage: sqlite3_errcode DB
4106 **
4107 ** Return the string representation of the most recent sqlite3_* API
4108 ** error code. e.g. "SQLITE_ERROR".
4109 */
4110 static int SQLITE_TCLAPI test_errcode(
4111   void * clientData,
4112   Tcl_Interp *interp,
4113   int objc,
4114   Tcl_Obj *CONST objv[]
4115 ){
4116   sqlite3 *db;
4117   int rc;
4118 
4119   if( objc!=2 ){
4120     Tcl_AppendResult(interp, "wrong # args: should be \"",
4121        Tcl_GetString(objv[0]), " DB", 0);
4122     return TCL_ERROR;
4123   }
4124   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4125   rc = sqlite3_errcode(db);
4126   Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0);
4127   return TCL_OK;
4128 }
4129 
4130 /*
4131 ** Usage:   sqlite3_errmsg DB
4132 **
4133 ** Returns the UTF-8 representation of the error message string for the
4134 ** most recent sqlite3_* API call.
4135 */
4136 static int SQLITE_TCLAPI test_errmsg(
4137   void * clientData,
4138   Tcl_Interp *interp,
4139   int objc,
4140   Tcl_Obj *CONST objv[]
4141 ){
4142   sqlite3 *db;
4143   const char *zErr;
4144 
4145   if( objc!=2 ){
4146     Tcl_AppendResult(interp, "wrong # args: should be \"",
4147        Tcl_GetString(objv[0]), " DB", 0);
4148     return TCL_ERROR;
4149   }
4150   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4151 
4152   zErr = sqlite3_errmsg(db);
4153   Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
4154   return TCL_OK;
4155 }
4156 
4157 /*
4158 ** Usage:   test_errmsg16 DB
4159 **
4160 ** Returns the UTF-16 representation of the error message string for the
4161 ** most recent sqlite3_* API call. This is a byte array object at the TCL
4162 ** level, and it includes the 0x00 0x00 terminator bytes at the end of the
4163 ** UTF-16 string.
4164 */
4165 static int SQLITE_TCLAPI test_errmsg16(
4166   void * clientData,
4167   Tcl_Interp *interp,
4168   int objc,
4169   Tcl_Obj *CONST objv[]
4170 ){
4171 #ifndef SQLITE_OMIT_UTF16
4172   sqlite3 *db;
4173   const void *zErr;
4174   const char *z;
4175   int bytes = 0;
4176 
4177   if( objc!=2 ){
4178     Tcl_AppendResult(interp, "wrong # args: should be \"",
4179        Tcl_GetString(objv[0]), " DB", 0);
4180     return TCL_ERROR;
4181   }
4182   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4183 
4184   zErr = sqlite3_errmsg16(db);
4185   if( zErr ){
4186     z = zErr;
4187     for(bytes=0; z[bytes] || z[bytes+1]; bytes+=2){}
4188   }
4189   Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
4190 #endif /* SQLITE_OMIT_UTF16 */
4191   return TCL_OK;
4192 }
4193 
4194 /*
4195 ** Usage: sqlite3_prepare DB sql bytes ?tailvar?
4196 **
4197 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
4198 ** database handle <DB>. The parameter <tailval> is the name of a global
4199 ** variable that is set to the unused portion of <sql> (if any). A
4200 ** STMT handle is returned.
4201 */
4202 static int SQLITE_TCLAPI test_prepare(
4203   void * clientData,
4204   Tcl_Interp *interp,
4205   int objc,
4206   Tcl_Obj *CONST objv[]
4207 ){
4208   sqlite3 *db;
4209   const char *zSql;
4210   int bytes;
4211   const char *zTail = 0;
4212   sqlite3_stmt *pStmt = 0;
4213   char zBuf[50];
4214   int rc;
4215 
4216   if( objc!=5 && objc!=4 ){
4217     Tcl_AppendResult(interp, "wrong # args: should be \"",
4218        Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
4219     return TCL_ERROR;
4220   }
4221   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4222   zSql = Tcl_GetString(objv[2]);
4223   if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
4224 
4225   rc = sqlite3_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
4226   Tcl_ResetResult(interp);
4227   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
4228   if( zTail && objc>=5 ){
4229     if( bytes>=0 ){
4230       bytes = bytes - (int)(zTail-zSql);
4231     }
4232     if( (int)strlen(zTail)<bytes ){
4233       bytes = (int)strlen(zTail);
4234     }
4235     Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
4236   }
4237   if( rc!=SQLITE_OK ){
4238     assert( pStmt==0 );
4239     sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
4240     Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
4241     return TCL_ERROR;
4242   }
4243 
4244   if( pStmt ){
4245     if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
4246     Tcl_AppendResult(interp, zBuf, 0);
4247   }
4248   return TCL_OK;
4249 }
4250 
4251 /*
4252 ** Usage: sqlite3_prepare_v2 DB sql bytes ?tailvar?
4253 **
4254 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
4255 ** database handle <DB>. The parameter <tailval> is the name of a global
4256 ** variable that is set to the unused portion of <sql> (if any). A
4257 ** STMT handle is returned.
4258 */
4259 static int SQLITE_TCLAPI test_prepare_v2(
4260   void * clientData,
4261   Tcl_Interp *interp,
4262   int objc,
4263   Tcl_Obj *CONST objv[]
4264 ){
4265   sqlite3 *db;
4266   const char *zSql;
4267   char *zCopy = 0;                /* malloc() copy of zSql */
4268   int bytes;
4269   const char *zTail = 0;
4270   const char **pzTail;
4271   sqlite3_stmt *pStmt = 0;
4272   char zBuf[50];
4273   int rc;
4274 
4275   if( objc!=5 && objc!=4 ){
4276     Tcl_AppendResult(interp, "wrong # args: should be \"",
4277        Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
4278     return TCL_ERROR;
4279   }
4280   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4281   zSql = Tcl_GetString(objv[2]);
4282   if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
4283 
4284   /* Instead of using zSql directly, make a copy into a buffer obtained
4285   ** directly from malloc(). The idea is to make it easier for valgrind
4286   ** to spot buffer overreads.  */
4287   if( bytes>=0 ){
4288     zCopy = malloc(bytes);
4289     memcpy(zCopy, zSql, bytes);
4290   }else{
4291     int n = (int)strlen(zSql) + 1;
4292     zCopy = malloc(n);
4293     memcpy(zCopy, zSql, n);
4294   }
4295   pzTail = objc>=5 ? &zTail : 0;
4296   rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, pzTail);
4297   if( objc>=5 ){
4298     zTail = &zSql[(zTail - zCopy)];
4299   }
4300   free(zCopy);
4301 
4302   assert(rc==SQLITE_OK || pStmt==0);
4303   Tcl_ResetResult(interp);
4304   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
4305   if( rc==SQLITE_OK && objc>=5 && zTail ){
4306     if( bytes>=0 ){
4307       bytes = bytes - (int)(zTail-zSql);
4308     }
4309     Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
4310   }
4311   if( rc!=SQLITE_OK ){
4312     assert( pStmt==0 );
4313     sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
4314     Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
4315     return TCL_ERROR;
4316   }
4317 
4318   if( pStmt ){
4319     if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
4320     Tcl_AppendResult(interp, zBuf, 0);
4321   }
4322   return TCL_OK;
4323 }
4324 
4325 /*
4326 ** Usage: sqlite3_prepare_v3 DB sql bytes flags ?tailvar?
4327 **
4328 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
4329 ** database handle <DB> and flags <flags>. The parameter <tailval> is
4330 ** the name of a global variable that is set to the unused portion of
4331 ** <sql> (if any). A STMT handle is returned.
4332 */
4333 static int SQLITE_TCLAPI test_prepare_v3(
4334   void * clientData,
4335   Tcl_Interp *interp,
4336   int objc,
4337   Tcl_Obj *CONST objv[]
4338 ){
4339   sqlite3 *db;
4340   const char *zSql;
4341   char *zCopy = 0;                /* malloc() copy of zSql */
4342   int bytes, flags;
4343   const char *zTail = 0;
4344   const char **pzTail;
4345   sqlite3_stmt *pStmt = 0;
4346   char zBuf[50];
4347   int rc;
4348 
4349   if( objc!=6 && objc!=5 ){
4350     Tcl_AppendResult(interp, "wrong # args: should be \"",
4351        Tcl_GetString(objv[0]), " DB sql bytes flags tailvar", 0);
4352     return TCL_ERROR;
4353   }
4354   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4355   zSql = Tcl_GetString(objv[2]);
4356   if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
4357   if( Tcl_GetIntFromObj(interp, objv[4], &flags) ) return TCL_ERROR;
4358 
4359   /* Instead of using zSql directly, make a copy into a buffer obtained
4360   ** directly from malloc(). The idea is to make it easier for valgrind
4361   ** to spot buffer overreads.  */
4362   if( bytes>=0 ){
4363     zCopy = malloc(bytes);
4364     memcpy(zCopy, zSql, bytes);
4365   }else{
4366     int n = (int)strlen(zSql) + 1;
4367     zCopy = malloc(n);
4368     memcpy(zCopy, zSql, n);
4369   }
4370   pzTail = objc>=6 ? &zTail : 0;
4371   rc = sqlite3_prepare_v3(db, zCopy, bytes, (unsigned int)flags,&pStmt,pzTail);
4372   free(zCopy);
4373   zTail = &zSql[(zTail - zCopy)];
4374 
4375   assert(rc==SQLITE_OK || pStmt==0);
4376   Tcl_ResetResult(interp);
4377   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
4378   if( rc==SQLITE_OK && zTail && objc>=6 ){
4379     if( bytes>=0 ){
4380       bytes = bytes - (int)(zTail-zSql);
4381     }
4382     Tcl_ObjSetVar2(interp, objv[5], 0, Tcl_NewStringObj(zTail, bytes), 0);
4383   }
4384   if( rc!=SQLITE_OK ){
4385     assert( pStmt==0 );
4386     sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
4387     Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
4388     return TCL_ERROR;
4389   }
4390 
4391   if( pStmt ){
4392     if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
4393     Tcl_AppendResult(interp, zBuf, 0);
4394   }
4395   return TCL_OK;
4396 }
4397 
4398 /*
4399 ** Usage: sqlite3_prepare_tkt3134 DB
4400 **
4401 ** Generate a prepared statement for a zero-byte string as a test
4402 ** for ticket #3134.  The string should be preceded by a zero byte.
4403 */
4404 static int SQLITE_TCLAPI test_prepare_tkt3134(
4405   void * clientData,
4406   Tcl_Interp *interp,
4407   int objc,
4408   Tcl_Obj *CONST objv[]
4409 ){
4410   sqlite3 *db;
4411   static const char zSql[] = "\000SELECT 1";
4412   sqlite3_stmt *pStmt = 0;
4413   char zBuf[50];
4414   int rc;
4415 
4416   if( objc!=2 ){
4417     Tcl_AppendResult(interp, "wrong # args: should be \"",
4418        Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
4419     return TCL_ERROR;
4420   }
4421   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4422   rc = sqlite3_prepare_v2(db, &zSql[1], 0, &pStmt, 0);
4423   assert(rc==SQLITE_OK || pStmt==0);
4424   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
4425   if( rc!=SQLITE_OK ){
4426     assert( pStmt==0 );
4427     sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
4428     Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
4429     return TCL_ERROR;
4430   }
4431 
4432   if( pStmt ){
4433     if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
4434     Tcl_AppendResult(interp, zBuf, 0);
4435   }
4436   return TCL_OK;
4437 }
4438 
4439 /*
4440 ** Usage: sqlite3_prepare16 DB sql bytes tailvar
4441 **
4442 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
4443 ** database handle <DB>. The parameter <tailval> is the name of a global
4444 ** variable that is set to the unused portion of <sql> (if any). A
4445 ** STMT handle is returned.
4446 */
4447 static int SQLITE_TCLAPI test_prepare16(
4448   void * clientData,
4449   Tcl_Interp *interp,
4450   int objc,
4451   Tcl_Obj *CONST objv[]
4452 ){
4453 #ifndef SQLITE_OMIT_UTF16
4454   sqlite3 *db;
4455   const void *zSql;
4456   const void *zTail = 0;
4457   Tcl_Obj *pTail = 0;
4458   sqlite3_stmt *pStmt = 0;
4459   char zBuf[50];
4460   int rc;
4461   int bytes;                /* The integer specified as arg 3 */
4462   int objlen;               /* The byte-array length of arg 2 */
4463 
4464   if( objc!=5 && objc!=4 ){
4465     Tcl_AppendResult(interp, "wrong # args: should be \"",
4466        Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
4467     return TCL_ERROR;
4468   }
4469   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4470   zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
4471   if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
4472 
4473   rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
4474   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
4475   if( rc ){
4476     return TCL_ERROR;
4477   }
4478 
4479   if( objc>=5 ){
4480     if( zTail ){
4481       objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql);
4482     }else{
4483       objlen = 0;
4484     }
4485     pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
4486     Tcl_IncrRefCount(pTail);
4487     Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
4488     Tcl_DecrRefCount(pTail);
4489   }
4490 
4491   if( pStmt ){
4492     if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
4493   }
4494   Tcl_AppendResult(interp, zBuf, 0);
4495 #endif /* SQLITE_OMIT_UTF16 */
4496   return TCL_OK;
4497 }
4498 
4499 /*
4500 ** Usage: sqlite3_prepare16_v2 DB sql bytes ?tailvar?
4501 **
4502 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
4503 ** database handle <DB>. The parameter <tailval> is the name of a global
4504 ** variable that is set to the unused portion of <sql> (if any). A
4505 ** STMT handle is returned.
4506 */
4507 static int SQLITE_TCLAPI test_prepare16_v2(
4508   void * clientData,
4509   Tcl_Interp *interp,
4510   int objc,
4511   Tcl_Obj *CONST objv[]
4512 ){
4513 #ifndef SQLITE_OMIT_UTF16
4514   sqlite3 *db;
4515   const void *zSql;
4516   const void *zTail = 0;
4517   Tcl_Obj *pTail = 0;
4518   sqlite3_stmt *pStmt = 0;
4519   char zBuf[50];
4520   int rc;
4521   int bytes;                /* The integer specified as arg 3 */
4522   int objlen;               /* The byte-array length of arg 2 */
4523 
4524   if( objc!=5 && objc!=4 ){
4525     Tcl_AppendResult(interp, "wrong # args: should be \"",
4526        Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
4527     return TCL_ERROR;
4528   }
4529   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4530   zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
4531   if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
4532 
4533   rc = sqlite3_prepare16_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
4534   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
4535   if( rc ){
4536     return TCL_ERROR;
4537   }
4538 
4539   if( objc>=5 ){
4540     if( zTail ){
4541       objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql);
4542     }else{
4543       objlen = 0;
4544     }
4545     pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
4546     Tcl_IncrRefCount(pTail);
4547     Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
4548     Tcl_DecrRefCount(pTail);
4549   }
4550 
4551   if( pStmt ){
4552     if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
4553   }
4554   Tcl_AppendResult(interp, zBuf, 0);
4555 #endif /* SQLITE_OMIT_UTF16 */
4556   return TCL_OK;
4557 }
4558 
4559 /*
4560 ** Usage: sqlite3_open filename ?options-list?
4561 */
4562 static int SQLITE_TCLAPI test_open(
4563   void * clientData,
4564   Tcl_Interp *interp,
4565   int objc,
4566   Tcl_Obj *CONST objv[]
4567 ){
4568   const char *zFilename;
4569   sqlite3 *db;
4570   char zBuf[100];
4571 
4572   if( objc!=3 && objc!=2 && objc!=1 ){
4573     Tcl_AppendResult(interp, "wrong # args: should be \"",
4574        Tcl_GetString(objv[0]), " filename options-list", 0);
4575     return TCL_ERROR;
4576   }
4577 
4578   zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0;
4579   sqlite3_open(zFilename, &db);
4580 
4581   if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
4582   Tcl_AppendResult(interp, zBuf, 0);
4583   return TCL_OK;
4584 }
4585 
4586 /*
4587 ** Usage: sqlite3_open_v2 FILENAME FLAGS VFS
4588 */
4589 static int SQLITE_TCLAPI test_open_v2(
4590   void * clientData,
4591   Tcl_Interp *interp,
4592   int objc,
4593   Tcl_Obj *CONST objv[]
4594 ){
4595   const char *zFilename;
4596   const char *zVfs;
4597   int flags = 0;
4598   sqlite3 *db;
4599   int rc;
4600   char zBuf[100];
4601 
4602   int nFlag;
4603   Tcl_Obj **apFlag;
4604   int i;
4605 
4606   if( objc!=4 ){
4607     Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS");
4608     return TCL_ERROR;
4609   }
4610   zFilename = Tcl_GetString(objv[1]);
4611   zVfs = Tcl_GetString(objv[3]);
4612   if( zVfs[0]==0x00 ) zVfs = 0;
4613 
4614   rc = Tcl_ListObjGetElements(interp, objv[2], &nFlag, &apFlag);
4615   if( rc!=TCL_OK ) return rc;
4616   for(i=0; i<nFlag; i++){
4617     int iFlag;
4618     struct OpenFlag {
4619       const char *zFlag;
4620       int flag;
4621     } aFlag[] = {
4622       { "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY },
4623       { "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE },
4624       { "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE },
4625       { "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE },
4626       { "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE },
4627       { "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY },
4628       { "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB },
4629       { "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB },
4630       { "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB },
4631       { "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL },
4632       { "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL },
4633       { "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL },
4634       { "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL },
4635       { "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX },
4636       { "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX },
4637       { "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE },
4638       { "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE },
4639       { "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL },
4640       { "SQLITE_OPEN_URI", SQLITE_OPEN_URI },
4641       { 0, 0 }
4642     };
4643     rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]),
4644         "flag", 0, &iFlag
4645     );
4646     if( rc!=TCL_OK ) return rc;
4647     flags |= aFlag[iFlag].flag;
4648   }
4649 
4650   rc = sqlite3_open_v2(zFilename, &db, flags, zVfs);
4651   if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
4652   Tcl_AppendResult(interp, zBuf, 0);
4653   return TCL_OK;
4654 }
4655 
4656 /*
4657 ** Usage: sqlite3_open16 filename options
4658 */
4659 static int SQLITE_TCLAPI test_open16(
4660   void * clientData,
4661   Tcl_Interp *interp,
4662   int objc,
4663   Tcl_Obj *CONST objv[]
4664 ){
4665 #ifndef SQLITE_OMIT_UTF16
4666   const void *zFilename;
4667   sqlite3 *db;
4668   char zBuf[100];
4669 
4670   if( objc!=3 ){
4671     Tcl_AppendResult(interp, "wrong # args: should be \"",
4672        Tcl_GetString(objv[0]), " filename options-list", 0);
4673     return TCL_ERROR;
4674   }
4675 
4676   zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
4677   sqlite3_open16(zFilename, &db);
4678 
4679   if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
4680   Tcl_AppendResult(interp, zBuf, 0);
4681 #endif /* SQLITE_OMIT_UTF16 */
4682   return TCL_OK;
4683 }
4684 
4685 /*
4686 ** Usage: sqlite3_complete16 <UTF-16 string>
4687 **
4688 ** Return 1 if the supplied argument is a complete SQL statement, or zero
4689 ** otherwise.
4690 */
4691 static int SQLITE_TCLAPI test_complete16(
4692   void * clientData,
4693   Tcl_Interp *interp,
4694   int objc,
4695   Tcl_Obj *CONST objv[]
4696 ){
4697 #if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16)
4698   char *zBuf;
4699 
4700   if( objc!=2 ){
4701     Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
4702     return TCL_ERROR;
4703   }
4704 
4705   zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0);
4706   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
4707 #endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */
4708   return TCL_OK;
4709 }
4710 
4711 /*
4712 ** Usage: sqlite3_normalize SQL
4713 **
4714 ** Return the normalized value for an SQL statement.
4715 */
4716 static int SQLITE_TCLAPI test_normalize(
4717   void * clientData,
4718   Tcl_Interp *interp,
4719   int objc,
4720   Tcl_Obj *CONST objv[]
4721 ){
4722   char *zSql;
4723   char *zNorm;
4724   extern char *sqlite3_normalize(const char*);
4725 
4726   if( objc!=2 ){
4727     Tcl_WrongNumArgs(interp, 1, objv, "SQL");
4728     return TCL_ERROR;
4729   }
4730 
4731   zSql = (char*)Tcl_GetString(objv[1]);
4732   zNorm = sqlite3_normalize(zSql);
4733   if( zNorm ){
4734     Tcl_SetObjResult(interp, Tcl_NewStringObj(zNorm, -1));
4735     sqlite3_free(zNorm);
4736   }
4737   return TCL_OK;
4738 }
4739 
4740 /*
4741 ** Usage: sqlite3_step STMT
4742 **
4743 ** Advance the statement to the next row.
4744 */
4745 static int SQLITE_TCLAPI test_step(
4746   void * clientData,
4747   Tcl_Interp *interp,
4748   int objc,
4749   Tcl_Obj *CONST objv[]
4750 ){
4751   sqlite3_stmt *pStmt;
4752   int rc;
4753 
4754   if( objc!=2 ){
4755     Tcl_AppendResult(interp, "wrong # args: should be \"",
4756        Tcl_GetString(objv[0]), " STMT", 0);
4757     return TCL_ERROR;
4758   }
4759 
4760   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4761   rc = sqlite3_step(pStmt);
4762 
4763   /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
4764   Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
4765   return TCL_OK;
4766 }
4767 
4768 static int SQLITE_TCLAPI test_sql(
4769   void * clientData,
4770   Tcl_Interp *interp,
4771   int objc,
4772   Tcl_Obj *CONST objv[]
4773 ){
4774   sqlite3_stmt *pStmt;
4775 
4776   if( objc!=2 ){
4777     Tcl_WrongNumArgs(interp, 1, objv, "STMT");
4778     return TCL_ERROR;
4779   }
4780 
4781   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4782   Tcl_SetResult(interp, (char *)sqlite3_sql(pStmt), TCL_VOLATILE);
4783   return TCL_OK;
4784 }
4785 static int SQLITE_TCLAPI test_ex_sql(
4786   void * clientData,
4787   Tcl_Interp *interp,
4788   int objc,
4789   Tcl_Obj *CONST objv[]
4790 ){
4791   sqlite3_stmt *pStmt;
4792   char *z;
4793 
4794   if( objc!=2 ){
4795     Tcl_WrongNumArgs(interp, 1, objv, "STMT");
4796     return TCL_ERROR;
4797   }
4798 
4799   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4800   z = sqlite3_expanded_sql(pStmt);
4801   Tcl_SetResult(interp, z, TCL_VOLATILE);
4802   sqlite3_free(z);
4803   return TCL_OK;
4804 }
4805 #ifdef SQLITE_ENABLE_NORMALIZE
4806 static int SQLITE_TCLAPI test_norm_sql(
4807   void * clientData,
4808   Tcl_Interp *interp,
4809   int objc,
4810   Tcl_Obj *CONST objv[]
4811 ){
4812   sqlite3_stmt *pStmt;
4813 
4814   if( objc!=2 ){
4815     Tcl_WrongNumArgs(interp, 1, objv, "STMT");
4816     return TCL_ERROR;
4817   }
4818 
4819   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4820   Tcl_SetResult(interp, (char *)sqlite3_normalized_sql(pStmt), TCL_VOLATILE);
4821   return TCL_OK;
4822 }
4823 #endif /* SQLITE_ENABLE_NORMALIZE */
4824 
4825 /*
4826 ** Usage: sqlite3_column_count STMT
4827 **
4828 ** Return the number of columns returned by the sql statement STMT.
4829 */
4830 static int SQLITE_TCLAPI test_column_count(
4831   void * clientData,
4832   Tcl_Interp *interp,
4833   int objc,
4834   Tcl_Obj *CONST objv[]
4835 ){
4836   sqlite3_stmt *pStmt;
4837 
4838   if( objc!=2 ){
4839     Tcl_AppendResult(interp, "wrong # args: should be \"",
4840        Tcl_GetString(objv[0]), " STMT column", 0);
4841     return TCL_ERROR;
4842   }
4843 
4844   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4845 
4846   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
4847   return TCL_OK;
4848 }
4849 
4850 /*
4851 ** Usage: sqlite3_column_type STMT column
4852 **
4853 ** Return the type of the data in column 'column' of the current row.
4854 */
4855 static int SQLITE_TCLAPI test_column_type(
4856   void * clientData,
4857   Tcl_Interp *interp,
4858   int objc,
4859   Tcl_Obj *CONST objv[]
4860 ){
4861   sqlite3_stmt *pStmt;
4862   int col;
4863   int tp;
4864 
4865   if( objc!=3 ){
4866     Tcl_AppendResult(interp, "wrong # args: should be \"",
4867        Tcl_GetString(objv[0]), " STMT column", 0);
4868     return TCL_ERROR;
4869   }
4870 
4871   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4872   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4873 
4874   tp = sqlite3_column_type(pStmt, col);
4875   switch( tp ){
4876     case SQLITE_INTEGER:
4877       Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
4878       break;
4879     case SQLITE_NULL:
4880       Tcl_SetResult(interp, "NULL", TCL_STATIC);
4881       break;
4882     case SQLITE_FLOAT:
4883       Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
4884       break;
4885     case SQLITE_TEXT:
4886       Tcl_SetResult(interp, "TEXT", TCL_STATIC);
4887       break;
4888     case SQLITE_BLOB:
4889       Tcl_SetResult(interp, "BLOB", TCL_STATIC);
4890       break;
4891     default:
4892       assert(0);
4893   }
4894 
4895   return TCL_OK;
4896 }
4897 
4898 /*
4899 ** Usage: sqlite3_column_int64 STMT column
4900 **
4901 ** Return the data in column 'column' of the current row cast as an
4902 ** wide (64-bit) integer.
4903 */
4904 static int SQLITE_TCLAPI test_column_int64(
4905   void * clientData,
4906   Tcl_Interp *interp,
4907   int objc,
4908   Tcl_Obj *CONST objv[]
4909 ){
4910   sqlite3_stmt *pStmt;
4911   int col;
4912   i64 iVal;
4913 
4914   if( objc!=3 ){
4915     Tcl_AppendResult(interp, "wrong # args: should be \"",
4916        Tcl_GetString(objv[0]), " STMT column", 0);
4917     return TCL_ERROR;
4918   }
4919 
4920   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4921   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4922 
4923   iVal = sqlite3_column_int64(pStmt, col);
4924   Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
4925   return TCL_OK;
4926 }
4927 
4928 /*
4929 ** Usage: sqlite3_column_blob STMT column
4930 */
4931 static int SQLITE_TCLAPI test_column_blob(
4932   void * clientData,
4933   Tcl_Interp *interp,
4934   int objc,
4935   Tcl_Obj *CONST objv[]
4936 ){
4937   sqlite3_stmt *pStmt;
4938   int col;
4939 
4940   int len;
4941   const void *pBlob;
4942 
4943   if( objc!=3 ){
4944     Tcl_AppendResult(interp, "wrong # args: should be \"",
4945        Tcl_GetString(objv[0]), " STMT column", 0);
4946     return TCL_ERROR;
4947   }
4948 
4949   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4950   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4951 
4952   len = sqlite3_column_bytes(pStmt, col);
4953   pBlob = sqlite3_column_blob(pStmt, col);
4954   Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
4955   return TCL_OK;
4956 }
4957 
4958 /*
4959 ** Usage: sqlite3_column_double STMT column
4960 **
4961 ** Return the data in column 'column' of the current row cast as a double.
4962 */
4963 static int SQLITE_TCLAPI test_column_double(
4964   void * clientData,
4965   Tcl_Interp *interp,
4966   int objc,
4967   Tcl_Obj *CONST objv[]
4968 ){
4969   sqlite3_stmt *pStmt;
4970   int col;
4971   double rVal;
4972 
4973   if( objc!=3 ){
4974     Tcl_AppendResult(interp, "wrong # args: should be \"",
4975        Tcl_GetString(objv[0]), " STMT column", 0);
4976     return TCL_ERROR;
4977   }
4978 
4979   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4980   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4981 
4982   rVal = sqlite3_column_double(pStmt, col);
4983   Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
4984   return TCL_OK;
4985 }
4986 
4987 /*
4988 ** Usage: sqlite3_data_count STMT
4989 **
4990 ** Return the number of columns returned by the sql statement STMT.
4991 */
4992 static int SQLITE_TCLAPI test_data_count(
4993   void * clientData,
4994   Tcl_Interp *interp,
4995   int objc,
4996   Tcl_Obj *CONST objv[]
4997 ){
4998   sqlite3_stmt *pStmt;
4999 
5000   if( objc!=2 ){
5001     Tcl_AppendResult(interp, "wrong # args: should be \"",
5002        Tcl_GetString(objv[0]), " STMT column", 0);
5003     return TCL_ERROR;
5004   }
5005 
5006   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
5007 
5008   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
5009   return TCL_OK;
5010 }
5011 
5012 /*
5013 ** Usage: sqlite3_column_text STMT column
5014 **
5015 ** Usage: sqlite3_column_decltype STMT column
5016 **
5017 ** Usage: sqlite3_column_name STMT column
5018 */
5019 static int SQLITE_TCLAPI test_stmt_utf8(
5020   void * clientData,        /* Pointer to SQLite API function to be invoke */
5021   Tcl_Interp *interp,
5022   int objc,
5023   Tcl_Obj *CONST objv[]
5024 ){
5025   sqlite3_stmt *pStmt;
5026   int col;
5027   const char *(*xFunc)(sqlite3_stmt*, int);
5028   const char *zRet;
5029 
5030   xFunc = (const char *(*)(sqlite3_stmt*, int))clientData;
5031   if( objc!=3 ){
5032     Tcl_AppendResult(interp, "wrong # args: should be \"",
5033        Tcl_GetString(objv[0]), " STMT column", 0);
5034     return TCL_ERROR;
5035   }
5036 
5037   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
5038   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
5039   zRet = xFunc(pStmt, col);
5040   if( zRet ){
5041     Tcl_SetResult(interp, (char *)zRet, 0);
5042   }
5043   return TCL_OK;
5044 }
5045 
5046 static int SQLITE_TCLAPI test_global_recover(
5047   void * clientData,
5048   Tcl_Interp *interp,
5049   int objc,
5050   Tcl_Obj *CONST objv[]
5051 ){
5052 #ifndef SQLITE_OMIT_DEPRECATED
5053   int rc;
5054   if( objc!=1 ){
5055     Tcl_WrongNumArgs(interp, 1, objv, "");
5056     return TCL_ERROR;
5057   }
5058   rc = sqlite3_global_recover();
5059   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
5060 #endif
5061   return TCL_OK;
5062 }
5063 
5064 /*
5065 ** Usage: sqlite3_column_text STMT column
5066 **
5067 ** Usage: sqlite3_column_decltype STMT column
5068 **
5069 ** Usage: sqlite3_column_name STMT column
5070 */
5071 static int SQLITE_TCLAPI test_stmt_utf16(
5072   void * clientData,     /* Pointer to SQLite API function to be invoked */
5073   Tcl_Interp *interp,
5074   int objc,
5075   Tcl_Obj *CONST objv[]
5076 ){
5077 #ifndef SQLITE_OMIT_UTF16
5078   sqlite3_stmt *pStmt;
5079   int col;
5080   Tcl_Obj *pRet;
5081   const void *zName16;
5082   const void *(*xFunc)(sqlite3_stmt*, int);
5083 
5084   xFunc = (const void *(*)(sqlite3_stmt*, int))clientData;
5085   if( objc!=3 ){
5086     Tcl_AppendResult(interp, "wrong # args: should be \"",
5087        Tcl_GetString(objv[0]), " STMT column", 0);
5088     return TCL_ERROR;
5089   }
5090 
5091   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
5092   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
5093 
5094   zName16 = xFunc(pStmt, col);
5095   if( zName16 ){
5096     int n;
5097     const char *z = zName16;
5098     for(n=0; z[n] || z[n+1]; n+=2){}
5099     pRet = Tcl_NewByteArrayObj(zName16, n+2);
5100     Tcl_SetObjResult(interp, pRet);
5101   }
5102 #endif /* SQLITE_OMIT_UTF16 */
5103 
5104   return TCL_OK;
5105 }
5106 
5107 /*
5108 ** Usage: sqlite3_column_int STMT column
5109 **
5110 ** Usage: sqlite3_column_bytes STMT column
5111 **
5112 ** Usage: sqlite3_column_bytes16 STMT column
5113 **
5114 */
5115 static int SQLITE_TCLAPI test_stmt_int(
5116   void * clientData,    /* Pointer to SQLite API function to be invoked */
5117   Tcl_Interp *interp,
5118   int objc,
5119   Tcl_Obj *CONST objv[]
5120 ){
5121   sqlite3_stmt *pStmt;
5122   int col;
5123   int (*xFunc)(sqlite3_stmt*, int);
5124 
5125   xFunc = (int (*)(sqlite3_stmt*, int))clientData;
5126   if( objc!=3 ){
5127     Tcl_AppendResult(interp, "wrong # args: should be \"",
5128        Tcl_GetString(objv[0]), " STMT column", 0);
5129     return TCL_ERROR;
5130   }
5131 
5132   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
5133   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
5134 
5135   Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
5136   return TCL_OK;
5137 }
5138 
5139 /*
5140 ** Usage:  sqlite_set_magic  DB  MAGIC-NUMBER
5141 **
5142 ** Set the db->magic value.  This is used to test error recovery logic.
5143 */
5144 static int SQLITE_TCLAPI sqlite_set_magic(
5145   void * clientData,
5146   Tcl_Interp *interp,
5147   int argc,
5148   char **argv
5149 ){
5150   sqlite3 *db;
5151   if( argc!=3 ){
5152     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
5153          " DB MAGIC", 0);
5154     return TCL_ERROR;
5155   }
5156   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
5157   if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
5158     db->magic = SQLITE_MAGIC_OPEN;
5159   }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
5160     db->magic = SQLITE_MAGIC_CLOSED;
5161   }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
5162     db->magic = SQLITE_MAGIC_BUSY;
5163   }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
5164     db->magic = SQLITE_MAGIC_ERROR;
5165   }else if( Tcl_GetInt(interp, argv[2], (int*)&db->magic) ){
5166     return TCL_ERROR;
5167   }
5168   return TCL_OK;
5169 }
5170 
5171 /*
5172 ** Usage:  sqlite3_interrupt  DB
5173 **
5174 ** Trigger an interrupt on DB
5175 */
5176 static int SQLITE_TCLAPI test_interrupt(
5177   void * clientData,
5178   Tcl_Interp *interp,
5179   int argc,
5180   char **argv
5181 ){
5182   sqlite3 *db;
5183   if( argc!=2 ){
5184     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
5185     return TCL_ERROR;
5186   }
5187   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
5188   sqlite3_interrupt(db);
5189   return TCL_OK;
5190 }
5191 
5192 /*
5193 ** Usage: sqlite_delete_function DB function-name
5194 **
5195 ** Delete the user function 'function-name' from database handle DB. It
5196 ** is assumed that the user function was created as UTF8, any number of
5197 ** arguments (the way the TCL interface does it).
5198 */
5199 static int SQLITE_TCLAPI delete_function(
5200   void * clientData,
5201   Tcl_Interp *interp,
5202   int argc,
5203   char **argv
5204 ){
5205   int rc;
5206   sqlite3 *db;
5207   if( argc!=3 ){
5208     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
5209         " DB function-name", 0);
5210     return TCL_ERROR;
5211   }
5212   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
5213   rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
5214   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
5215   return TCL_OK;
5216 }
5217 
5218 /*
5219 ** Usage: sqlite_delete_collation DB collation-name
5220 **
5221 ** Delete the collation sequence 'collation-name' from database handle
5222 ** DB. It is assumed that the collation sequence was created as UTF8 (the
5223 ** way the TCL interface does it).
5224 */
5225 static int SQLITE_TCLAPI delete_collation(
5226   void * clientData,
5227   Tcl_Interp *interp,
5228   int argc,
5229   char **argv
5230 ){
5231   int rc;
5232   sqlite3 *db;
5233   if( argc!=3 ){
5234     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
5235         " DB function-name", 0);
5236     return TCL_ERROR;
5237   }
5238   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
5239   rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
5240   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
5241   return TCL_OK;
5242 }
5243 
5244 /*
5245 ** Usage: sqlite3_get_autocommit DB
5246 **
5247 ** Return true if the database DB is currently in auto-commit mode.
5248 ** Return false if not.
5249 */
5250 static int SQLITE_TCLAPI get_autocommit(
5251   void * clientData,
5252   Tcl_Interp *interp,
5253   int argc,
5254   char **argv
5255 ){
5256   char zBuf[30];
5257   sqlite3 *db;
5258   if( argc!=2 ){
5259     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
5260         " DB", 0);
5261     return TCL_ERROR;
5262   }
5263   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
5264   sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3_get_autocommit(db));
5265   Tcl_AppendResult(interp, zBuf, 0);
5266   return TCL_OK;
5267 }
5268 
5269 /*
5270 ** Usage: sqlite3_busy_timeout DB MS
5271 **
5272 ** Set the busy timeout.  This is more easily done using the timeout
5273 ** method of the TCL interface.  But we need a way to test the case
5274 ** where it returns SQLITE_MISUSE.
5275 */
5276 static int SQLITE_TCLAPI test_busy_timeout(
5277   void * clientData,
5278   Tcl_Interp *interp,
5279   int argc,
5280   char **argv
5281 ){
5282   int rc, ms;
5283   sqlite3 *db;
5284   if( argc!=3 ){
5285     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
5286         " DB", 0);
5287     return TCL_ERROR;
5288   }
5289   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
5290   if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR;
5291   rc = sqlite3_busy_timeout(db, ms);
5292   Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
5293   return TCL_OK;
5294 }
5295 
5296 /*
5297 ** Usage:  tcl_variable_type VARIABLENAME
5298 **
5299 ** Return the name of the internal representation for the
5300 ** value of the given variable.
5301 */
5302 static int SQLITE_TCLAPI tcl_variable_type(
5303   void * clientData,
5304   Tcl_Interp *interp,
5305   int objc,
5306   Tcl_Obj *CONST objv[]
5307 ){
5308   Tcl_Obj *pVar;
5309   if( objc!=2 ){
5310     Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
5311     return TCL_ERROR;
5312   }
5313   pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
5314   if( pVar==0 ) return TCL_ERROR;
5315   if( pVar->typePtr ){
5316     Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
5317   }
5318   return TCL_OK;
5319 }
5320 
5321 /*
5322 ** Usage:  sqlite3_release_memory ?N?
5323 **
5324 ** Attempt to release memory currently held but not actually required.
5325 ** The integer N is the number of bytes we are trying to release.  The
5326 ** return value is the amount of memory actually released.
5327 */
5328 static int SQLITE_TCLAPI test_release_memory(
5329   void * clientData,
5330   Tcl_Interp *interp,
5331   int objc,
5332   Tcl_Obj *CONST objv[]
5333 ){
5334 #if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
5335   int N;
5336   int amt;
5337   if( objc!=1 && objc!=2 ){
5338     Tcl_WrongNumArgs(interp, 1, objv, "?N?");
5339     return TCL_ERROR;
5340   }
5341   if( objc==2 ){
5342     if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
5343   }else{
5344     N = -1;
5345   }
5346   amt = sqlite3_release_memory(N);
5347   Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
5348 #endif
5349   return TCL_OK;
5350 }
5351 
5352 
5353 /*
5354 ** Usage:  sqlite3_db_release_memory DB
5355 **
5356 ** Attempt to release memory currently held by database DB.  Return the
5357 ** result code (which in the current implementation is always zero).
5358 */
5359 static int SQLITE_TCLAPI test_db_release_memory(
5360   void * clientData,
5361   Tcl_Interp *interp,
5362   int objc,
5363   Tcl_Obj *CONST objv[]
5364 ){
5365   sqlite3 *db;
5366   int rc;
5367   if( objc!=2 ){
5368     Tcl_WrongNumArgs(interp, 1, objv, "DB");
5369     return TCL_ERROR;
5370   }
5371   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
5372   rc = sqlite3_db_release_memory(db);
5373   Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5374   return TCL_OK;
5375 }
5376 
5377 /*
5378 ** Usage:  sqlite3_db_cacheflush DB
5379 **
5380 ** Attempt to flush any dirty pages to disk.
5381 */
5382 static int SQLITE_TCLAPI test_db_cacheflush(
5383   void * clientData,
5384   Tcl_Interp *interp,
5385   int objc,
5386   Tcl_Obj *CONST objv[]
5387 ){
5388   sqlite3 *db;
5389   int rc;
5390   if( objc!=2 ){
5391     Tcl_WrongNumArgs(interp, 1, objv, "DB");
5392     return TCL_ERROR;
5393   }
5394   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
5395   rc = sqlite3_db_cacheflush(db);
5396   if( rc ){
5397     Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
5398     return TCL_ERROR;
5399   }
5400 
5401   Tcl_ResetResult(interp);
5402   return TCL_OK;
5403 }
5404 
5405 /*
5406 ** Usage:  sqlite3_system_errno DB
5407 **
5408 ** Return the low-level system errno value.
5409 */
5410 static int SQLITE_TCLAPI test_system_errno(
5411   void * clientData,
5412   Tcl_Interp *interp,
5413   int objc,
5414   Tcl_Obj *CONST objv[]
5415 ){
5416   sqlite3 *db;
5417   int iErrno;
5418   if( objc!=2 ){
5419     Tcl_WrongNumArgs(interp, 1, objv, "DB");
5420     return TCL_ERROR;
5421   }
5422   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
5423   iErrno = sqlite3_system_errno(db);
5424   Tcl_SetObjResult(interp, Tcl_NewIntObj(iErrno));
5425   return TCL_OK;
5426 }
5427 
5428 /*
5429 ** Usage:  sqlite3_db_filename DB DBNAME
5430 **
5431 ** Return the name of a file associated with a database.
5432 */
5433 static int SQLITE_TCLAPI test_db_filename(
5434   void * clientData,
5435   Tcl_Interp *interp,
5436   int objc,
5437   Tcl_Obj *CONST objv[]
5438 ){
5439   sqlite3 *db;
5440   const char *zDbName;
5441   if( objc!=3 ){
5442     Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
5443     return TCL_ERROR;
5444   }
5445   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
5446   zDbName = Tcl_GetString(objv[2]);
5447   Tcl_AppendResult(interp, sqlite3_db_filename(db, zDbName), (void*)0);
5448   return TCL_OK;
5449 }
5450 
5451 /*
5452 ** Usage:  sqlite3_db_readonly DB DBNAME
5453 **
5454 ** Return 1 or 0 if DBNAME is readonly or not.  Return -1 if DBNAME does
5455 ** not exist.
5456 */
5457 static int SQLITE_TCLAPI test_db_readonly(
5458   void * clientData,
5459   Tcl_Interp *interp,
5460   int objc,
5461   Tcl_Obj *CONST objv[]
5462 ){
5463   sqlite3 *db;
5464   const char *zDbName;
5465   if( objc!=3 ){
5466     Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
5467     return TCL_ERROR;
5468   }
5469   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
5470   zDbName = Tcl_GetString(objv[2]);
5471   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_db_readonly(db, zDbName)));
5472   return TCL_OK;
5473 }
5474 
5475 /*
5476 ** Usage:  sqlite3_soft_heap_limit ?N?
5477 **
5478 ** Query or set the soft heap limit for the current thread.  The
5479 ** limit is only changed if the N is present.  The previous limit
5480 ** is returned.
5481 */
5482 static int SQLITE_TCLAPI test_soft_heap_limit(
5483   void * clientData,
5484   Tcl_Interp *interp,
5485   int objc,
5486   Tcl_Obj *CONST objv[]
5487 ){
5488   sqlite3_int64 amt;
5489   Tcl_WideInt N = -1;
5490   if( objc!=1 && objc!=2 ){
5491     Tcl_WrongNumArgs(interp, 1, objv, "?N?");
5492     return TCL_ERROR;
5493   }
5494   if( objc==2 ){
5495     if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
5496   }
5497   amt = sqlite3_soft_heap_limit64(N);
5498   Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt));
5499   return TCL_OK;
5500 }
5501 
5502 /*
5503 ** Usage:   sqlite3_thread_cleanup
5504 **
5505 ** Call the sqlite3_thread_cleanup API.
5506 */
5507 static int SQLITE_TCLAPI test_thread_cleanup(
5508   void * clientData,
5509   Tcl_Interp *interp,
5510   int objc,
5511   Tcl_Obj *CONST objv[]
5512 ){
5513 #ifndef SQLITE_OMIT_DEPRECATED
5514   sqlite3_thread_cleanup();
5515 #endif
5516   return TCL_OK;
5517 }
5518 
5519 /*
5520 ** Usage:   sqlite3_pager_refcounts  DB
5521 **
5522 ** Return a list of numbers which are the PagerRefcount for all
5523 ** pagers on each database connection.
5524 */
5525 static int SQLITE_TCLAPI test_pager_refcounts(
5526   void * clientData,
5527   Tcl_Interp *interp,
5528   int objc,
5529   Tcl_Obj *CONST objv[]
5530 ){
5531   sqlite3 *db;
5532   int i;
5533   int v, *a;
5534   Tcl_Obj *pResult;
5535 
5536   if( objc!=2 ){
5537     Tcl_AppendResult(interp, "wrong # args: should be \"",
5538         Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
5539     return TCL_ERROR;
5540   }
5541   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
5542   pResult = Tcl_NewObj();
5543   for(i=0; i<db->nDb; i++){
5544     if( db->aDb[i].pBt==0 ){
5545       v = -1;
5546     }else{
5547       sqlite3_mutex_enter(db->mutex);
5548       a = sqlite3PagerStats(sqlite3BtreePager(db->aDb[i].pBt));
5549       v = a[0];
5550       sqlite3_mutex_leave(db->mutex);
5551     }
5552     Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(v));
5553   }
5554   Tcl_SetObjResult(interp, pResult);
5555   return TCL_OK;
5556 }
5557 
5558 
5559 /*
5560 ** tclcmd:   working_64bit_int
5561 **
5562 ** Some TCL builds (ex: cygwin) do not support 64-bit integers.  This
5563 ** leads to a number of test failures.  The present command checks the
5564 ** TCL build to see whether or not it supports 64-bit integers.  It
5565 ** returns TRUE if it does and FALSE if not.
5566 **
5567 ** This command is used to warn users that their TCL build is defective
5568 ** and that the errors they are seeing in the test scripts might be
5569 ** a result of their defective TCL rather than problems in SQLite.
5570 */
5571 static int SQLITE_TCLAPI working_64bit_int(
5572   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5573   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
5574   int objc,              /* Number of arguments */
5575   Tcl_Obj *CONST objv[]  /* Command arguments */
5576 ){
5577   Tcl_Obj *pTestObj;
5578   int working = 0;
5579 
5580   pTestObj = Tcl_NewWideIntObj(1000000*(i64)1234567890);
5581   working = strcmp(Tcl_GetString(pTestObj), "1234567890000000")==0;
5582   Tcl_DecrRefCount(pTestObj);
5583   Tcl_SetObjResult(interp, Tcl_NewBooleanObj(working));
5584   return TCL_OK;
5585 }
5586 
5587 
5588 /*
5589 ** tclcmd:   vfs_unlink_test
5590 **
5591 ** This TCL command unregisters the primary VFS and then registers
5592 ** it back again.  This is used to test the ability to register a
5593 ** VFS when none are previously registered, and the ability to
5594 ** unregister the only available VFS.  Ticket #2738
5595 */
5596 static int SQLITE_TCLAPI vfs_unlink_test(
5597   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5598   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
5599   int objc,              /* Number of arguments */
5600   Tcl_Obj *CONST objv[]  /* Command arguments */
5601 ){
5602   int i;
5603   sqlite3_vfs *pMain;
5604   sqlite3_vfs *apVfs[20];
5605   sqlite3_vfs one, two;
5606 
5607   sqlite3_vfs_unregister(0);   /* Unregister of NULL is harmless */
5608   one.zName = "__one";
5609   two.zName = "__two";
5610 
5611   /* Calling sqlite3_vfs_register with 2nd argument of 0 does not
5612   ** change the default VFS
5613   */
5614   pMain = sqlite3_vfs_find(0);
5615   sqlite3_vfs_register(&one, 0);
5616   assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
5617   sqlite3_vfs_register(&two, 0);
5618   assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
5619 
5620   /* We can find a VFS by its name */
5621   assert( sqlite3_vfs_find("__one")==&one );
5622   assert( sqlite3_vfs_find("__two")==&two );
5623 
5624   /* Calling sqlite_vfs_register with non-zero second parameter changes the
5625   ** default VFS, even if the 1st parameter is an existig VFS that is
5626   ** previously registered as the non-default.
5627   */
5628   sqlite3_vfs_register(&one, 1);
5629   assert( sqlite3_vfs_find("__one")==&one );
5630   assert( sqlite3_vfs_find("__two")==&two );
5631   assert( sqlite3_vfs_find(0)==&one );
5632   sqlite3_vfs_register(&two, 1);
5633   assert( sqlite3_vfs_find("__one")==&one );
5634   assert( sqlite3_vfs_find("__two")==&two );
5635   assert( sqlite3_vfs_find(0)==&two );
5636   if( pMain ){
5637     sqlite3_vfs_register(pMain, 1);
5638     assert( sqlite3_vfs_find("__one")==&one );
5639     assert( sqlite3_vfs_find("__two")==&two );
5640     assert( sqlite3_vfs_find(0)==pMain );
5641   }
5642 
5643   /* Unlink the default VFS.  Repeat until there are no more VFSes
5644   ** registered.
5645   */
5646   for(i=0; i<sizeof(apVfs)/sizeof(apVfs[0]); i++){
5647     apVfs[i] = sqlite3_vfs_find(0);
5648     if( apVfs[i] ){
5649       assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
5650       sqlite3_vfs_unregister(apVfs[i]);
5651       assert( 0==sqlite3_vfs_find(apVfs[i]->zName) );
5652     }
5653   }
5654   assert( 0==sqlite3_vfs_find(0) );
5655 
5656   /* Register the main VFS as non-default (will be made default, since
5657   ** it'll be the only one in existence).
5658   */
5659   sqlite3_vfs_register(pMain, 0);
5660   assert( sqlite3_vfs_find(0)==pMain );
5661 
5662   /* Un-register the main VFS again to restore an empty VFS list */
5663   sqlite3_vfs_unregister(pMain);
5664   assert( 0==sqlite3_vfs_find(0) );
5665 
5666   /* Relink all VFSes in reverse order. */
5667   for(i=sizeof(apVfs)/sizeof(apVfs[0])-1; i>=0; i--){
5668     if( apVfs[i] ){
5669       sqlite3_vfs_register(apVfs[i], 1);
5670       assert( apVfs[i]==sqlite3_vfs_find(0) );
5671       assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
5672     }
5673   }
5674 
5675   /* Unregister out sample VFSes. */
5676   sqlite3_vfs_unregister(&one);
5677   sqlite3_vfs_unregister(&two);
5678 
5679   /* Unregistering a VFS that is not currently registered is harmless */
5680   sqlite3_vfs_unregister(&one);
5681   sqlite3_vfs_unregister(&two);
5682   assert( sqlite3_vfs_find("__one")==0 );
5683   assert( sqlite3_vfs_find("__two")==0 );
5684 
5685   /* We should be left with the original default VFS back as the
5686   ** original */
5687   assert( sqlite3_vfs_find(0)==pMain );
5688 
5689   return TCL_OK;
5690 }
5691 
5692 /*
5693 ** tclcmd:   vfs_initfail_test
5694 **
5695 ** This TCL command attempts to vfs_find and vfs_register when the
5696 ** sqlite3_initialize() interface is failing.  All calls should fail.
5697 */
5698 static int SQLITE_TCLAPI vfs_initfail_test(
5699   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5700   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
5701   int objc,              /* Number of arguments */
5702   Tcl_Obj *CONST objv[]  /* Command arguments */
5703 ){
5704   sqlite3_vfs one;
5705   one.zName = "__one";
5706 
5707   if( sqlite3_vfs_find(0) ) return TCL_ERROR;
5708   sqlite3_vfs_register(&one, 0);
5709   if( sqlite3_vfs_find(0) ) return TCL_ERROR;
5710   sqlite3_vfs_register(&one, 1);
5711   if( sqlite3_vfs_find(0) ) return TCL_ERROR;
5712   return TCL_OK;
5713 }
5714 
5715 /*
5716 ** Saved VFSes
5717 */
5718 static sqlite3_vfs *apVfs[20];
5719 static int nVfs = 0;
5720 
5721 /*
5722 ** tclcmd:   vfs_unregister_all
5723 **
5724 ** Unregister all VFSes.
5725 */
5726 static int SQLITE_TCLAPI vfs_unregister_all(
5727   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5728   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
5729   int objc,              /* Number of arguments */
5730   Tcl_Obj *CONST objv[]  /* Command arguments */
5731 ){
5732   int i;
5733   for(i=0; i<ArraySize(apVfs); i++){
5734     apVfs[i] = sqlite3_vfs_find(0);
5735     if( apVfs[i]==0 ) break;
5736     sqlite3_vfs_unregister(apVfs[i]);
5737   }
5738   nVfs = i;
5739   return TCL_OK;
5740 }
5741 /*
5742 ** tclcmd:   vfs_reregister_all
5743 **
5744 ** Restore all VFSes that were removed using vfs_unregister_all. Taking
5745 ** care to put the linked list back together in the same order as it was
5746 ** in before vfs_unregister_all was invoked.
5747 */
5748 static int SQLITE_TCLAPI vfs_reregister_all(
5749   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5750   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
5751   int objc,              /* Number of arguments */
5752   Tcl_Obj *CONST objv[]  /* Command arguments */
5753 ){
5754   int i;
5755   for(i=nVfs-1; i>=0; i--){
5756     sqlite3_vfs_register(apVfs[i], 1);
5757   }
5758   return TCL_OK;
5759 }
5760 
5761 
5762 /*
5763 ** tclcmd:   file_control_test DB
5764 **
5765 ** This TCL command runs the sqlite3_file_control interface and
5766 ** verifies correct operation of the same.
5767 */
5768 static int SQLITE_TCLAPI file_control_test(
5769   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5770   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
5771   int objc,              /* Number of arguments */
5772   Tcl_Obj *CONST objv[]  /* Command arguments */
5773 ){
5774   int iArg = 0;
5775   sqlite3 *db;
5776   int rc;
5777 
5778   if( objc!=2 ){
5779     Tcl_AppendResult(interp, "wrong # args: should be \"",
5780         Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
5781     return TCL_ERROR;
5782   }
5783   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
5784   rc = sqlite3_file_control(db, 0, 0, &iArg);
5785   assert( rc==SQLITE_NOTFOUND );
5786   rc = sqlite3_file_control(db, "notadatabase", SQLITE_FCNTL_LOCKSTATE, &iArg);
5787   assert( rc==SQLITE_ERROR );
5788   rc = sqlite3_file_control(db, "main", -1, &iArg);
5789   assert( rc==SQLITE_NOTFOUND );
5790   rc = sqlite3_file_control(db, "temp", -1, &iArg);
5791   assert( rc==SQLITE_NOTFOUND || rc==SQLITE_ERROR );
5792 
5793   return TCL_OK;
5794 }
5795 
5796 
5797 /*
5798 ** tclcmd:   file_control_lasterrno_test DB
5799 **
5800 ** This TCL command runs the sqlite3_file_control interface and
5801 ** verifies correct operation of the SQLITE_LAST_ERRNO verb.
5802 */
5803 static int SQLITE_TCLAPI file_control_lasterrno_test(
5804   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5805   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
5806   int objc,              /* Number of arguments */
5807   Tcl_Obj *CONST objv[]  /* Command arguments */
5808 ){
5809   int iArg = 0;
5810   sqlite3 *db;
5811   int rc;
5812 
5813   if( objc!=2 ){
5814     Tcl_AppendResult(interp, "wrong # args: should be \"",
5815         Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
5816     return TCL_ERROR;
5817   }
5818   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5819     return TCL_ERROR;
5820   }
5821   rc = sqlite3_file_control(db, NULL, SQLITE_LAST_ERRNO, &iArg);
5822   if( rc ){
5823     Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5824     return TCL_ERROR;
5825   }
5826   if( iArg!=0 ) {
5827     Tcl_AppendResult(interp, "Unexpected non-zero errno: ",
5828                      Tcl_GetStringFromObj(Tcl_NewIntObj(iArg), 0), " ", 0);
5829     return TCL_ERROR;
5830   }
5831   return TCL_OK;
5832 }
5833 
5834 /*
5835 ** tclcmd:   file_control_data_version DB DBNAME
5836 **
5837 ** This TCL command runs the sqlite3_file_control with the
5838 ** SQLITE_FCNTL_DATA_VERSION opcode, returning the result.
5839 */
5840 static int SQLITE_TCLAPI file_control_data_version(
5841   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5842   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
5843   int objc,              /* Number of arguments */
5844   Tcl_Obj *CONST objv[]  /* Command arguments */
5845 ){
5846   unsigned int iVers;             /* data version */
5847   char *zDb;                      /* Db name ("main", "temp" etc.) */
5848   sqlite3 *db;                    /* Database handle */
5849   int rc;                         /* file_control() return code */
5850   char zBuf[100];
5851 
5852   if( objc!=3 && objc!=2 ){
5853     Tcl_WrongNumArgs(interp, 1, objv, "DB [DBNAME]");
5854     return TCL_ERROR;
5855   }
5856   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5857    return TCL_ERROR;
5858   }
5859   zDb = objc==3 ? Tcl_GetString(objv[2]) : NULL;
5860 
5861   rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_DATA_VERSION, (void *)&iVers);
5862   if( rc ){
5863     Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
5864     return TCL_ERROR;
5865   }else{
5866     sqlite3_snprintf(sizeof(zBuf),zBuf,"%u",iVers);
5867     Tcl_SetResult(interp, (char *)zBuf, TCL_VOLATILE);
5868     return TCL_OK;
5869   }
5870 }
5871 
5872 /*
5873 ** tclcmd:   file_control_chunksize_test DB DBNAME SIZE
5874 **
5875 ** This TCL command runs the sqlite3_file_control interface and
5876 ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
5877 ** SQLITE_SET_LOCKPROXYFILE verbs.
5878 */
5879 static int SQLITE_TCLAPI file_control_chunksize_test(
5880   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5881   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
5882   int objc,              /* Number of arguments */
5883   Tcl_Obj *CONST objv[]  /* Command arguments */
5884 ){
5885   int nSize;                      /* New chunk size */
5886   char *zDb;                      /* Db name ("main", "temp" etc.) */
5887   sqlite3 *db;                    /* Database handle */
5888   int rc;                         /* file_control() return code */
5889 
5890   if( objc!=4 ){
5891     Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
5892     return TCL_ERROR;
5893   }
5894   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
5895    || Tcl_GetIntFromObj(interp, objv[3], &nSize)
5896   ){
5897    return TCL_ERROR;
5898   }
5899   zDb = Tcl_GetString(objv[2]);
5900   if( zDb[0]=='\0' ) zDb = NULL;
5901 
5902   rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_CHUNK_SIZE, (void *)&nSize);
5903   if( rc ){
5904     Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
5905     return TCL_ERROR;
5906   }
5907   return TCL_OK;
5908 }
5909 
5910 /*
5911 ** tclcmd:   file_control_sizehint_test DB DBNAME SIZE
5912 **
5913 ** This TCL command runs the sqlite3_file_control interface
5914 ** with SQLITE_FCNTL_SIZE_HINT
5915 */
5916 static int SQLITE_TCLAPI file_control_sizehint_test(
5917   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5918   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
5919   int objc,              /* Number of arguments */
5920   Tcl_Obj *CONST objv[]  /* Command arguments */
5921 ){
5922   Tcl_WideInt nSize;              /* Hinted size */
5923   char *zDb;                      /* Db name ("main", "temp" etc.) */
5924   sqlite3 *db;                    /* Database handle */
5925   int rc;                         /* file_control() return code */
5926 
5927   if( objc!=4 ){
5928     Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
5929     return TCL_ERROR;
5930   }
5931   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
5932    || Tcl_GetWideIntFromObj(interp, objv[3], &nSize)
5933   ){
5934    return TCL_ERROR;
5935   }
5936   zDb = Tcl_GetString(objv[2]);
5937   if( zDb[0]=='\0' ) zDb = NULL;
5938 
5939   rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_SIZE_HINT, (void *)&nSize);
5940   if( rc ){
5941     Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
5942     return TCL_ERROR;
5943   }
5944   return TCL_OK;
5945 }
5946 
5947 /*
5948 ** tclcmd:   file_control_lockproxy_test DB PWD
5949 **
5950 ** This TCL command runs the sqlite3_file_control interface and
5951 ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
5952 ** SQLITE_SET_LOCKPROXYFILE verbs.
5953 */
5954 static int SQLITE_TCLAPI file_control_lockproxy_test(
5955   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5956   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
5957   int objc,              /* Number of arguments */
5958   Tcl_Obj *CONST objv[]  /* Command arguments */
5959 ){
5960   sqlite3 *db;
5961 
5962   if( objc!=3 ){
5963     Tcl_AppendResult(interp, "wrong # args: should be \"",
5964                      Tcl_GetStringFromObj(objv[0], 0), " DB PWD", 0);
5965     return TCL_ERROR;
5966   }
5967   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5968    return TCL_ERROR;
5969   }
5970 
5971 #if !defined(SQLITE_ENABLE_LOCKING_STYLE)
5972 #  if defined(__APPLE__)
5973 #    define SQLITE_ENABLE_LOCKING_STYLE 1
5974 #  else
5975 #    define SQLITE_ENABLE_LOCKING_STYLE 0
5976 #  endif
5977 #endif
5978 #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
5979   {
5980     char *testPath;
5981     int rc;
5982     int nPwd;
5983     const char *zPwd;
5984     char proxyPath[400];
5985 
5986     zPwd = Tcl_GetStringFromObj(objv[2], &nPwd);
5987     if( sizeof(proxyPath)<nPwd+20 ){
5988       Tcl_AppendResult(interp, "PWD too big", (void*)0);
5989       return TCL_ERROR;
5990     }
5991     sqlite3_snprintf(sizeof(proxyPath), proxyPath, "%s/test.proxy", zPwd);
5992     rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
5993     if( rc ){
5994       Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5995       return TCL_ERROR;
5996     }
5997     rc = sqlite3_file_control(db, NULL, SQLITE_GET_LOCKPROXYFILE, &testPath);
5998     if( strncmp(proxyPath,testPath,11) ){
5999       Tcl_AppendResult(interp, "Lock proxy file did not match the "
6000                                "previously assigned value", 0);
6001       return TCL_ERROR;
6002     }
6003     if( rc ){
6004       Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
6005       return TCL_ERROR;
6006     }
6007     rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
6008     if( rc ){
6009       Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
6010       return TCL_ERROR;
6011     }
6012   }
6013 #endif
6014   return TCL_OK;
6015 }
6016 
6017 #if SQLITE_OS_WIN
6018 /*
6019 ** tclcmd:   file_control_win32_av_retry DB  NRETRY  DELAY
6020 **
6021 ** This TCL command runs the sqlite3_file_control interface with
6022 ** the SQLITE_FCNTL_WIN32_AV_RETRY opcode.
6023 */
6024 static int SQLITE_TCLAPI file_control_win32_av_retry(
6025   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6026   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6027   int objc,              /* Number of arguments */
6028   Tcl_Obj *CONST objv[]  /* Command arguments */
6029 ){
6030   sqlite3 *db;
6031   int rc;
6032   int a[2];
6033   char z[100];
6034 
6035   if( objc!=4 ){
6036     Tcl_AppendResult(interp, "wrong # args: should be \"",
6037         Tcl_GetStringFromObj(objv[0], 0), " DB NRETRY DELAY", 0);
6038     return TCL_ERROR;
6039   }
6040   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6041     return TCL_ERROR;
6042   }
6043   if( Tcl_GetIntFromObj(interp, objv[2], &a[0]) ) return TCL_ERROR;
6044   if( Tcl_GetIntFromObj(interp, objv[3], &a[1]) ) return TCL_ERROR;
6045   rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a);
6046   sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]);
6047   Tcl_AppendResult(interp, z, (char*)0);
6048   return TCL_OK;
6049 }
6050 
6051 /*
6052 ** tclcmd:   file_control_win32_get_handle DB
6053 **
6054 ** This TCL command runs the sqlite3_file_control interface with
6055 ** the SQLITE_FCNTL_WIN32_GET_HANDLE opcode.
6056 */
6057 static int file_control_win32_get_handle(
6058   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6059   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6060   int objc,              /* Number of arguments */
6061   Tcl_Obj *CONST objv[]  /* Command arguments */
6062 ){
6063   sqlite3 *db;
6064   int rc;
6065   HANDLE hFile = NULL;
6066   char z[100];
6067 
6068   if( objc!=2 ){
6069     Tcl_AppendResult(interp, "wrong # args: should be \"",
6070         Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
6071     return TCL_ERROR;
6072   }
6073   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6074     return TCL_ERROR;
6075   }
6076   rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_GET_HANDLE,
6077                             (void*)&hFile);
6078   sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
6079   Tcl_AppendResult(interp, z, (char*)0);
6080   return TCL_OK;
6081 }
6082 
6083 /*
6084 ** tclcmd:   file_control_win32_set_handle DB HANDLE
6085 **
6086 ** This TCL command runs the sqlite3_file_control interface with
6087 ** the SQLITE_FCNTL_WIN32_SET_HANDLE opcode.
6088 */
6089 static int SQLITE_TCLAPI file_control_win32_set_handle(
6090   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6091   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6092   int objc,              /* Number of arguments */
6093   Tcl_Obj *CONST objv[]  /* Command arguments */
6094 ){
6095   sqlite3 *db;
6096   int rc;
6097   HANDLE hFile = NULL;
6098   char z[100];
6099 
6100   if( objc!=3 ){
6101     Tcl_AppendResult(interp, "wrong # args: should be \"",
6102         Tcl_GetStringFromObj(objv[0], 0), " DB HANDLE", 0);
6103     return TCL_ERROR;
6104   }
6105   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6106     return TCL_ERROR;
6107   }
6108   if( getWin32Handle(interp, Tcl_GetString(objv[2]), &hFile) ){
6109     return TCL_ERROR;
6110   }
6111   rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_SET_HANDLE,
6112                             (void*)&hFile);
6113   sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
6114   Tcl_AppendResult(interp, z, (char*)0);
6115   return TCL_OK;
6116 }
6117 #endif
6118 
6119 /*
6120 ** tclcmd:   file_control_persist_wal DB PERSIST-FLAG
6121 **
6122 ** This TCL command runs the sqlite3_file_control interface with
6123 ** the SQLITE_FCNTL_PERSIST_WAL opcode.
6124 */
6125 static int SQLITE_TCLAPI file_control_persist_wal(
6126   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6127   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6128   int objc,              /* Number of arguments */
6129   Tcl_Obj *CONST objv[]  /* Command arguments */
6130 ){
6131   sqlite3 *db;
6132   int rc;
6133   int bPersist;
6134   char z[100];
6135 
6136   if( objc!=3 ){
6137     Tcl_AppendResult(interp, "wrong # args: should be \"",
6138         Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
6139     return TCL_ERROR;
6140   }
6141   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6142     return TCL_ERROR;
6143   }
6144   if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR;
6145   rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist);
6146   sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist);
6147   Tcl_AppendResult(interp, z, (char*)0);
6148   return TCL_OK;
6149 }
6150 
6151 /*
6152 ** tclcmd:   file_control_powersafe_overwrite DB PSOW-FLAG
6153 **
6154 ** This TCL command runs the sqlite3_file_control interface with
6155 ** the SQLITE_FCNTL_POWERSAFE_OVERWRITE opcode.
6156 */
6157 static int SQLITE_TCLAPI file_control_powersafe_overwrite(
6158   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6159   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6160   int objc,              /* Number of arguments */
6161   Tcl_Obj *CONST objv[]  /* Command arguments */
6162 ){
6163   sqlite3 *db;
6164   int rc;
6165   int b;
6166   char z[100];
6167 
6168   if( objc!=3 ){
6169     Tcl_AppendResult(interp, "wrong # args: should be \"",
6170         Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
6171     return TCL_ERROR;
6172   }
6173   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6174     return TCL_ERROR;
6175   }
6176   if( Tcl_GetIntFromObj(interp, objv[2], &b) ) return TCL_ERROR;
6177   rc = sqlite3_file_control(db,NULL,SQLITE_FCNTL_POWERSAFE_OVERWRITE,(void*)&b);
6178   sqlite3_snprintf(sizeof(z), z, "%d %d", rc, b);
6179   Tcl_AppendResult(interp, z, (char*)0);
6180   return TCL_OK;
6181 }
6182 
6183 
6184 /*
6185 ** tclcmd:   file_control_vfsname DB ?AUXDB?
6186 **
6187 ** Return a string that describes the stack of VFSes.
6188 */
6189 static int SQLITE_TCLAPI file_control_vfsname(
6190   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6191   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6192   int objc,              /* Number of arguments */
6193   Tcl_Obj *CONST objv[]  /* Command arguments */
6194 ){
6195   sqlite3 *db;
6196   const char *zDbName = "main";
6197   char *zVfsName = 0;
6198 
6199   if( objc!=2 && objc!=3 ){
6200     Tcl_AppendResult(interp, "wrong # args: should be \"",
6201         Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
6202     return TCL_ERROR;
6203   }
6204   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6205     return TCL_ERROR;
6206   }
6207   if( objc==3 ){
6208     zDbName = Tcl_GetString(objv[2]);
6209   }
6210   sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName);
6211   Tcl_AppendResult(interp, zVfsName, (char*)0);
6212   sqlite3_free(zVfsName);
6213   return TCL_OK;
6214 }
6215 
6216 /*
6217 ** tclcmd:   file_control_tempfilename DB ?AUXDB?
6218 **
6219 ** Return a string that is a temporary filename
6220 */
6221 static int SQLITE_TCLAPI file_control_tempfilename(
6222   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6223   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6224   int objc,              /* Number of arguments */
6225   Tcl_Obj *CONST objv[]  /* Command arguments */
6226 ){
6227   sqlite3 *db;
6228   const char *zDbName = "main";
6229   char *zTName = 0;
6230 
6231   if( objc!=2 && objc!=3 ){
6232     Tcl_AppendResult(interp, "wrong # args: should be \"",
6233         Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
6234     return TCL_ERROR;
6235   }
6236   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6237     return TCL_ERROR;
6238   }
6239   if( objc==3 ){
6240     zDbName = Tcl_GetString(objv[2]);
6241   }
6242   sqlite3_file_control(db, zDbName, SQLITE_FCNTL_TEMPFILENAME, (void*)&zTName);
6243   Tcl_AppendResult(interp, zTName, (char*)0);
6244   sqlite3_free(zTName);
6245   return TCL_OK;
6246 }
6247 
6248 
6249 /*
6250 ** tclcmd:   sqlite3_vfs_list
6251 **
6252 **   Return a tcl list containing the names of all registered vfs's.
6253 */
6254 static int SQLITE_TCLAPI vfs_list(
6255   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6256   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6257   int objc,              /* Number of arguments */
6258   Tcl_Obj *CONST objv[]  /* Command arguments */
6259 ){
6260   sqlite3_vfs *pVfs;
6261   Tcl_Obj *pRet = Tcl_NewObj();
6262   if( objc!=1 ){
6263     Tcl_WrongNumArgs(interp, 1, objv, "");
6264     return TCL_ERROR;
6265   }
6266   for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
6267     Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(pVfs->zName, -1));
6268   }
6269   Tcl_SetObjResult(interp, pRet);
6270   return TCL_OK;
6271 }
6272 
6273 /*
6274 ** tclcmd:   sqlite3_limit DB ID VALUE
6275 **
6276 ** This TCL command runs the sqlite3_limit interface and
6277 ** verifies correct operation of the same.
6278 */
6279 static int SQLITE_TCLAPI test_limit(
6280   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6281   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6282   int objc,              /* Number of arguments */
6283   Tcl_Obj *CONST objv[]  /* Command arguments */
6284 ){
6285   sqlite3 *db;
6286   int rc;
6287   static const struct {
6288      char *zName;
6289      int id;
6290   } aId[] = {
6291     { "SQLITE_LIMIT_LENGTH",              SQLITE_LIMIT_LENGTH               },
6292     { "SQLITE_LIMIT_SQL_LENGTH",          SQLITE_LIMIT_SQL_LENGTH           },
6293     { "SQLITE_LIMIT_COLUMN",              SQLITE_LIMIT_COLUMN               },
6294     { "SQLITE_LIMIT_EXPR_DEPTH",          SQLITE_LIMIT_EXPR_DEPTH           },
6295     { "SQLITE_LIMIT_COMPOUND_SELECT",     SQLITE_LIMIT_COMPOUND_SELECT      },
6296     { "SQLITE_LIMIT_VDBE_OP",             SQLITE_LIMIT_VDBE_OP              },
6297     { "SQLITE_LIMIT_FUNCTION_ARG",        SQLITE_LIMIT_FUNCTION_ARG         },
6298     { "SQLITE_LIMIT_ATTACHED",            SQLITE_LIMIT_ATTACHED             },
6299     { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH  },
6300     { "SQLITE_LIMIT_VARIABLE_NUMBER",     SQLITE_LIMIT_VARIABLE_NUMBER      },
6301     { "SQLITE_LIMIT_TRIGGER_DEPTH",       SQLITE_LIMIT_TRIGGER_DEPTH        },
6302     { "SQLITE_LIMIT_WORKER_THREADS",      SQLITE_LIMIT_WORKER_THREADS       },
6303 
6304     /* Out of range test cases */
6305     { "SQLITE_LIMIT_TOOSMALL",            -1,                               },
6306     { "SQLITE_LIMIT_TOOBIG",              SQLITE_LIMIT_WORKER_THREADS+1     },
6307   };
6308   int i, id = 0;
6309   int val;
6310   const char *zId;
6311 
6312   if( objc!=4 ){
6313     Tcl_AppendResult(interp, "wrong # args: should be \"",
6314         Tcl_GetStringFromObj(objv[0], 0), " DB ID VALUE", 0);
6315     return TCL_ERROR;
6316   }
6317   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
6318   zId = Tcl_GetString(objv[2]);
6319   for(i=0; i<sizeof(aId)/sizeof(aId[0]); i++){
6320     if( strcmp(zId, aId[i].zName)==0 ){
6321       id = aId[i].id;
6322       break;
6323     }
6324   }
6325   if( i>=sizeof(aId)/sizeof(aId[0]) ){
6326     Tcl_AppendResult(interp, "unknown limit type: ", zId, (char*)0);
6327     return TCL_ERROR;
6328   }
6329   if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
6330   rc = sqlite3_limit(db, id, val);
6331   Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
6332   return TCL_OK;
6333 }
6334 
6335 /*
6336 ** tclcmd:  save_prng_state
6337 **
6338 ** Save the state of the pseudo-random number generator.
6339 ** At the same time, verify that sqlite3_test_control works even when
6340 ** called with an out-of-range opcode.
6341 */
6342 static int SQLITE_TCLAPI save_prng_state(
6343   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6344   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6345   int objc,              /* Number of arguments */
6346   Tcl_Obj *CONST objv[]  /* Command arguments */
6347 ){
6348   int rc = sqlite3_test_control(9999);
6349   assert( rc==0 );
6350   rc = sqlite3_test_control(-1);
6351   assert( rc==0 );
6352   sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SAVE);
6353   return TCL_OK;
6354 }
6355 /*
6356 ** tclcmd:  restore_prng_state
6357 */
6358 static int SQLITE_TCLAPI restore_prng_state(
6359   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6360   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6361   int objc,              /* Number of arguments */
6362   Tcl_Obj *CONST objv[]  /* Command arguments */
6363 ){
6364   sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESTORE);
6365   return TCL_OK;
6366 }
6367 /*
6368 ** tclcmd:  reset_prng_state
6369 */
6370 static int SQLITE_TCLAPI reset_prng_state(
6371   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6372   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6373   int objc,              /* Number of arguments */
6374   Tcl_Obj *CONST objv[]  /* Command arguments */
6375 ){
6376   sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESET);
6377   return TCL_OK;
6378 }
6379 
6380 /*
6381 ** tclcmd:  database_may_be_corrupt
6382 **
6383 ** Indicate that database files might be corrupt. In other words, set the normal
6384 ** state of operation.
6385 */
6386 static int SQLITE_TCLAPI database_may_be_corrupt(
6387   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6388   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6389   int objc,              /* Number of arguments */
6390   Tcl_Obj *CONST objv[]  /* Command arguments */
6391 ){
6392   sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 0);
6393   return TCL_OK;
6394 }
6395 /*
6396 ** tclcmd:  database_never_corrupt
6397 **
6398 ** Indicate that database files are always well-formed. This enables
6399 ** extra assert() statements that test conditions that are always true
6400 ** for well-formed databases.
6401 */
6402 static int SQLITE_TCLAPI database_never_corrupt(
6403   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6404   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6405   int objc,              /* Number of arguments */
6406   Tcl_Obj *CONST objv[]  /* Command arguments */
6407 ){
6408   sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 1);
6409   return TCL_OK;
6410 }
6411 
6412 /*
6413 ** tclcmd:  pcache_stats
6414 */
6415 static int SQLITE_TCLAPI test_pcache_stats(
6416   ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6417   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6418   int objc,              /* Number of arguments */
6419   Tcl_Obj *CONST objv[]  /* Command arguments */
6420 ){
6421   int nMin;
6422   int nMax;
6423   int nCurrent;
6424   int nRecyclable;
6425   Tcl_Obj *pRet;
6426 
6427   sqlite3PcacheStats(&nCurrent, &nMax, &nMin, &nRecyclable);
6428 
6429   pRet = Tcl_NewObj();
6430   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("current", -1));
6431   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCurrent));
6432   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("max", -1));
6433   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMax));
6434   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("min", -1));
6435   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMin));
6436   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("recyclable", -1));
6437   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nRecyclable));
6438 
6439   Tcl_SetObjResult(interp, pRet);
6440 
6441   return TCL_OK;
6442 }
6443 
6444 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
6445 static void test_unlock_notify_cb(void **aArg, int nArg){
6446   int ii;
6447   for(ii=0; ii<nArg; ii++){
6448     Tcl_EvalEx((Tcl_Interp *)aArg[ii], "unlock_notify", -1, TCL_EVAL_GLOBAL);
6449   }
6450 }
6451 #endif /* SQLITE_ENABLE_UNLOCK_NOTIFY */
6452 
6453 /*
6454 ** tclcmd:  sqlite3_unlock_notify db
6455 */
6456 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
6457 static int SQLITE_TCLAPI test_unlock_notify(
6458   ClientData clientData, /* Unused */
6459   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6460   int objc,              /* Number of arguments */
6461   Tcl_Obj *CONST objv[]  /* Command arguments */
6462 ){
6463   sqlite3 *db;
6464   int rc;
6465 
6466   if( objc!=2 ){
6467     Tcl_WrongNumArgs(interp, 1, objv, "DB");
6468     return TCL_ERROR;
6469   }
6470 
6471   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6472     return TCL_ERROR;
6473   }
6474   rc = sqlite3_unlock_notify(db, test_unlock_notify_cb, (void *)interp);
6475   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
6476   return TCL_OK;
6477 }
6478 #endif
6479 
6480 /*
6481 ** tclcmd:  sqlite3_wal_checkpoint db ?NAME?
6482 */
6483 static int SQLITE_TCLAPI test_wal_checkpoint(
6484   ClientData clientData, /* Unused */
6485   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6486   int objc,              /* Number of arguments */
6487   Tcl_Obj *CONST objv[]  /* Command arguments */
6488 ){
6489   char *zDb = 0;
6490   sqlite3 *db;
6491   int rc;
6492 
6493   if( objc!=3 && objc!=2 ){
6494     Tcl_WrongNumArgs(interp, 1, objv, "DB ?NAME?");
6495     return TCL_ERROR;
6496   }
6497 
6498   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6499     return TCL_ERROR;
6500   }
6501   if( objc==3 ){
6502     zDb = Tcl_GetString(objv[2]);
6503   }
6504   rc = sqlite3_wal_checkpoint(db, zDb);
6505   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
6506   return TCL_OK;
6507 }
6508 
6509 /*
6510 ** tclcmd:  sqlite3_wal_checkpoint_v2 db MODE ?NAME?
6511 **
6512 ** This command calls the wal_checkpoint_v2() function with the specified
6513 ** mode argument (passive, full or restart). If present, the database name
6514 ** NAME is passed as the second argument to wal_checkpoint_v2(). If it the
6515 ** NAME argument is not present, a NULL pointer is passed instead.
6516 **
6517 ** If wal_checkpoint_v2() returns any value other than SQLITE_BUSY or
6518 ** SQLITE_OK, then this command returns TCL_ERROR. The Tcl result is set
6519 ** to the error message obtained from sqlite3_errmsg().
6520 **
6521 ** Otherwise, this command returns a list of three integers. The first integer
6522 ** is 1 if SQLITE_BUSY was returned, or 0 otherwise. The following two integers
6523 ** are the values returned via the output parameters by wal_checkpoint_v2() -
6524 ** the number of frames in the log and the number of frames in the log
6525 ** that have been checkpointed.
6526 */
6527 static int SQLITE_TCLAPI test_wal_checkpoint_v2(
6528   ClientData clientData, /* Unused */
6529   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6530   int objc,              /* Number of arguments */
6531   Tcl_Obj *CONST objv[]  /* Command arguments */
6532 ){
6533   char *zDb = 0;
6534   sqlite3 *db;
6535   int rc;
6536 
6537   int eMode;
6538   int nLog = -555;
6539   int nCkpt = -555;
6540   Tcl_Obj *pRet;
6541 
6542   const char * aMode[] = { "passive", "full", "restart", "truncate", 0 };
6543   assert( SQLITE_CHECKPOINT_PASSIVE==0 );
6544   assert( SQLITE_CHECKPOINT_FULL==1 );
6545   assert( SQLITE_CHECKPOINT_RESTART==2 );
6546   assert( SQLITE_CHECKPOINT_TRUNCATE==3 );
6547 
6548   if( objc!=3 && objc!=4 ){
6549     Tcl_WrongNumArgs(interp, 1, objv, "DB MODE ?NAME?");
6550     return TCL_ERROR;
6551   }
6552 
6553   if( objc==4 ){
6554     zDb = Tcl_GetString(objv[3]);
6555   }
6556   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) || (
6557       TCL_OK!=Tcl_GetIntFromObj(0, objv[2], &eMode)
6558    && TCL_OK!=Tcl_GetIndexFromObj(interp, objv[2], aMode, "mode", 0, &eMode)
6559   )){
6560     return TCL_ERROR;
6561   }
6562 
6563   rc = sqlite3_wal_checkpoint_v2(db, zDb, eMode, &nLog, &nCkpt);
6564   if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
6565     const char *zErrCode = sqlite3ErrName(rc);
6566     Tcl_ResetResult(interp);
6567     Tcl_AppendResult(interp, zErrCode, " - ", (char *)sqlite3_errmsg(db), 0);
6568     return TCL_ERROR;
6569   }
6570 
6571   pRet = Tcl_NewObj();
6572   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(rc==SQLITE_BUSY?1:0));
6573   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nLog));
6574   Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCkpt));
6575   Tcl_SetObjResult(interp, pRet);
6576 
6577   return TCL_OK;
6578 }
6579 
6580 /*
6581 ** tclcmd:  sqlite3_wal_autocheckpoint db VALUE
6582 */
6583 static int SQLITE_TCLAPI test_wal_autocheckpoint(
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   sqlite3 *db;
6590   int rc;
6591   int iVal;
6592 
6593 
6594   if( objc!=3 ){
6595     Tcl_WrongNumArgs(interp, 1, objv, "DB VALUE");
6596     return TCL_ERROR;
6597   }
6598 
6599   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
6600    || Tcl_GetIntFromObj(0, objv[2], &iVal)
6601   ){
6602     return TCL_ERROR;
6603   }
6604 
6605   rc = sqlite3_wal_autocheckpoint(db, iVal);
6606   Tcl_ResetResult(interp);
6607   if( rc!=SQLITE_OK ){
6608     const char *zErrCode = sqlite3ErrName(rc);
6609     Tcl_SetObjResult(interp, Tcl_NewStringObj(zErrCode, -1));
6610     return TCL_ERROR;
6611   }
6612 
6613   return TCL_OK;
6614 }
6615 
6616 
6617 /*
6618 ** tclcmd:  test_sqlite3_log ?SCRIPT?
6619 */
6620 static struct LogCallback {
6621   Tcl_Interp *pInterp;
6622   Tcl_Obj *pObj;
6623 } logcallback = {0, 0};
6624 static void xLogcallback(void *unused, int err, char *zMsg){
6625   Tcl_Obj *pNew = Tcl_DuplicateObj(logcallback.pObj);
6626   Tcl_IncrRefCount(pNew);
6627   Tcl_ListObjAppendElement(
6628       0, pNew, Tcl_NewStringObj(sqlite3ErrName(err), -1)
6629   );
6630   Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zMsg, -1));
6631   Tcl_EvalObjEx(logcallback.pInterp, pNew, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
6632   Tcl_DecrRefCount(pNew);
6633 }
6634 static int SQLITE_TCLAPI test_sqlite3_log(
6635   ClientData clientData,
6636   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6637   int objc,              /* Number of arguments */
6638   Tcl_Obj *CONST objv[]  /* Command arguments */
6639 ){
6640   if( objc>2 ){
6641     Tcl_WrongNumArgs(interp, 1, objv, "SCRIPT");
6642     return TCL_ERROR;
6643   }
6644   if( logcallback.pObj ){
6645     Tcl_DecrRefCount(logcallback.pObj);
6646     logcallback.pObj = 0;
6647     logcallback.pInterp = 0;
6648     sqlite3_config(SQLITE_CONFIG_LOG, (void*)0, (void*)0);
6649   }
6650   if( objc>1 ){
6651     logcallback.pObj = objv[1];
6652     Tcl_IncrRefCount(logcallback.pObj);
6653     logcallback.pInterp = interp;
6654     sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, (void*)0);
6655   }
6656   return TCL_OK;
6657 }
6658 
6659 /*
6660 **     tcl_objproc COMMANDNAME ARGS...
6661 **
6662 ** Run a TCL command using its objProc interface.  Throw an error if
6663 ** the command has no objProc interface.
6664 */
6665 static int SQLITE_TCLAPI runAsObjProc(
6666   void * clientData,
6667   Tcl_Interp *interp,
6668   int objc,
6669   Tcl_Obj *CONST objv[]
6670 ){
6671   Tcl_CmdInfo cmdInfo;
6672   if( objc<2 ){
6673     Tcl_WrongNumArgs(interp, 1, objv, "COMMAND ...");
6674     return TCL_ERROR;
6675   }
6676   if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
6677     Tcl_AppendResult(interp, "command not found: ",
6678            Tcl_GetString(objv[1]), (char*)0);
6679     return TCL_ERROR;
6680   }
6681   if( cmdInfo.objProc==0 ){
6682     Tcl_AppendResult(interp, "command has no objProc: ",
6683            Tcl_GetString(objv[1]), (char*)0);
6684     return TCL_ERROR;
6685   }
6686   return cmdInfo.objProc(cmdInfo.objClientData, interp, objc-1, objv+1);
6687 }
6688 
6689 #ifndef SQLITE_OMIT_EXPLAIN
6690 /*
6691 ** WARNING: The following function, printExplainQueryPlan() is an exact
6692 ** copy of example code from eqp.in (eqp.html). If this code is modified,
6693 ** then the documentation copy needs to be modified as well.
6694 */
6695 /*
6696 ** Argument pStmt is a prepared SQL statement. This function compiles
6697 ** an EXPLAIN QUERY PLAN command to report on the prepared statement,
6698 ** and prints the report to stdout using printf().
6699 */
6700 int printExplainQueryPlan(sqlite3_stmt *pStmt){
6701   const char *zSql;               /* Input SQL */
6702   char *zExplain;                 /* SQL with EXPLAIN QUERY PLAN prepended */
6703   sqlite3_stmt *pExplain;         /* Compiled EXPLAIN QUERY PLAN command */
6704   int rc;                         /* Return code from sqlite3_prepare_v2() */
6705 
6706   zSql = sqlite3_sql(pStmt);
6707   if( zSql==0 ) return SQLITE_ERROR;
6708 
6709   zExplain = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zSql);
6710   if( zExplain==0 ) return SQLITE_NOMEM;
6711 
6712   rc = sqlite3_prepare_v2(sqlite3_db_handle(pStmt), zExplain, -1, &pExplain, 0);
6713   sqlite3_free(zExplain);
6714   if( rc!=SQLITE_OK ) return rc;
6715 
6716   while( SQLITE_ROW==sqlite3_step(pExplain) ){
6717     int iSelectid = sqlite3_column_int(pExplain, 0);
6718     int iOrder = sqlite3_column_int(pExplain, 1);
6719     int iFrom = sqlite3_column_int(pExplain, 2);
6720     const char *zDetail = (const char *)sqlite3_column_text(pExplain, 3);
6721 
6722     printf("%d %d %d %s\n", iSelectid, iOrder, iFrom, zDetail);
6723   }
6724 
6725   return sqlite3_finalize(pExplain);
6726 }
6727 
6728 static int SQLITE_TCLAPI test_print_eqp(
6729   void * clientData,
6730   Tcl_Interp *interp,
6731   int objc,
6732   Tcl_Obj *CONST objv[]
6733 ){
6734   int rc;
6735   sqlite3_stmt *pStmt;
6736 
6737   if( objc!=2 ){
6738     Tcl_WrongNumArgs(interp, 1, objv, "STMT");
6739     return TCL_ERROR;
6740   }
6741   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
6742   rc = printExplainQueryPlan(pStmt);
6743   /* This is needed on Windows so that a test case using this
6744   ** function can open a read pipe and get the output of
6745   ** printExplainQueryPlan() immediately.
6746   */
6747   fflush(stdout);
6748   Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
6749   return TCL_OK;
6750 }
6751 #endif /* SQLITE_OMIT_EXPLAIN */
6752 
6753 /*
6754 ** sqlite3_test_control VERB ARGS...
6755 */
6756 static int SQLITE_TCLAPI test_test_control(
6757   void * clientData,
6758   Tcl_Interp *interp,
6759   int objc,
6760   Tcl_Obj *CONST objv[]
6761 ){
6762   struct Verb {
6763     const char *zName;
6764     int i;
6765   } aVerb[] = {
6766     { "SQLITE_TESTCTRL_LOCALTIME_FAULT",    SQLITE_TESTCTRL_LOCALTIME_FAULT },
6767     { "SQLITE_TESTCTRL_SORTER_MMAP",        SQLITE_TESTCTRL_SORTER_MMAP     },
6768     { "SQLITE_TESTCTRL_IMPOSTER",           SQLITE_TESTCTRL_IMPOSTER        },
6769     { "SQLITE_TESTCTRL_INTERNAL_FUNCTIONS", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS},
6770   };
6771   int iVerb;
6772   int iFlag;
6773   int rc;
6774 
6775   if( objc<2 ){
6776     Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS...");
6777     return TCL_ERROR;
6778   }
6779 
6780   rc = Tcl_GetIndexFromObjStruct(
6781       interp, objv[1], aVerb, sizeof(aVerb[0]), "VERB", 0, &iVerb
6782   );
6783   if( rc!=TCL_OK ) return rc;
6784 
6785   iFlag = aVerb[iVerb].i;
6786   switch( iFlag ){
6787     case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
6788     case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
6789       int val;
6790       if( objc!=3 ){
6791         Tcl_WrongNumArgs(interp, 2, objv, "ONOFF");
6792         return TCL_ERROR;
6793       }
6794       if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
6795       sqlite3_test_control(iFlag, val);
6796       break;
6797     }
6798 
6799     case SQLITE_TESTCTRL_SORTER_MMAP: {
6800       int val;
6801       sqlite3 *db;
6802       if( objc!=4 ){
6803         Tcl_WrongNumArgs(interp, 2, objv, "DB LIMIT");
6804         return TCL_ERROR;
6805       }
6806       if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
6807       if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
6808       sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, val);
6809       break;
6810     }
6811 
6812     case SQLITE_TESTCTRL_IMPOSTER: {
6813       int onOff, tnum;
6814       const char *zDbName;
6815       sqlite3 *db;
6816       if( objc!=6 ){
6817         Tcl_WrongNumArgs(interp, 2, objv, "DB dbName onOff tnum");
6818         return TCL_ERROR;
6819       }
6820       if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
6821       zDbName = Tcl_GetString(objv[3]);
6822       if( Tcl_GetIntFromObj(interp, objv[4], &onOff) ) return TCL_ERROR;
6823       if( Tcl_GetIntFromObj(interp, objv[5], &tnum) ) return TCL_ERROR;
6824       sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zDbName, onOff, tnum);
6825       break;
6826     }
6827   }
6828 
6829   Tcl_ResetResult(interp);
6830   return TCL_OK;
6831 }
6832 
6833 #if SQLITE_OS_UNIX
6834 #include <sys/time.h>
6835 #include <sys/resource.h>
6836 
6837 static int SQLITE_TCLAPI test_getrusage(
6838   void * clientData,
6839   Tcl_Interp *interp,
6840   int objc,
6841   Tcl_Obj *CONST objv[]
6842 ){
6843   char buf[1024];
6844   struct rusage r;
6845   memset(&r, 0, sizeof(r));
6846   getrusage(RUSAGE_SELF, &r);
6847 
6848   sqlite3_snprintf(sizeof(buf), buf,
6849     "ru_utime=%d.%06d ru_stime=%d.%06d ru_minflt=%d ru_majflt=%d",
6850     (int)r.ru_utime.tv_sec, (int)r.ru_utime.tv_usec,
6851     (int)r.ru_stime.tv_sec, (int)r.ru_stime.tv_usec,
6852     (int)r.ru_minflt, (int)r.ru_majflt
6853   );
6854   Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
6855   return TCL_OK;
6856 }
6857 #endif
6858 
6859 #if SQLITE_OS_WIN
6860 /*
6861 ** Information passed from the main thread into the windows file locker
6862 ** background thread.
6863 */
6864 struct win32FileLocker {
6865   char *evName;       /* Name of event to signal thread startup */
6866   HANDLE h;           /* Handle of the file to be locked */
6867   int delay1;         /* Delay before locking */
6868   int delay2;         /* Delay before unlocking */
6869   int ok;             /* Finished ok */
6870   int err;            /* True if an error occurs */
6871 };
6872 #endif
6873 
6874 
6875 #if SQLITE_OS_WIN
6876 #include <process.h>
6877 /*
6878 ** The background thread that does file locking.
6879 */
6880 static void SQLITE_CDECL win32_file_locker(void *pAppData){
6881   struct win32FileLocker *p = (struct win32FileLocker*)pAppData;
6882   if( p->evName ){
6883     HANDLE ev = OpenEvent(EVENT_MODIFY_STATE, FALSE, p->evName);
6884     if ( ev ){
6885       SetEvent(ev);
6886       CloseHandle(ev);
6887     }
6888   }
6889   if( p->delay1 ) Sleep(p->delay1);
6890   if( LockFile(p->h, 0, 0, 100000000, 0) ){
6891     Sleep(p->delay2);
6892     UnlockFile(p->h, 0, 0, 100000000, 0);
6893     p->ok = 1;
6894   }else{
6895     p->err = 1;
6896   }
6897   CloseHandle(p->h);
6898   p->h = 0;
6899   p->delay1 = 0;
6900   p->delay2 = 0;
6901 }
6902 #endif
6903 
6904 #if SQLITE_OS_WIN
6905 /*
6906 **      lock_win32_file FILENAME DELAY1 DELAY2
6907 **
6908 ** Get an exclusive manditory lock on file for DELAY2 milliseconds.
6909 ** Wait DELAY1 milliseconds before acquiring the lock.
6910 */
6911 static int SQLITE_TCLAPI win32_file_lock(
6912   void * clientData,
6913   Tcl_Interp *interp,
6914   int objc,
6915   Tcl_Obj *CONST objv[]
6916 ){
6917   static struct win32FileLocker x = { "win32_file_lock", 0, 0, 0, 0, 0 };
6918   const char *zFilename;
6919   char zBuf[200];
6920   int retry = 0;
6921   HANDLE ev;
6922   DWORD wResult;
6923 
6924   if( objc!=4 && objc!=1 ){
6925     Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2");
6926     return TCL_ERROR;
6927   }
6928   if( objc==1 ){
6929     sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d",
6930                      x.ok, x.err, x.delay1, x.delay2, x.h);
6931     Tcl_AppendResult(interp, zBuf, (char*)0);
6932     return TCL_OK;
6933   }
6934   while( x.h && retry<30 ){
6935     retry++;
6936     Sleep(100);
6937   }
6938   if( x.h ){
6939     Tcl_AppendResult(interp, "busy", (char*)0);
6940     return TCL_ERROR;
6941   }
6942   if( Tcl_GetIntFromObj(interp, objv[2], &x.delay1) ) return TCL_ERROR;
6943   if( Tcl_GetIntFromObj(interp, objv[3], &x.delay2) ) return TCL_ERROR;
6944   zFilename = Tcl_GetString(objv[1]);
6945   x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE,
6946               FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
6947               FILE_ATTRIBUTE_NORMAL, 0);
6948   if( !x.h ){
6949     Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0);
6950     return TCL_ERROR;
6951   }
6952   ev = CreateEvent(NULL, TRUE, FALSE, x.evName);
6953   if ( !ev ){
6954     Tcl_AppendResult(interp, "cannot create event: ", x.evName, (char*)0);
6955     return TCL_ERROR;
6956   }
6957   _beginthread(win32_file_locker, 0, (void*)&x);
6958   Sleep(0);
6959   if ( (wResult = WaitForSingleObject(ev, 10000))!=WAIT_OBJECT_0 ){
6960     sqlite3_snprintf(sizeof(zBuf), zBuf, "0x%x", wResult);
6961     Tcl_AppendResult(interp, "wait failed: ", zBuf, (char*)0);
6962     CloseHandle(ev);
6963     return TCL_ERROR;
6964   }
6965   CloseHandle(ev);
6966   return TCL_OK;
6967 }
6968 
6969 /*
6970 **      exists_win32_path PATH
6971 **
6972 ** Returns non-zero if the specified path exists, whose fully qualified name
6973 ** may exceed 260 characters if it is prefixed with "\\?\".
6974 */
6975 static int SQLITE_TCLAPI win32_exists_path(
6976   void *clientData,
6977   Tcl_Interp *interp,
6978   int objc,
6979   Tcl_Obj *CONST objv[]
6980 ){
6981   if( objc!=2 ){
6982     Tcl_WrongNumArgs(interp, 1, objv, "PATH");
6983     return TCL_ERROR;
6984   }
6985   Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
6986       GetFileAttributesW( Tcl_GetUnicode(objv[1]))!=INVALID_FILE_ATTRIBUTES ));
6987   return TCL_OK;
6988 }
6989 
6990 /*
6991 **      find_win32_file PATTERN
6992 **
6993 ** Returns a list of entries in a directory that match the specified pattern,
6994 ** whose fully qualified name may exceed 248 characters if it is prefixed with
6995 ** "\\?\".
6996 */
6997 static int SQLITE_TCLAPI win32_find_file(
6998   void *clientData,
6999   Tcl_Interp *interp,
7000   int objc,
7001   Tcl_Obj *CONST objv[]
7002 ){
7003   HANDLE hFindFile = INVALID_HANDLE_VALUE;
7004   WIN32_FIND_DATAW findData;
7005   Tcl_Obj *listObj;
7006   DWORD lastErrno;
7007   if( objc!=2 ){
7008     Tcl_WrongNumArgs(interp, 1, objv, "PATTERN");
7009     return TCL_ERROR;
7010   }
7011   hFindFile = FindFirstFileW(Tcl_GetUnicode(objv[1]), &findData);
7012   if( hFindFile==INVALID_HANDLE_VALUE ){
7013     Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
7014     return TCL_ERROR;
7015   }
7016   listObj = Tcl_NewObj();
7017   Tcl_IncrRefCount(listObj);
7018   do {
7019     Tcl_ListObjAppendElement(interp, listObj, Tcl_NewUnicodeObj(
7020         findData.cFileName, -1));
7021     Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(
7022         findData.dwFileAttributes));
7023   } while( FindNextFileW(hFindFile, &findData) );
7024   lastErrno = GetLastError();
7025   if( lastErrno!=NO_ERROR && lastErrno!=ERROR_NO_MORE_FILES ){
7026     FindClose(hFindFile);
7027     Tcl_DecrRefCount(listObj);
7028     Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
7029     return TCL_ERROR;
7030   }
7031   FindClose(hFindFile);
7032   Tcl_SetObjResult(interp, listObj);
7033   return TCL_OK;
7034 }
7035 
7036 /*
7037 **      delete_win32_file FILENAME
7038 **
7039 ** Deletes the specified file, whose fully qualified name may exceed 260
7040 ** characters if it is prefixed with "\\?\".
7041 */
7042 static int SQLITE_TCLAPI win32_delete_file(
7043   void *clientData,
7044   Tcl_Interp *interp,
7045   int objc,
7046   Tcl_Obj *CONST objv[]
7047 ){
7048   if( objc!=2 ){
7049     Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
7050     return TCL_ERROR;
7051   }
7052   if( !DeleteFileW(Tcl_GetUnicode(objv[1])) ){
7053     Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
7054     return TCL_ERROR;
7055   }
7056   Tcl_ResetResult(interp);
7057   return TCL_OK;
7058 }
7059 
7060 /*
7061 **      make_win32_dir DIRECTORY
7062 **
7063 ** Creates the specified directory, whose fully qualified name may exceed 248
7064 ** characters if it is prefixed with "\\?\".
7065 */
7066 static int SQLITE_TCLAPI win32_mkdir(
7067   void *clientData,
7068   Tcl_Interp *interp,
7069   int objc,
7070   Tcl_Obj *CONST objv[]
7071 ){
7072   if( objc!=2 ){
7073     Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY");
7074     return TCL_ERROR;
7075   }
7076   if( !CreateDirectoryW(Tcl_GetUnicode(objv[1]), NULL) ){
7077     Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
7078     return TCL_ERROR;
7079   }
7080   Tcl_ResetResult(interp);
7081   return TCL_OK;
7082 }
7083 
7084 /*
7085 **      remove_win32_dir DIRECTORY
7086 **
7087 ** Removes the specified directory, whose fully qualified name may exceed 248
7088 ** characters if it is prefixed with "\\?\".
7089 */
7090 static int SQLITE_TCLAPI win32_rmdir(
7091   void *clientData,
7092   Tcl_Interp *interp,
7093   int objc,
7094   Tcl_Obj *CONST objv[]
7095 ){
7096   if( objc!=2 ){
7097     Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY");
7098     return TCL_ERROR;
7099   }
7100   if( !RemoveDirectoryW(Tcl_GetUnicode(objv[1])) ){
7101     Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
7102     return TCL_ERROR;
7103   }
7104   Tcl_ResetResult(interp);
7105   return TCL_OK;
7106 }
7107 #endif
7108 
7109 
7110 /*
7111 **      optimization_control DB OPT BOOLEAN
7112 **
7113 ** Enable or disable query optimizations using the sqlite3_test_control()
7114 ** interface.  Disable if BOOLEAN is false and enable if BOOLEAN is true.
7115 ** OPT is the name of the optimization to be disabled.
7116 */
7117 static int SQLITE_TCLAPI optimization_control(
7118   void * clientData,
7119   Tcl_Interp *interp,
7120   int objc,
7121   Tcl_Obj *CONST objv[]
7122 ){
7123   int i;
7124   sqlite3 *db;
7125   const char *zOpt;
7126   int onoff;
7127   int mask = 0;
7128   static const struct {
7129     const char *zOptName;
7130     int mask;
7131   } aOpt[] = {
7132     { "all",                 SQLITE_AllOpts        },
7133     { "none",                0                     },
7134     { "query-flattener",     SQLITE_QueryFlattener },
7135     { "groupby-order",       SQLITE_GroupByOrder   },
7136     { "factor-constants",    SQLITE_FactorOutConst },
7137     { "distinct-opt",        SQLITE_DistinctOpt    },
7138     { "cover-idx-scan",      SQLITE_CoverIdxScan   },
7139     { "order-by-idx-join",   SQLITE_OrderByIdxJoin },
7140     { "transitive",          SQLITE_Transitive     },
7141     { "omit-noop-join",      SQLITE_OmitNoopJoin   },
7142     { "stat3",               SQLITE_Stat34         },
7143     { "stat4",               SQLITE_Stat34         },
7144     { "skip-scan",           SQLITE_SkipScan       },
7145   };
7146 
7147   if( objc!=4 ){
7148     Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN");
7149     return TCL_ERROR;
7150   }
7151   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
7152   if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR;
7153   zOpt = Tcl_GetString(objv[2]);
7154   for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
7155     if( strcmp(zOpt, aOpt[i].zOptName)==0 ){
7156       mask = aOpt[i].mask;
7157       break;
7158     }
7159   }
7160   if( onoff ) mask = ~mask;
7161   if( i>=sizeof(aOpt)/sizeof(aOpt[0]) ){
7162     Tcl_AppendResult(interp, "unknown optimization - should be one of:",
7163                      (char*)0);
7164     for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
7165       Tcl_AppendResult(interp, " ", aOpt[i].zOptName, (char*)0);
7166     }
7167     return TCL_ERROR;
7168   }
7169   sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask);
7170   return TCL_OK;
7171 }
7172 
7173 /*
7174 **     load_static_extension DB NAME ...
7175 **
7176 ** Load one or more statically linked extensions.
7177 */
7178 static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
7179   void * clientData,
7180   Tcl_Interp *interp,
7181   int objc,
7182   Tcl_Obj *CONST objv[]
7183 ){
7184   extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*);
7185   extern int sqlite3_carray_init(sqlite3*,char**,const sqlite3_api_routines*);
7186   extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
7187   extern int sqlite3_csv_init(sqlite3*,char**,const sqlite3_api_routines*);
7188   extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*);
7189   extern int sqlite3_explain_init(sqlite3*,char**,const sqlite3_api_routines*);
7190   extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
7191   extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
7192   extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
7193   extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*);
7194   extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
7195 #ifndef SQLITE_OMIT_VIRTUALTABLE
7196   extern int sqlite3_prefixes_init(sqlite3*,char**,const sqlite3_api_routines*);
7197 #endif
7198   extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*);
7199   extern int sqlite3_remember_init(sqlite3*,char**,const sqlite3_api_routines*);
7200   extern int sqlite3_series_init(sqlite3*,char**,const sqlite3_api_routines*);
7201   extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*);
7202   extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*);
7203   extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*);
7204   extern int sqlite3_unionvtab_init(sqlite3*,char**,const sqlite3_api_routines*);
7205 #ifdef SQLITE_HAVE_ZLIB
7206   extern int sqlite3_zipfile_init(sqlite3*,char**,const sqlite3_api_routines*);
7207 #endif
7208   static const struct {
7209     const char *zExtName;
7210     int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*);
7211   } aExtension[] = {
7212     { "amatch",                sqlite3_amatch_init               },
7213     { "carray",                sqlite3_carray_init               },
7214     { "closure",               sqlite3_closure_init              },
7215     { "csv",                   sqlite3_csv_init                  },
7216     { "eval",                  sqlite3_eval_init                 },
7217     { "explain",               sqlite3_explain_init              },
7218     { "fileio",                sqlite3_fileio_init               },
7219     { "fuzzer",                sqlite3_fuzzer_init               },
7220     { "ieee754",               sqlite3_ieee_init                 },
7221     { "nextchar",              sqlite3_nextchar_init             },
7222     { "percentile",            sqlite3_percentile_init           },
7223 #ifndef SQLITE_OMIT_VIRTUALTABLE
7224     { "prefixes",              sqlite3_prefixes_init             },
7225 #endif
7226     { "regexp",                sqlite3_regexp_init               },
7227     { "remember",              sqlite3_remember_init             },
7228     { "series",                sqlite3_series_init               },
7229     { "spellfix",              sqlite3_spellfix_init             },
7230     { "totype",                sqlite3_totype_init               },
7231     { "unionvtab",             sqlite3_unionvtab_init            },
7232     { "wholenumber",           sqlite3_wholenumber_init          },
7233 #ifdef SQLITE_HAVE_ZLIB
7234     { "zipfile",               sqlite3_zipfile_init              },
7235 #endif
7236   };
7237   sqlite3 *db;
7238   const char *zName;
7239   int i, j, rc;
7240   char *zErrMsg = 0;
7241   if( objc<3 ){
7242     Tcl_WrongNumArgs(interp, 1, objv, "DB NAME ...");
7243     return TCL_ERROR;
7244   }
7245   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
7246   for(j=2; j<objc; j++){
7247     zName = Tcl_GetString(objv[j]);
7248     for(i=0; i<ArraySize(aExtension); i++){
7249       if( strcmp(zName, aExtension[i].zExtName)==0 ) break;
7250     }
7251     if( i>=ArraySize(aExtension) ){
7252       Tcl_AppendResult(interp, "no such extension: ", zName, (char*)0);
7253       return TCL_ERROR;
7254     }
7255     if( aExtension[i].pInit ){
7256       rc = aExtension[i].pInit(db, &zErrMsg, 0);
7257     }else{
7258       rc = SQLITE_OK;
7259     }
7260     if( rc!=SQLITE_OK || zErrMsg ){
7261       Tcl_AppendResult(interp, "initialization of ", zName, " failed: ", zErrMsg,
7262                        (char*)0);
7263       sqlite3_free(zErrMsg);
7264       return TCL_ERROR;
7265     }
7266   }
7267   return TCL_OK;
7268 }
7269 
7270 /*
7271 **     sorter_test_fakeheap BOOL
7272 **
7273 */
7274 static int SQLITE_TCLAPI sorter_test_fakeheap(
7275   void * clientData,
7276   Tcl_Interp *interp,
7277   int objc,
7278   Tcl_Obj *CONST objv[]
7279 ){
7280   int bArg;
7281   if( objc!=2 ){
7282     Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
7283     return TCL_ERROR;
7284   }
7285 
7286   if( Tcl_GetBooleanFromObj(interp, objv[1], &bArg) ){
7287     return TCL_ERROR;
7288   }
7289 
7290   if( bArg ){
7291     if( sqlite3GlobalConfig.pHeap==0 ){
7292       sqlite3GlobalConfig.pHeap = SQLITE_INT_TO_PTR(-1);
7293     }
7294   }else{
7295     if( sqlite3GlobalConfig.pHeap==SQLITE_INT_TO_PTR(-1) ){
7296       sqlite3GlobalConfig.pHeap = 0;
7297     }
7298   }
7299 
7300   Tcl_ResetResult(interp);
7301   return TCL_OK;
7302 }
7303 
7304 /*
7305 **     sorter_test_sort4_helper DB SQL1 NSTEP SQL2
7306 **
7307 ** Compile SQL statement $SQL1 and step it $NSTEP times. For each row,
7308 ** check that the leftmost and rightmost columns returned are both integers,
7309 ** and that both contain the same value.
7310 **
7311 ** Then execute statement $SQL2. Check that the statement returns the same
7312 ** set of integers in the same order as in the previous step (using $SQL1).
7313 */
7314 static int SQLITE_TCLAPI sorter_test_sort4_helper(
7315   void * clientData,
7316   Tcl_Interp *interp,
7317   int objc,
7318   Tcl_Obj *CONST objv[]
7319 ){
7320   const char *zSql1;
7321   const char *zSql2;
7322   int nStep;
7323   int iStep;
7324   unsigned int iCksum1 = 0;
7325   unsigned int iCksum2 = 0;
7326   int rc;
7327   int iB;
7328   sqlite3 *db;
7329   sqlite3_stmt *pStmt;
7330 
7331   if( objc!=5 ){
7332     Tcl_WrongNumArgs(interp, 1, objv, "DB SQL1 NSTEP SQL2");
7333     return TCL_ERROR;
7334   }
7335 
7336   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
7337   zSql1 = Tcl_GetString(objv[2]);
7338   if( Tcl_GetIntFromObj(interp, objv[3], &nStep) ) return TCL_ERROR;
7339   zSql2 = Tcl_GetString(objv[4]);
7340 
7341   rc = sqlite3_prepare_v2(db, zSql1, -1, &pStmt, 0);
7342   if( rc!=SQLITE_OK ) goto sql_error;
7343 
7344   iB = sqlite3_column_count(pStmt)-1;
7345   for(iStep=0; iStep<nStep && SQLITE_ROW==sqlite3_step(pStmt); iStep++){
7346     int a = sqlite3_column_int(pStmt, 0);
7347     if( a!=sqlite3_column_int(pStmt, iB) ){
7348       Tcl_AppendResult(interp, "data error: (a!=b)", 0);
7349       return TCL_ERROR;
7350     }
7351 
7352     iCksum1 += (iCksum1 << 3) + (unsigned int)a;
7353   }
7354   rc = sqlite3_finalize(pStmt);
7355   if( rc!=SQLITE_OK ) goto sql_error;
7356 
7357   rc = sqlite3_prepare_v2(db, zSql2, -1, &pStmt, 0);
7358   if( rc!=SQLITE_OK ) goto sql_error;
7359   for(iStep=0; SQLITE_ROW==sqlite3_step(pStmt); iStep++){
7360     int a = sqlite3_column_int(pStmt, 0);
7361     iCksum2 += (iCksum2 << 3) + (unsigned int)a;
7362   }
7363   rc = sqlite3_finalize(pStmt);
7364   if( rc!=SQLITE_OK ) goto sql_error;
7365 
7366   if( iCksum1!=iCksum2 ){
7367     Tcl_AppendResult(interp, "checksum mismatch", 0);
7368     return TCL_ERROR;
7369   }
7370 
7371   return TCL_OK;
7372  sql_error:
7373   Tcl_AppendResult(interp, "sql error: ", sqlite3_errmsg(db), 0);
7374   return TCL_ERROR;
7375 }
7376 
7377 
7378 #ifdef SQLITE_USER_AUTHENTICATION
7379 #include "sqlite3userauth.h"
7380 /*
7381 ** tclcmd:  sqlite3_user_authenticate DB USERNAME PASSWORD
7382 */
7383 static int SQLITE_TCLAPI test_user_authenticate(
7384   ClientData clientData, /* Unused */
7385   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
7386   int objc,              /* Number of arguments */
7387   Tcl_Obj *CONST objv[]  /* Command arguments */
7388 ){
7389   char *zUser = 0;
7390   char *zPasswd = 0;
7391   int nPasswd = 0;
7392   sqlite3 *db;
7393   int rc;
7394 
7395   if( objc!=4 ){
7396     Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD");
7397     return TCL_ERROR;
7398   }
7399   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
7400     return TCL_ERROR;
7401   }
7402   zUser = Tcl_GetString(objv[2]);
7403   zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
7404   rc = sqlite3_user_authenticate(db, zUser, zPasswd, nPasswd);
7405   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
7406   return TCL_OK;
7407 }
7408 #endif /* SQLITE_USER_AUTHENTICATION */
7409 
7410 #ifdef SQLITE_USER_AUTHENTICATION
7411 /*
7412 ** tclcmd:  sqlite3_user_add DB USERNAME PASSWORD ISADMIN
7413 */
7414 static int SQLITE_TCLAPI test_user_add(
7415   ClientData clientData, /* Unused */
7416   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
7417   int objc,              /* Number of arguments */
7418   Tcl_Obj *CONST objv[]  /* Command arguments */
7419 ){
7420   char *zUser = 0;
7421   char *zPasswd = 0;
7422   int nPasswd = 0;
7423   int isAdmin = 0;
7424   sqlite3 *db;
7425   int rc;
7426 
7427   if( objc!=5 ){
7428     Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
7429     return TCL_ERROR;
7430   }
7431   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
7432     return TCL_ERROR;
7433   }
7434   zUser = Tcl_GetString(objv[2]);
7435   zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
7436   Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
7437   rc = sqlite3_user_add(db, zUser, zPasswd, nPasswd, isAdmin);
7438   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
7439   return TCL_OK;
7440 }
7441 #endif /* SQLITE_USER_AUTHENTICATION */
7442 
7443 #ifdef SQLITE_USER_AUTHENTICATION
7444 /*
7445 ** tclcmd:  sqlite3_user_change DB USERNAME PASSWORD ISADMIN
7446 */
7447 static int SQLITE_TCLAPI test_user_change(
7448   ClientData clientData, /* Unused */
7449   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
7450   int objc,              /* Number of arguments */
7451   Tcl_Obj *CONST objv[]  /* Command arguments */
7452 ){
7453   char *zUser = 0;
7454   char *zPasswd = 0;
7455   int nPasswd = 0;
7456   int isAdmin = 0;
7457   sqlite3 *db;
7458   int rc;
7459 
7460   if( objc!=5 ){
7461     Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
7462     return TCL_ERROR;
7463   }
7464   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
7465     return TCL_ERROR;
7466   }
7467   zUser = Tcl_GetString(objv[2]);
7468   zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
7469   Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
7470   rc = sqlite3_user_change(db, zUser, zPasswd, nPasswd, isAdmin);
7471   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
7472   return TCL_OK;
7473 }
7474 #endif /* SQLITE_USER_AUTHENTICATION */
7475 
7476 #ifdef SQLITE_USER_AUTHENTICATION
7477 /*
7478 ** tclcmd:  sqlite3_user_delete DB USERNAME
7479 */
7480 static int SQLITE_TCLAPI test_user_delete(
7481   ClientData clientData, /* Unused */
7482   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
7483   int objc,              /* Number of arguments */
7484   Tcl_Obj *CONST objv[]  /* Command arguments */
7485 ){
7486   char *zUser = 0;
7487   sqlite3 *db;
7488   int rc;
7489 
7490   if( objc!=3 ){
7491     Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME");
7492     return TCL_ERROR;
7493   }
7494   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
7495     return TCL_ERROR;
7496   }
7497   zUser = Tcl_GetString(objv[2]);
7498   rc = sqlite3_user_delete(db, zUser);
7499   Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
7500   return TCL_OK;
7501 }
7502 #endif /* SQLITE_USER_AUTHENTICATION */
7503 
7504 /*
7505 ** tclcmd: bad_behavior TYPE
7506 **
7507 ** Do some things that should trigger a valgrind or -fsanitize=undefined
7508 ** warning.  This is used to verify that errors and warnings output by those
7509 ** tools are detected by the test scripts.
7510 **
7511 **       TYPE       BEHAVIOR
7512 **       1          Overflow a signed integer
7513 **       2          Jump based on an uninitialized variable
7514 **       3          Read after free
7515 **       4          Panic
7516 */
7517 static int SQLITE_TCLAPI test_bad_behavior(
7518   ClientData clientData, /* Pointer to an integer containing zero */
7519   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
7520   int objc,              /* Number of arguments */
7521   Tcl_Obj *CONST objv[]  /* Command arguments */
7522 ){
7523   int iType;
7524   int xyz;
7525   int i = *(int*)clientData;
7526   int j;
7527   int w[10];
7528   int *a;
7529   if( objc!=2 ){
7530     Tcl_WrongNumArgs(interp, 1, objv, "TYPE");
7531     return TCL_ERROR;
7532   }
7533   if( Tcl_GetIntFromObj(interp, objv[1], &iType) ) return TCL_ERROR;
7534   switch( iType ){
7535     case 1: {
7536       xyz = 0x7fffff00 - i;
7537       xyz += 0x100;
7538       Tcl_SetObjResult(interp, Tcl_NewIntObj(xyz));
7539       break;
7540     }
7541     case 2: {
7542       w[1] = 5;
7543       if( w[i]>0 ) w[1]++;
7544       Tcl_SetObjResult(interp, Tcl_NewIntObj(w[1]));
7545       break;
7546     }
7547     case 3: {
7548       a = malloc( sizeof(int)*10 );
7549       for(j=0; j<10; j++) a[j] = j;
7550       free(a);
7551       Tcl_SetObjResult(interp, Tcl_NewIntObj(a[i]));
7552       break;
7553     }
7554     case 4: {
7555       Tcl_Panic("Deliberate panic");
7556       break;
7557     }
7558   }
7559   return TCL_OK;
7560 }
7561 
7562 /*
7563 ** tclcmd:   register_dbstat_vtab DB
7564 **
7565 ** Cause the dbstat virtual table to be available on the connection DB
7566 */
7567 static int SQLITE_TCLAPI test_register_dbstat_vtab(
7568   void *clientData,
7569   Tcl_Interp *interp,
7570   int objc,
7571   Tcl_Obj *CONST objv[]
7572 ){
7573 #ifdef SQLITE_OMIT_VIRTUALTABLE
7574   Tcl_AppendResult(interp, "dbstat not available because of "
7575                            "SQLITE_OMIT_VIRTUALTABLE", (void*)0);
7576   return TCL_ERROR;
7577 #else
7578   struct SqliteDb { sqlite3 *db; };
7579   char *zDb;
7580   Tcl_CmdInfo cmdInfo;
7581 
7582   if( objc!=2 ){
7583     Tcl_WrongNumArgs(interp, 1, objv, "DB");
7584     return TCL_ERROR;
7585   }
7586 
7587   zDb = Tcl_GetString(objv[1]);
7588   if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
7589     sqlite3* db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
7590     sqlite3DbstatRegister(db);
7591   }
7592   return TCL_OK;
7593 #endif /* SQLITE_OMIT_VIRTUALTABLE */
7594 }
7595 
7596 /*
7597 ** tclcmd:   sqlite3_db_config DB SETTING VALUE
7598 **
7599 ** Invoke sqlite3_db_config() for one of the setting values.
7600 */
7601 static int SQLITE_TCLAPI test_sqlite3_db_config(
7602   void *clientData,
7603   Tcl_Interp *interp,
7604   int objc,
7605   Tcl_Obj *CONST objv[]
7606 ){
7607   static const struct {
7608     const char *zName;
7609     int eVal;
7610   } aSetting[] = {
7611     { "FKEY",               SQLITE_DBCONFIG_ENABLE_FKEY },
7612     { "TRIGGER",            SQLITE_DBCONFIG_ENABLE_TRIGGER },
7613     { "FTS3_TOKENIZER",     SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
7614     { "LOAD_EXTENSION",     SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
7615     { "NO_CKPT_ON_CLOSE",   SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
7616     { "QPSG",               SQLITE_DBCONFIG_ENABLE_QPSG },
7617     { "TRIGGER_EQP",        SQLITE_DBCONFIG_TRIGGER_EQP },
7618     { "RESET_DB",           SQLITE_DBCONFIG_RESET_DATABASE },
7619     { "DEFENSIVE",          SQLITE_DBCONFIG_DEFENSIVE },
7620     { "WRITABLE_SCHEMA",    SQLITE_DBCONFIG_WRITABLE_SCHEMA },
7621     { "LEGACY_ALTER_TABLE", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
7622     { "DQS_DML",            SQLITE_DBCONFIG_DQS_DML },
7623     { "DQS_DDL",            SQLITE_DBCONFIG_DQS_DDL },
7624   };
7625   int i;
7626   int v;
7627   const char *zSetting;
7628   sqlite3 *db;
7629 
7630   if( objc!=4 ){
7631     Tcl_WrongNumArgs(interp, 1, objv, "DB SETTING VALUE");
7632     return TCL_ERROR;
7633   }
7634   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
7635   zSetting = Tcl_GetString(objv[2]);
7636   if( sqlite3_strglob("SQLITE_*", zSetting)==0 ) zSetting += 7;
7637   if( sqlite3_strglob("DBCONFIG_*", zSetting)==0 ) zSetting += 9;
7638   if( sqlite3_strglob("ENABLE_*", zSetting)==0 ) zSetting += 7;
7639   for(i=0; i<ArraySize(aSetting); i++){
7640     if( strcmp(zSetting, aSetting[i].zName)==0 ) break;
7641   }
7642   if( i>=ArraySize(aSetting) ){
7643     Tcl_SetObjResult(interp,
7644       Tcl_NewStringObj("unknown sqlite3_db_config setting", -1));
7645     return TCL_ERROR;
7646   }
7647   if( Tcl_GetIntFromObj(interp, objv[3], &v) ) return TCL_ERROR;
7648   sqlite3_db_config(db, aSetting[i].eVal, v, &v);
7649   Tcl_SetObjResult(interp, Tcl_NewIntObj(v));
7650   return TCL_OK;
7651 }
7652 
7653 /*
7654 ** Change the name of the main database schema from "main" to "icecube".
7655 */
7656 static int SQLITE_TCLAPI test_dbconfig_maindbname_icecube(
7657   void * clientData,
7658   Tcl_Interp *interp,
7659   int objc,
7660   Tcl_Obj *CONST objv[]
7661 ){
7662   int rc;
7663   sqlite3 *db;
7664   extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
7665   if( objc!=2 ){
7666     Tcl_WrongNumArgs(interp, 1, objv, "DB");
7667     return TCL_ERROR;
7668   }else{
7669     if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
7670     rc = sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, "icecube");
7671     Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
7672     return TCL_OK;
7673   }
7674 }
7675 
7676 /*
7677 ** Usage: sqlite3_mmap_warm DB DBNAME
7678 */
7679 static int SQLITE_TCLAPI test_mmap_warm(
7680   void * clientData,
7681   Tcl_Interp *interp,
7682   int objc,
7683   Tcl_Obj *CONST objv[]
7684 ){
7685   extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
7686   extern int sqlite3_mmap_warm(sqlite3 *db, const char *);
7687 
7688   if( objc!=2 && objc!=3 ){
7689     Tcl_WrongNumArgs(interp, 1, objv, "DB ?DBNAME?");
7690     return TCL_ERROR;
7691   }else{
7692     int rc;
7693     sqlite3 *db;
7694     const char *zDb = 0;
7695     if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
7696     if( objc==3 ){
7697       zDb = Tcl_GetString(objv[2]);
7698     }
7699     rc = sqlite3_mmap_warm(db, zDb);
7700     Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
7701     return TCL_OK;
7702   }
7703 }
7704 
7705 /*
7706 ** Usage:  decode_hexdb TEXT
7707 **
7708 ** Example:   db deserialize [decode_hexdb $output_of_dbtotxt]
7709 **
7710 ** This routine returns a byte-array for an SQLite database file that
7711 ** is constructed from a text input which is the output of the "dbtotxt"
7712 ** utility.
7713 */
7714 static int SQLITE_TCLAPI test_decode_hexdb(
7715   void * clientData,
7716   Tcl_Interp *interp,
7717   int objc,
7718   Tcl_Obj *CONST objv[]
7719 ){
7720   const char *zIn = 0;
7721   unsigned char *a = 0;
7722   int n = 0;
7723   int lineno = 0;
7724   int i, iNext;
7725   int iOffset = 0;
7726   int j, k;
7727   int rc;
7728   unsigned int x[16];
7729   if( objc!=2 ){
7730     Tcl_WrongNumArgs(interp, 1, objv, "HEXDB");
7731     return TCL_ERROR;
7732   }
7733   zIn = Tcl_GetString(objv[1]);
7734   for(i=0; zIn[i]; i=iNext){
7735     lineno++;
7736     for(iNext=i; zIn[iNext] && zIn[iNext]!='\n'; iNext++){}
7737     if( zIn[iNext]=='\n' ) iNext++;
7738     while( zIn[i]==' ' || zIn[i]=='\t' ){ i++; }
7739     if( a==0 ){
7740       int pgsz;
7741       rc = sscanf(zIn+i, "| size %d pagesize %d", &n, &pgsz);
7742       if( rc!=2 ) continue;
7743       if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ){
7744         Tcl_AppendResult(interp, "bad 'pagesize' field", (void*)0);
7745         return TCL_ERROR;
7746       }
7747       n = (n+pgsz-1)&~(pgsz-1);  /* Round n up to the next multiple of pgsz */
7748       if( n<512 ){
7749         Tcl_AppendResult(interp, "bad 'size' field", (void*)0);
7750         return TCL_ERROR;
7751       }
7752       a = malloc( n );
7753       if( a==0 ){
7754         Tcl_AppendResult(interp, "out of memory", (void*)0);
7755         return TCL_ERROR;
7756       }
7757       memset(a, 0, n);
7758       continue;
7759     }
7760     rc = sscanf(zIn+i, "| page %d offset %d", &j, &k);
7761     if( rc==2 ){
7762       iOffset = k;
7763       continue;
7764     }
7765     rc = sscanf(zIn+i,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
7766                 &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
7767                 &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
7768     if( rc==17 ){
7769       k = iOffset+j;
7770       if( k+16<=n ){
7771         int ii;
7772         for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
7773       }
7774       continue;
7775     }
7776   }
7777   Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(a, n));
7778   free(a);
7779   return TCL_OK;
7780 }
7781 
7782 
7783 /*
7784 ** Register commands with the TCL interpreter.
7785 */
7786 int Sqlitetest1_Init(Tcl_Interp *interp){
7787   extern int sqlite3_search_count;
7788   extern int sqlite3_found_count;
7789   extern int sqlite3_interrupt_count;
7790   extern int sqlite3_open_file_count;
7791   extern int sqlite3_sort_count;
7792   extern int sqlite3_current_time;
7793 #if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
7794   extern int sqlite3_hostid_num;
7795 #endif
7796   extern int sqlite3_max_blobsize;
7797   extern int SQLITE_TCLAPI sqlite3BtreeSharedCacheReport(void*,
7798                                           Tcl_Interp*,int,Tcl_Obj*CONST*);
7799   static int iZero = 0;
7800   static struct {
7801      char *zName;
7802      Tcl_CmdProc *xProc;
7803   } aCmd[] = {
7804      { "db_enter",                      (Tcl_CmdProc*)db_enter               },
7805      { "db_leave",                      (Tcl_CmdProc*)db_leave               },
7806      { "sqlite3_mprintf_int",           (Tcl_CmdProc*)sqlite3_mprintf_int    },
7807      { "sqlite3_mprintf_int64",         (Tcl_CmdProc*)sqlite3_mprintf_int64  },
7808      { "sqlite3_mprintf_long",          (Tcl_CmdProc*)sqlite3_mprintf_long   },
7809      { "sqlite3_mprintf_str",           (Tcl_CmdProc*)sqlite3_mprintf_str    },
7810      { "sqlite3_snprintf_str",          (Tcl_CmdProc*)sqlite3_snprintf_str   },
7811      { "sqlite3_mprintf_stronly",       (Tcl_CmdProc*)sqlite3_mprintf_stronly},
7812      { "sqlite3_mprintf_double",        (Tcl_CmdProc*)sqlite3_mprintf_double },
7813      { "sqlite3_mprintf_scaled",        (Tcl_CmdProc*)sqlite3_mprintf_scaled },
7814      { "sqlite3_mprintf_hexdouble",   (Tcl_CmdProc*)sqlite3_mprintf_hexdouble},
7815      { "sqlite3_mprintf_z_test",        (Tcl_CmdProc*)test_mprintf_z        },
7816      { "sqlite3_mprintf_n_test",        (Tcl_CmdProc*)test_mprintf_n        },
7817      { "sqlite3_snprintf_int",          (Tcl_CmdProc*)test_snprintf_int     },
7818      { "sqlite3_last_insert_rowid",     (Tcl_CmdProc*)test_last_rowid       },
7819      { "sqlite3_exec_printf",           (Tcl_CmdProc*)test_exec_printf      },
7820      { "sqlite3_exec_hex",              (Tcl_CmdProc*)test_exec_hex         },
7821      { "sqlite3_exec",                  (Tcl_CmdProc*)test_exec             },
7822      { "sqlite3_exec_nr",               (Tcl_CmdProc*)test_exec_nr          },
7823 #ifndef SQLITE_OMIT_GET_TABLE
7824      { "sqlite3_get_table_printf",      (Tcl_CmdProc*)test_get_table_printf },
7825 #endif
7826      { "sqlite3_close",                 (Tcl_CmdProc*)sqlite_test_close     },
7827      { "sqlite3_close_v2",              (Tcl_CmdProc*)sqlite_test_close_v2  },
7828      { "sqlite3_create_function",       (Tcl_CmdProc*)test_create_function  },
7829      { "sqlite3_create_aggregate",      (Tcl_CmdProc*)test_create_aggregate },
7830      { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func    },
7831      { "sqlite_abort",                  (Tcl_CmdProc*)sqlite_abort          },
7832      { "sqlite_bind",                   (Tcl_CmdProc*)test_bind             },
7833      { "breakpoint",                    (Tcl_CmdProc*)test_breakpoint       },
7834      { "sqlite3_key",                   (Tcl_CmdProc*)test_key              },
7835      { "sqlite3_rekey",                 (Tcl_CmdProc*)test_rekey            },
7836      { "sqlite_set_magic",              (Tcl_CmdProc*)sqlite_set_magic      },
7837      { "sqlite3_interrupt",             (Tcl_CmdProc*)test_interrupt        },
7838      { "sqlite_delete_function",        (Tcl_CmdProc*)delete_function       },
7839      { "sqlite_delete_collation",       (Tcl_CmdProc*)delete_collation      },
7840      { "sqlite3_get_autocommit",        (Tcl_CmdProc*)get_autocommit        },
7841      { "sqlite3_busy_timeout",          (Tcl_CmdProc*)test_busy_timeout     },
7842      { "printf",                        (Tcl_CmdProc*)test_printf           },
7843      { "sqlite3IoTrace",              (Tcl_CmdProc*)test_io_trace         },
7844      { "clang_sanitize_address",        (Tcl_CmdProc*)clang_sanitize_address },
7845   };
7846   static struct {
7847      char *zName;
7848      Tcl_ObjCmdProc *xProc;
7849      void *clientData;
7850   } aObjCmd[] = {
7851      { "sqlite3_db_config",             test_sqlite3_db_config, 0 },
7852      { "bad_behavior",                  test_bad_behavior,  (void*)&iZero },
7853      { "register_dbstat_vtab",          test_register_dbstat_vtab  },
7854      { "sqlite3_connection_pointer",    get_sqlite_pointer, 0 },
7855      { "intarray_addr",                 test_intarray_addr, 0 },
7856      { "int64array_addr",               test_int64array_addr, 0 },
7857      { "doublearray_addr",              test_doublearray_addr, 0 },
7858      { "textarray_addr",                test_textarray_addr, 0 },
7859      { "sqlite3_bind_int",              test_bind_int,      0 },
7860      { "sqlite3_bind_zeroblob",         test_bind_zeroblob, 0 },
7861      { "sqlite3_bind_zeroblob64",       test_bind_zeroblob64, 0 },
7862      { "sqlite3_bind_int64",            test_bind_int64,    0 },
7863      { "sqlite3_bind_double",           test_bind_double,   0 },
7864      { "sqlite3_bind_null",             test_bind_null     ,0 },
7865      { "sqlite3_bind_text",             test_bind_text     ,0 },
7866      { "sqlite3_bind_text16",           test_bind_text16   ,0 },
7867      { "sqlite3_bind_blob",             test_bind_blob     ,0 },
7868      { "sqlite3_bind_parameter_count",  test_bind_parameter_count, 0},
7869      { "sqlite3_bind_parameter_name",   test_bind_parameter_name,  0},
7870      { "sqlite3_bind_parameter_index",  test_bind_parameter_index, 0},
7871      { "sqlite3_clear_bindings",        test_clear_bindings, 0},
7872      { "sqlite3_sleep",                 test_sleep,          0},
7873      { "sqlite3_errcode",               test_errcode       ,0 },
7874      { "sqlite3_extended_errcode",      test_ex_errcode    ,0 },
7875      { "sqlite3_errmsg",                test_errmsg        ,0 },
7876      { "sqlite3_errmsg16",              test_errmsg16      ,0 },
7877      { "sqlite3_open",                  test_open          ,0 },
7878      { "sqlite3_open16",                test_open16        ,0 },
7879      { "sqlite3_open_v2",               test_open_v2       ,0 },
7880      { "sqlite3_complete16",            test_complete16    ,0 },
7881      { "sqlite3_normalize",             test_normalize     ,0 },
7882 
7883      { "sqlite3_prepare",               test_prepare       ,0 },
7884      { "sqlite3_prepare16",             test_prepare16     ,0 },
7885      { "sqlite3_prepare_v2",            test_prepare_v2    ,0 },
7886      { "sqlite3_prepare_v3",            test_prepare_v3    ,0 },
7887      { "sqlite3_prepare_tkt3134",       test_prepare_tkt3134, 0},
7888      { "sqlite3_prepare16_v2",          test_prepare16_v2  ,0 },
7889      { "sqlite3_finalize",              test_finalize      ,0 },
7890      { "sqlite3_stmt_status",           test_stmt_status   ,0 },
7891      { "sqlite3_reset",                 test_reset         ,0 },
7892      { "sqlite3_expired",               test_expired       ,0 },
7893      { "sqlite3_transfer_bindings",     test_transfer_bind ,0 },
7894      { "sqlite3_changes",               test_changes       ,0 },
7895      { "sqlite3_step",                  test_step          ,0 },
7896      { "sqlite3_sql",                   test_sql           ,0 },
7897      { "sqlite3_expanded_sql",          test_ex_sql        ,0 },
7898 #ifdef SQLITE_ENABLE_NORMALIZE
7899      { "sqlite3_normalized_sql",        test_norm_sql      ,0 },
7900 #endif
7901      { "sqlite3_next_stmt",             test_next_stmt     ,0 },
7902      { "sqlite3_stmt_readonly",         test_stmt_readonly ,0 },
7903      { "sqlite3_stmt_isexplain",        test_stmt_isexplain,0 },
7904      { "sqlite3_stmt_busy",             test_stmt_busy     ,0 },
7905      { "uses_stmt_journal",             uses_stmt_journal ,0 },
7906 
7907      { "sqlite3_release_memory",        test_release_memory,     0},
7908      { "sqlite3_db_release_memory",     test_db_release_memory,  0},
7909      { "sqlite3_db_cacheflush",         test_db_cacheflush,      0},
7910      { "sqlite3_system_errno",          test_system_errno,       0},
7911      { "sqlite3_db_filename",           test_db_filename,        0},
7912      { "sqlite3_db_readonly",           test_db_readonly,        0},
7913      { "sqlite3_soft_heap_limit",       test_soft_heap_limit,    0},
7914      { "sqlite3_thread_cleanup",        test_thread_cleanup,     0},
7915      { "sqlite3_pager_refcounts",       test_pager_refcounts,    0},
7916 
7917      { "sqlite3_load_extension",        test_load_extension,     0},
7918      { "sqlite3_enable_load_extension", test_enable_load,        0},
7919      { "sqlite3_extended_result_codes", test_extended_result_codes, 0},
7920      { "sqlite3_limit",                 test_limit,                 0},
7921      { "dbconfig_maindbname_icecube",   test_dbconfig_maindbname_icecube },
7922 
7923      { "save_prng_state",               save_prng_state,    0 },
7924      { "restore_prng_state",            restore_prng_state, 0 },
7925      { "reset_prng_state",              reset_prng_state,   0 },
7926      { "database_never_corrupt",        database_never_corrupt, 0},
7927      { "database_may_be_corrupt",       database_may_be_corrupt, 0},
7928      { "optimization_control",          optimization_control,0},
7929 #if SQLITE_OS_WIN
7930      { "lock_win32_file",               win32_file_lock,    0 },
7931      { "exists_win32_path",             win32_exists_path,  0 },
7932      { "find_win32_file",               win32_find_file,    0 },
7933      { "delete_win32_file",             win32_delete_file,  0 },
7934      { "make_win32_dir",                win32_mkdir,        0 },
7935      { "remove_win32_dir",              win32_rmdir,        0 },
7936 #endif
7937      { "tcl_objproc",                   runAsObjProc,       0 },
7938 
7939      /* sqlite3_column_*() API */
7940      { "sqlite3_column_count",          test_column_count  ,0 },
7941      { "sqlite3_data_count",            test_data_count    ,0 },
7942      { "sqlite3_column_type",           test_column_type   ,0 },
7943      { "sqlite3_column_blob",           test_column_blob   ,0 },
7944      { "sqlite3_column_double",         test_column_double ,0 },
7945      { "sqlite3_column_int64",          test_column_int64  ,0 },
7946      { "sqlite3_column_text",   test_stmt_utf8,  (void*)sqlite3_column_text },
7947      { "sqlite3_column_name",   test_stmt_utf8,  (void*)sqlite3_column_name },
7948      { "sqlite3_column_int",    test_stmt_int,   (void*)sqlite3_column_int  },
7949      { "sqlite3_column_bytes",  test_stmt_int,   (void*)sqlite3_column_bytes},
7950 #ifndef SQLITE_OMIT_DECLTYPE
7951      { "sqlite3_column_decltype",test_stmt_utf8,(void*)sqlite3_column_decltype},
7952 #endif
7953 #ifdef SQLITE_ENABLE_COLUMN_METADATA
7954 { "sqlite3_column_database_name",test_stmt_utf8,(void*)sqlite3_column_database_name},
7955 { "sqlite3_column_table_name",test_stmt_utf8,(void*)sqlite3_column_table_name},
7956 { "sqlite3_column_origin_name",test_stmt_utf8,(void*)sqlite3_column_origin_name},
7957 #endif
7958 
7959 #ifndef SQLITE_OMIT_UTF16
7960      { "sqlite3_column_bytes16", test_stmt_int, (void*)sqlite3_column_bytes16 },
7961      { "sqlite3_column_text16",  test_stmt_utf16, (void*)sqlite3_column_text16},
7962      { "sqlite3_column_name16",  test_stmt_utf16, (void*)sqlite3_column_name16},
7963      { "add_alignment_test_collations", add_alignment_test_collations, 0      },
7964 #ifndef SQLITE_OMIT_DECLTYPE
7965      { "sqlite3_column_decltype16",test_stmt_utf16,(void*)sqlite3_column_decltype16},
7966 #endif
7967 #ifdef SQLITE_ENABLE_COLUMN_METADATA
7968 {"sqlite3_column_database_name16",
7969   test_stmt_utf16, (void*)sqlite3_column_database_name16},
7970 {"sqlite3_column_table_name16", test_stmt_utf16, (void*)sqlite3_column_table_name16},
7971 {"sqlite3_column_origin_name16", test_stmt_utf16, (void*)sqlite3_column_origin_name16},
7972 #endif
7973 #endif
7974      { "sqlite3_create_collation_v2", test_create_collation_v2, 0 },
7975      { "sqlite3_global_recover",     test_global_recover, 0   },
7976      { "working_64bit_int",          working_64bit_int,   0   },
7977      { "vfs_unlink_test",            vfs_unlink_test,     0   },
7978      { "vfs_initfail_test",          vfs_initfail_test,   0   },
7979      { "vfs_unregister_all",         vfs_unregister_all,  0   },
7980      { "vfs_reregister_all",         vfs_reregister_all,  0   },
7981      { "file_control_test",          file_control_test,   0   },
7982      { "file_control_lasterrno_test", file_control_lasterrno_test,  0   },
7983      { "file_control_lockproxy_test", file_control_lockproxy_test,  0   },
7984      { "file_control_chunksize_test", file_control_chunksize_test,  0   },
7985      { "file_control_sizehint_test",  file_control_sizehint_test,   0   },
7986      { "file_control_data_version",   file_control_data_version,    0   },
7987 #if SQLITE_OS_WIN
7988      { "file_control_win32_av_retry", file_control_win32_av_retry,  0   },
7989      { "file_control_win32_get_handle", file_control_win32_get_handle, 0  },
7990      { "file_control_win32_set_handle", file_control_win32_set_handle, 0  },
7991 #endif
7992      { "file_control_persist_wal",    file_control_persist_wal,     0   },
7993      { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
7994      { "file_control_vfsname",        file_control_vfsname,         0   },
7995      { "file_control_tempfilename",   file_control_tempfilename,    0   },
7996      { "sqlite3_vfs_list",           vfs_list,     0   },
7997      { "sqlite3_create_function_v2", test_create_function_v2, 0 },
7998 
7999      /* Functions from os.h */
8000 #ifndef SQLITE_OMIT_UTF16
8001      { "add_test_collate",        test_collate, 0            },
8002      { "add_test_collate_needed", test_collate_needed, 0     },
8003      { "add_test_function",       test_function, 0           },
8004      { "add_test_utf16bin_collate",    test_utf16bin_collate, 0        },
8005 #endif
8006      { "sqlite3_test_errstr",     test_errstr, 0             },
8007      { "tcl_variable_type",       tcl_variable_type, 0       },
8008 #ifndef SQLITE_OMIT_SHARED_CACHE
8009      { "sqlite3_enable_shared_cache", test_enable_shared, 0  },
8010      { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0},
8011 #endif
8012      { "sqlite3_libversion_number", test_libversion_number, 0  },
8013      { "sqlite3_table_column_metadata", test_table_column_metadata, 0  },
8014 #ifndef SQLITE_OMIT_INCRBLOB
8015      { "sqlite3_blob_reopen", test_blob_reopen, 0  },
8016 #endif
8017      { "pcache_stats",       test_pcache_stats, 0  },
8018 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
8019      { "sqlite3_unlock_notify", test_unlock_notify, 0  },
8020 #endif
8021      { "sqlite3_wal_checkpoint",   test_wal_checkpoint, 0  },
8022      { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0  },
8023      { "sqlite3_wal_autocheckpoint",test_wal_autocheckpoint, 0  },
8024      { "test_sqlite3_log",         test_sqlite3_log, 0  },
8025 #ifndef SQLITE_OMIT_EXPLAIN
8026      { "print_explain_query_plan", test_print_eqp, 0  },
8027 #endif
8028      { "sqlite3_test_control", test_test_control },
8029 #if SQLITE_OS_UNIX
8030      { "getrusage", test_getrusage },
8031 #endif
8032      { "load_static_extension", tclLoadStaticExtensionCmd },
8033      { "sorter_test_fakeheap", sorter_test_fakeheap },
8034      { "sorter_test_sort4_helper", sorter_test_sort4_helper },
8035 #ifdef SQLITE_USER_AUTHENTICATION
8036      { "sqlite3_user_authenticate", test_user_authenticate, 0 },
8037      { "sqlite3_user_add",          test_user_add,          0 },
8038      { "sqlite3_user_change",       test_user_change,       0 },
8039      { "sqlite3_user_delete",       test_user_delete,       0 },
8040 #endif
8041 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
8042      { "sqlite3_stmt_scanstatus",       test_stmt_scanstatus,   0 },
8043      { "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset,   0 },
8044 #endif
8045 #ifdef SQLITE_ENABLE_SQLLOG
8046      { "sqlite3_config_sqllog",         test_config_sqllog,   0 },
8047 #endif
8048      { "vfs_current_time_int64",           vfsCurrentTimeInt64,   0 },
8049 #ifdef SQLITE_ENABLE_SNAPSHOT
8050      { "sqlite3_snapshot_get", test_snapshot_get, 0 },
8051      { "sqlite3_snapshot_open", test_snapshot_open, 0 },
8052      { "sqlite3_snapshot_free", test_snapshot_free, 0 },
8053      { "sqlite3_snapshot_cmp", test_snapshot_cmp, 0 },
8054      { "sqlite3_snapshot_recover", test_snapshot_recover, 0 },
8055      { "sqlite3_snapshot_get_blob", test_snapshot_get_blob, 0 },
8056      { "sqlite3_snapshot_open_blob", test_snapshot_open_blob, 0 },
8057      { "sqlite3_snapshot_cmp_blob", test_snapshot_cmp_blob, 0 },
8058 #endif
8059      { "sqlite3_delete_database", test_delete_database,    0 },
8060      { "atomic_batch_write",      test_atomic_batch_write, 0 },
8061      { "sqlite3_mmap_warm",       test_mmap_warm,          0 },
8062      { "sqlite3_config_sorterref", test_config_sorterref,   0 },
8063      { "decode_hexdb",             test_decode_hexdb,       0 },
8064   };
8065   static int bitmask_size = sizeof(Bitmask)*8;
8066   static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
8067   int i;
8068   extern int sqlite3_sync_count, sqlite3_fullsync_count;
8069   extern int sqlite3_opentemp_count;
8070   extern int sqlite3_like_count;
8071   extern int sqlite3_xferopt_count;
8072   extern int sqlite3_pager_readdb_count;
8073   extern int sqlite3_pager_writedb_count;
8074   extern int sqlite3_pager_writej_count;
8075 #if SQLITE_OS_WIN
8076   extern LONG volatile sqlite3_os_type;
8077 #endif
8078 #ifdef SQLITE_DEBUG
8079   extern int sqlite3WhereTrace;
8080   extern int sqlite3OSTrace;
8081   extern int sqlite3WalTrace;
8082 #endif
8083 #ifdef SQLITE_TEST
8084 #ifdef SQLITE_ENABLE_FTS3
8085   extern int sqlite3_fts3_enable_parentheses;
8086 #endif
8087 #endif
8088 #if defined(SQLITE_ENABLE_SELECTTRACE)
8089   extern int sqlite3SelectTrace;
8090 #endif
8091 
8092   for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
8093     Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
8094   }
8095   for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
8096     Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
8097         aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
8098   }
8099   Tcl_LinkVar(interp, "sqlite_search_count",
8100       (char*)&sqlite3_search_count, TCL_LINK_INT);
8101   Tcl_LinkVar(interp, "sqlite_found_count",
8102       (char*)&sqlite3_found_count, TCL_LINK_INT);
8103   Tcl_LinkVar(interp, "sqlite_sort_count",
8104       (char*)&sqlite3_sort_count, TCL_LINK_INT);
8105   Tcl_LinkVar(interp, "sqlite3_max_blobsize",
8106       (char*)&sqlite3_max_blobsize, TCL_LINK_INT);
8107   Tcl_LinkVar(interp, "sqlite_like_count",
8108       (char*)&sqlite3_like_count, TCL_LINK_INT);
8109   Tcl_LinkVar(interp, "sqlite_interrupt_count",
8110       (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
8111   Tcl_LinkVar(interp, "sqlite_open_file_count",
8112       (char*)&sqlite3_open_file_count, TCL_LINK_INT);
8113   Tcl_LinkVar(interp, "sqlite_current_time",
8114       (char*)&sqlite3_current_time, TCL_LINK_INT);
8115 #if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
8116   Tcl_LinkVar(interp, "sqlite_hostid_num",
8117       (char*)&sqlite3_hostid_num, TCL_LINK_INT);
8118 #endif
8119   Tcl_LinkVar(interp, "sqlite3_xferopt_count",
8120       (char*)&sqlite3_xferopt_count, TCL_LINK_INT);
8121   Tcl_LinkVar(interp, "sqlite3_pager_readdb_count",
8122       (char*)&sqlite3_pager_readdb_count, TCL_LINK_INT);
8123   Tcl_LinkVar(interp, "sqlite3_pager_writedb_count",
8124       (char*)&sqlite3_pager_writedb_count, TCL_LINK_INT);
8125   Tcl_LinkVar(interp, "sqlite3_pager_writej_count",
8126       (char*)&sqlite3_pager_writej_count, TCL_LINK_INT);
8127 #ifndef SQLITE_OMIT_UTF16
8128   Tcl_LinkVar(interp, "unaligned_string_counter",
8129       (char*)&unaligned_string_counter, TCL_LINK_INT);
8130 #endif
8131 #ifndef SQLITE_OMIT_UTF16
8132   Tcl_LinkVar(interp, "sqlite_last_needed_collation",
8133       (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
8134 #endif
8135 #if SQLITE_OS_WIN
8136   Tcl_LinkVar(interp, "sqlite_os_type",
8137       (char*)&sqlite3_os_type, TCL_LINK_LONG);
8138 #endif
8139 #ifdef SQLITE_TEST
8140   {
8141     static const char *query_plan = "*** OBSOLETE VARIABLE ***";
8142     Tcl_LinkVar(interp, "sqlite_query_plan",
8143        (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
8144   }
8145 #endif
8146 #ifdef SQLITE_DEBUG
8147   Tcl_LinkVar(interp, "sqlite_where_trace",
8148       (char*)&sqlite3WhereTrace, TCL_LINK_INT);
8149   Tcl_LinkVar(interp, "sqlite_os_trace",
8150       (char*)&sqlite3OSTrace, TCL_LINK_INT);
8151 #ifndef SQLITE_OMIT_WAL
8152   Tcl_LinkVar(interp, "sqlite_wal_trace",
8153       (char*)&sqlite3WalTrace, TCL_LINK_INT);
8154 #endif
8155 #endif
8156 #ifndef SQLITE_OMIT_DISKIO
8157   Tcl_LinkVar(interp, "sqlite_opentemp_count",
8158       (char*)&sqlite3_opentemp_count, TCL_LINK_INT);
8159 #endif
8160   Tcl_LinkVar(interp, "sqlite_static_bind_value",
8161       (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
8162   Tcl_LinkVar(interp, "sqlite_static_bind_nbyte",
8163       (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT);
8164   Tcl_LinkVar(interp, "sqlite_temp_directory",
8165       (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
8166   Tcl_LinkVar(interp, "sqlite_data_directory",
8167       (char*)&sqlite3_data_directory, TCL_LINK_STRING);
8168   Tcl_LinkVar(interp, "bitmask_size",
8169       (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
8170   Tcl_LinkVar(interp, "longdouble_size",
8171       (char*)&longdouble_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
8172   Tcl_LinkVar(interp, "sqlite_sync_count",
8173       (char*)&sqlite3_sync_count, TCL_LINK_INT);
8174   Tcl_LinkVar(interp, "sqlite_fullsync_count",
8175       (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
8176 #if defined(SQLITE_ENABLE_SELECTTRACE)
8177   Tcl_LinkVar(interp, "sqlite3SelectTrace",
8178       (char*)&sqlite3SelectTrace, TCL_LINK_INT);
8179 #endif
8180 #if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST)
8181   Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses",
8182       (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT);
8183 #endif
8184   return TCL_OK;
8185 }
8186