1d1bf3512Sdrh /*
2b19a2bc6Sdrh ** 2001 September 15
3d1bf3512Sdrh **
4b19a2bc6Sdrh ** The author disclaims copyright to this source code. In place of
5b19a2bc6Sdrh ** a legal notice, here is a blessing:
6d1bf3512Sdrh **
7b19a2bc6Sdrh ** May you do good and not evil.
8b19a2bc6Sdrh ** May you find forgiveness for yourself and forgive others.
9b19a2bc6Sdrh ** May you share freely, never taking more than you give.
10d1bf3512Sdrh **
11d1bf3512Sdrh *************************************************************************
1205a82983Sdrh ** Code for testing all sorts of SQLite interfaces. This code
13d1bf3512Sdrh ** is not included in the SQLite library. It is used for automated
14d1bf3512Sdrh ** testing of the SQLite library.
15d1bf3512Sdrh */
16d1bf3512Sdrh #include "sqliteInt.h"
17f74b9e09Smistachkin #if SQLITE_OS_WIN
18f74b9e09Smistachkin # include "os_win.h"
19f74b9e09Smistachkin #endif
20f74b9e09Smistachkin
21d9495cd0Sdan #include "vdbeInt.h"
2252b1dbb5Smistachkin #if defined(INCLUDE_SQLITE_TCL_H)
2352b1dbb5Smistachkin # include "sqlite_tcl.h"
2452b1dbb5Smistachkin #else
25d1bf3512Sdrh # include "tcl.h"
2652b1dbb5Smistachkin #endif
27d1bf3512Sdrh #include <stdlib.h>
28d1bf3512Sdrh #include <string.h>
29d1bf3512Sdrh
30dddca286Sdrh /*
31dddca286Sdrh ** This is a copy of the first part of the SqliteDb structure in
32dddca286Sdrh ** tclsqlite.c. We need it here so that the get_sqlite_pointer routine
33dddca286Sdrh ** can extract the sqlite3* pointer from an existing Tcl SQLite
34dddca286Sdrh ** connection.
35dddca286Sdrh */
36dddca286Sdrh struct SqliteDb {
37dddca286Sdrh sqlite3 *db;
38dddca286Sdrh };
39dddca286Sdrh
40dddca286Sdrh /*
41a3152895Sdrh ** Convert text generated by the "%p" conversion format back into
42a3152895Sdrh ** a pointer.
43a3152895Sdrh */
testHexToInt(int h)44a3152895Sdrh static int testHexToInt(int h){
45a3152895Sdrh if( h>='0' && h<='9' ){
46a3152895Sdrh return h - '0';
47a3152895Sdrh }else if( h>='a' && h<='f' ){
48a3152895Sdrh return h - 'a' + 10;
49a3152895Sdrh }else{
50a3152895Sdrh assert( h>='A' && h<='F' );
51a3152895Sdrh return h - 'A' + 10;
52a3152895Sdrh }
53a3152895Sdrh }
sqlite3TestTextToPtr(const char * z)54e8f52c50Sdrh void *sqlite3TestTextToPtr(const char *z){
55a3152895Sdrh void *p;
56a3152895Sdrh u64 v;
57a3152895Sdrh u32 v2;
58a3152895Sdrh if( z[0]=='0' && z[1]=='x' ){
59a3152895Sdrh z += 2;
60a3152895Sdrh }
61a3152895Sdrh v = 0;
62a3152895Sdrh while( *z ){
63a3152895Sdrh v = (v<<4) + testHexToInt(*z);
64a3152895Sdrh z++;
65a3152895Sdrh }
66a3152895Sdrh if( sizeof(p)==sizeof(v) ){
67a3152895Sdrh memcpy(&p, &v, sizeof(p));
68a3152895Sdrh }else{
69a3152895Sdrh assert( sizeof(p)==sizeof(v2) );
70a3152895Sdrh v2 = (u32)v;
71a3152895Sdrh memcpy(&p, &v2, sizeof(p));
72a3152895Sdrh }
73a3152895Sdrh return p;
74a3152895Sdrh }
75a3152895Sdrh
76a3152895Sdrh
77a3152895Sdrh /*
78dddca286Sdrh ** A TCL command that returns the address of the sqlite* pointer
79dddca286Sdrh ** for an sqlite connection instance. Bad things happen if the
80dddca286Sdrh ** input is not an sqlite connection.
81dddca286Sdrh */
get_sqlite_pointer(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])827617e4a8Smistachkin static int SQLITE_TCLAPI get_sqlite_pointer(
83dddca286Sdrh void * clientData,
84dddca286Sdrh Tcl_Interp *interp,
85dddca286Sdrh int objc,
86dddca286Sdrh Tcl_Obj *CONST objv[]
87dddca286Sdrh ){
88dddca286Sdrh struct SqliteDb *p;
89dddca286Sdrh Tcl_CmdInfo cmdInfo;
90dddca286Sdrh char zBuf[100];
91dddca286Sdrh if( objc!=2 ){
92dddca286Sdrh Tcl_WrongNumArgs(interp, 1, objv, "SQLITE-CONNECTION");
93dddca286Sdrh return TCL_ERROR;
94dddca286Sdrh }
95dddca286Sdrh if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
96dddca286Sdrh Tcl_AppendResult(interp, "command not found: ",
97dddca286Sdrh Tcl_GetString(objv[1]), (char*)0);
98dddca286Sdrh return TCL_ERROR;
99dddca286Sdrh }
100dddca286Sdrh p = (struct SqliteDb*)cmdInfo.objClientData;
10165545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", p->db);
102dddca286Sdrh Tcl_AppendResult(interp, zBuf, 0);
103dddca286Sdrh return TCL_OK;
104dddca286Sdrh }
105dddca286Sdrh
106b62c335eSdrh /*
107b62c335eSdrh ** Decode a pointer to an sqlite3 object.
108b62c335eSdrh */
getDbPointer(Tcl_Interp * interp,const char * zA,sqlite3 ** ppDb)10924b58dd7Sdrh int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
110b62c335eSdrh struct SqliteDb *p;
111b62c335eSdrh Tcl_CmdInfo cmdInfo;
112b62c335eSdrh if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){
113b62c335eSdrh p = (struct SqliteDb*)cmdInfo.objClientData;
114b62c335eSdrh *ppDb = p->db;
115b62c335eSdrh }else{
116e8f52c50Sdrh *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA);
117b62c335eSdrh }
118b62c335eSdrh return TCL_OK;
119b62c335eSdrh }
120b62c335eSdrh
1216b98d67bSmistachkin #if SQLITE_OS_WIN
1226b98d67bSmistachkin /*
1236b98d67bSmistachkin ** Decode a Win32 HANDLE object.
1246b98d67bSmistachkin */
getWin32Handle(Tcl_Interp * interp,const char * zA,LPHANDLE phFile)1256b98d67bSmistachkin int getWin32Handle(Tcl_Interp *interp, const char *zA, LPHANDLE phFile){
1266b98d67bSmistachkin *phFile = (HANDLE)sqlite3TestTextToPtr(zA);
1276b98d67bSmistachkin return TCL_OK;
1286b98d67bSmistachkin }
1296b98d67bSmistachkin #endif
1306b98d67bSmistachkin
131e84d8d32Smistachkin extern const char *sqlite3ErrName(int);
132e84d8d32Smistachkin #define t1ErrorName sqlite3ErrName
1336622cce3Sdanielk1977
134d1bf3512Sdrh /*
135c60d0446Sdrh ** Convert an sqlite3_stmt* into an sqlite3*. This depends on the
136c60d0446Sdrh ** fact that the sqlite3* is the first field in the Vdbe structure.
137c60d0446Sdrh */
13851942bc3Sdrh #define StmtToDb(X) sqlite3_db_handle(X)
139c60d0446Sdrh
140c60d0446Sdrh /*
141c60d0446Sdrh ** Check a return value to make sure it agrees with the results
142c60d0446Sdrh ** from sqlite3_errcode.
143c60d0446Sdrh */
sqlite3TestErrCode(Tcl_Interp * interp,sqlite3 * db,int rc)144c60d0446Sdrh int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
145b8613ab1Sdrh if( sqlite3_threadsafe()==0 && rc!=SQLITE_MISUSE && rc!=SQLITE_OK
146b8613ab1Sdrh && sqlite3_errcode(db)!=rc ){
147c60d0446Sdrh char zBuf[200];
148c60d0446Sdrh int r2 = sqlite3_errcode(db);
14965545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf,
15065545b59Sdrh "error code %s (%d) does not match sqlite3_errcode %s (%d)",
1514f0c5878Sdrh t1ErrorName(rc), rc, t1ErrorName(r2), r2);
152c60d0446Sdrh Tcl_ResetResult(interp);
153c60d0446Sdrh Tcl_AppendResult(interp, zBuf, 0);
154c60d0446Sdrh return 1;
155c60d0446Sdrh }
156c60d0446Sdrh return 0;
157c60d0446Sdrh }
158c60d0446Sdrh
159c60d0446Sdrh /*
16051e3d8e2Sdanielk1977 ** Decode a pointer to an sqlite3_stmt object.
16151e3d8e2Sdanielk1977 */
getStmtPointer(Tcl_Interp * interp,const char * zArg,sqlite3_stmt ** ppStmt)16251e3d8e2Sdanielk1977 static int getStmtPointer(
16351e3d8e2Sdanielk1977 Tcl_Interp *interp,
16451e3d8e2Sdanielk1977 const char *zArg,
16551e3d8e2Sdanielk1977 sqlite3_stmt **ppStmt
16651e3d8e2Sdanielk1977 ){
167e8f52c50Sdrh *ppStmt = (sqlite3_stmt*)sqlite3TestTextToPtr(zArg);
16851e3d8e2Sdanielk1977 return TCL_OK;
16951e3d8e2Sdanielk1977 }
17051e3d8e2Sdanielk1977
17151e3d8e2Sdanielk1977 /*
1727d8085a8Sdrh ** Generate a text representation of a pointer that can be understood
1737d8085a8Sdrh ** by the getDbPointer and getVmPointer routines above.
1747d8085a8Sdrh **
1757d8085a8Sdrh ** The problem is, on some machines (Solaris) if you do a printf with
1767d8085a8Sdrh ** "%p" you cannot turn around and do a scanf with the same "%p" and
1777d8085a8Sdrh ** get your pointer back. You have to prepend a "0x" before it will
1787d8085a8Sdrh ** work. Or at least that is what is reported to me (drh). But this
1797d8085a8Sdrh ** behavior varies from machine to machine. The solution used her is
1807d8085a8Sdrh ** to test the string right after it is generated to see if it can be
1817d8085a8Sdrh ** understood by scanf, and if not, try prepending an "0x" to see if
1827d8085a8Sdrh ** that helps. If nothing works, a fatal error is generated.
1837d8085a8Sdrh */
sqlite3TestMakePointerStr(Tcl_Interp * interp,char * zPtr,void * p)18464b1bea3Sdrh int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
185fe63d1c9Sdrh sqlite3_snprintf(100, zPtr, "%p", p);
1867d8085a8Sdrh return TCL_OK;
1877d8085a8Sdrh }
1887d8085a8Sdrh
1897d8085a8Sdrh /*
1906f8a503dSdanielk1977 ** The callback routine for sqlite3_exec_printf().
191d1bf3512Sdrh */
exec_printf_cb(void * pArg,int argc,char ** argv,char ** name)192d1bf3512Sdrh static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
193d1bf3512Sdrh Tcl_DString *str = (Tcl_DString*)pArg;
194d1bf3512Sdrh int i;
195d1bf3512Sdrh
196d1bf3512Sdrh if( Tcl_DStringLength(str)==0 ){
197d1bf3512Sdrh for(i=0; i<argc; i++){
198d1bf3512Sdrh Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
199d1bf3512Sdrh }
200d1bf3512Sdrh }
201d1bf3512Sdrh for(i=0; i<argc; i++){
202d1bf3512Sdrh Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
203d1bf3512Sdrh }
204d1bf3512Sdrh return 0;
205d1bf3512Sdrh }
206d1bf3512Sdrh
207d1bf3512Sdrh /*
208538f570cSdrh ** The I/O tracing callback.
209538f570cSdrh */
210afdd23a4Sshane #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
211538f570cSdrh static FILE *iotrace_file = 0;
io_trace_callback(const char * zFormat,...)212538f570cSdrh static void io_trace_callback(const char *zFormat, ...){
213538f570cSdrh va_list ap;
214538f570cSdrh va_start(ap, zFormat);
215538f570cSdrh vfprintf(iotrace_file, zFormat, ap);
216538f570cSdrh va_end(ap);
217538f570cSdrh fflush(iotrace_file);
218538f570cSdrh }
219afdd23a4Sshane #endif
220538f570cSdrh
221538f570cSdrh /*
222538f570cSdrh ** Usage: io_trace FILENAME
223538f570cSdrh **
224538f570cSdrh ** Turn I/O tracing on or off. If FILENAME is not an empty string,
225538f570cSdrh ** I/O tracing begins going into FILENAME. If FILENAME is an empty
226538f570cSdrh ** string, I/O tracing is turned off.
227538f570cSdrh */
test_io_trace(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)2287617e4a8Smistachkin static int SQLITE_TCLAPI test_io_trace(
229538f570cSdrh void *NotUsed,
230538f570cSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
231538f570cSdrh int argc, /* Number of arguments */
232538f570cSdrh char **argv /* Text of each argument */
233538f570cSdrh ){
234286d2f4aSdanielk1977 #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
235538f570cSdrh if( argc!=2 ){
236538f570cSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
237538f570cSdrh " FILENAME\"", 0);
238538f570cSdrh return TCL_ERROR;
239538f570cSdrh }
240538f570cSdrh if( iotrace_file ){
241538f570cSdrh if( iotrace_file!=stdout && iotrace_file!=stderr ){
242538f570cSdrh fclose(iotrace_file);
243538f570cSdrh }
244538f570cSdrh iotrace_file = 0;
2453a00f907Smlcreech sqlite3IoTrace = 0;
246538f570cSdrh }
247538f570cSdrh if( argv[1][0] ){
248538f570cSdrh if( strcmp(argv[1],"stdout")==0 ){
249538f570cSdrh iotrace_file = stdout;
250538f570cSdrh }else if( strcmp(argv[1],"stderr")==0 ){
251538f570cSdrh iotrace_file = stderr;
252538f570cSdrh }else{
253538f570cSdrh iotrace_file = fopen(argv[1], "w");
254538f570cSdrh }
2553a00f907Smlcreech sqlite3IoTrace = io_trace_callback;
256538f570cSdrh }
257286d2f4aSdanielk1977 #endif
258286d2f4aSdanielk1977 return TCL_OK;
259538f570cSdrh }
260538f570cSdrh
261afcf9bd8Sdan /*
262afcf9bd8Sdan ** Usage: clang_sanitize_address
263afcf9bd8Sdan **
264afcf9bd8Sdan ** Returns true if the program was compiled using clang with the
265afcf9bd8Sdan ** -fsanitize=address switch on the command line. False otherwise.
26632e1f279Sdrh **
26732e1f279Sdrh ** Also return true if the OMIT_MISUSE environment variable exists.
268afcf9bd8Sdan */
clang_sanitize_address(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)2697617e4a8Smistachkin static int SQLITE_TCLAPI clang_sanitize_address(
270afcf9bd8Sdan void *NotUsed,
271afcf9bd8Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
272afcf9bd8Sdan int argc, /* Number of arguments */
273afcf9bd8Sdan char **argv /* Text of each argument */
274afcf9bd8Sdan ){
275afcf9bd8Sdan int res = 0;
276afcf9bd8Sdan #if defined(__has_feature)
277afcf9bd8Sdan # if __has_feature(address_sanitizer)
278afcf9bd8Sdan res = 1;
279afcf9bd8Sdan # endif
280afcf9bd8Sdan #endif
281618ee61eSdrh #ifdef __SANITIZE_ADDRESS__
282618ee61eSdrh res = 1;
283618ee61eSdrh #endif
28432e1f279Sdrh if( res==0 && getenv("OMIT_MISUSE")!=0 ) res = 1;
285afcf9bd8Sdan Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
286afcf9bd8Sdan return TCL_OK;
287afcf9bd8Sdan }
288538f570cSdrh
289538f570cSdrh /*
2906f8a503dSdanielk1977 ** Usage: sqlite3_exec_printf DB FORMAT STRING
291d1bf3512Sdrh **
2926f8a503dSdanielk1977 ** Invoke the sqlite3_exec_printf() interface using the open database
293d1bf3512Sdrh ** DB. The SQL is the string FORMAT. The format string should contain
294d1bf3512Sdrh ** one %s or %q. STRING is the value inserted into %s or %q.
295d1bf3512Sdrh */
test_exec_printf(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)2967617e4a8Smistachkin static int SQLITE_TCLAPI test_exec_printf(
297d1bf3512Sdrh void *NotUsed,
298d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
299d1bf3512Sdrh int argc, /* Number of arguments */
300d1bf3512Sdrh char **argv /* Text of each argument */
301d1bf3512Sdrh ){
3029bb575fdSdrh sqlite3 *db;
303d1bf3512Sdrh Tcl_DString str;
304d1bf3512Sdrh int rc;
305d1bf3512Sdrh char *zErr = 0;
3061211de37Sdrh char *zSql;
307d1bf3512Sdrh char zBuf[30];
308d1bf3512Sdrh if( argc!=4 ){
309d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
310d1bf3512Sdrh " DB FORMAT STRING", 0);
311d1bf3512Sdrh return TCL_ERROR;
312d1bf3512Sdrh }
313b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
314d1bf3512Sdrh Tcl_DStringInit(&str);
3151211de37Sdrh zSql = sqlite3_mprintf(argv[2], argv[3]);
3161211de37Sdrh rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
3171211de37Sdrh sqlite3_free(zSql);
31865545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
319d1bf3512Sdrh Tcl_AppendElement(interp, zBuf);
320d1bf3512Sdrh Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
321d1bf3512Sdrh Tcl_DStringFree(&str);
322926aab22Sdanielk1977 if( zErr ) sqlite3_free(zErr);
323c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
324d1bf3512Sdrh return TCL_OK;
325d1bf3512Sdrh }
326d1bf3512Sdrh
327d1bf3512Sdrh /*
3285bd98aefSdrh ** Usage: sqlite3_exec_hex DB HEX
3295bd98aefSdrh **
3305bd98aefSdrh ** Invoke the sqlite3_exec() on a string that is obtained by translating
3315bd98aefSdrh ** HEX into ASCII. Most characters are translated as is. %HH becomes
3325bd98aefSdrh ** a hex character.
3335bd98aefSdrh */
test_exec_hex(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)3347617e4a8Smistachkin static int SQLITE_TCLAPI test_exec_hex(
3355bd98aefSdrh void *NotUsed,
3365bd98aefSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
3375bd98aefSdrh int argc, /* Number of arguments */
3385bd98aefSdrh char **argv /* Text of each argument */
3395bd98aefSdrh ){
3405bd98aefSdrh sqlite3 *db;
3415bd98aefSdrh Tcl_DString str;
3425bd98aefSdrh int rc, i, j;
3435bd98aefSdrh char *zErr = 0;
3445bd98aefSdrh char *zHex;
345dca92904Sdan char zSql[501];
3465bd98aefSdrh char zBuf[30];
3475bd98aefSdrh if( argc!=3 ){
3485bd98aefSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3495bd98aefSdrh " DB HEX", 0);
3505bd98aefSdrh return TCL_ERROR;
3515bd98aefSdrh }
3525bd98aefSdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
3535bd98aefSdrh zHex = argv[2];
354dca92904Sdan for(i=j=0; i<(sizeof(zSql)-1) && zHex[j]; i++, j++){
3555bd98aefSdrh if( zHex[j]=='%' && zHex[j+2] && zHex[j+2] ){
3565bd98aefSdrh zSql[i] = (testHexToInt(zHex[j+1])<<4) + testHexToInt(zHex[j+2]);
3575bd98aefSdrh j += 2;
3585bd98aefSdrh }else{
3595bd98aefSdrh zSql[i] = zHex[j];
3605bd98aefSdrh }
3615bd98aefSdrh }
3625bd98aefSdrh zSql[i] = 0;
3635bd98aefSdrh Tcl_DStringInit(&str);
3645bd98aefSdrh rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
36565545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
3665bd98aefSdrh Tcl_AppendElement(interp, zBuf);
3675bd98aefSdrh Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
3685bd98aefSdrh Tcl_DStringFree(&str);
3695bd98aefSdrh if( zErr ) sqlite3_free(zErr);
3705bd98aefSdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
3715bd98aefSdrh return TCL_OK;
3725bd98aefSdrh }
3735bd98aefSdrh
3745bd98aefSdrh /*
37527641703Sdrh ** Usage: db_enter DB
37627641703Sdrh ** db_leave DB
37727641703Sdrh **
37827641703Sdrh ** Enter or leave the mutex on a database connection.
37927641703Sdrh */
db_enter(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)3807617e4a8Smistachkin static int SQLITE_TCLAPI db_enter(
38127641703Sdrh void *NotUsed,
38227641703Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
38327641703Sdrh int argc, /* Number of arguments */
38427641703Sdrh char **argv /* Text of each argument */
38527641703Sdrh ){
38627641703Sdrh sqlite3 *db;
38727641703Sdrh if( argc!=2 ){
38827641703Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
38927641703Sdrh " DB", 0);
39027641703Sdrh return TCL_ERROR;
39127641703Sdrh }
39227641703Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
39327641703Sdrh sqlite3_mutex_enter(db->mutex);
39427641703Sdrh return TCL_OK;
39527641703Sdrh }
db_leave(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)3967617e4a8Smistachkin static int SQLITE_TCLAPI db_leave(
39727641703Sdrh void *NotUsed,
39827641703Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
39927641703Sdrh int argc, /* Number of arguments */
40027641703Sdrh char **argv /* Text of each argument */
40127641703Sdrh ){
40227641703Sdrh sqlite3 *db;
40327641703Sdrh if( argc!=2 ){
40427641703Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
40527641703Sdrh " DB", 0);
40627641703Sdrh return TCL_ERROR;
40727641703Sdrh }
40827641703Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
40927641703Sdrh sqlite3_mutex_leave(db->mutex);
41027641703Sdrh return TCL_OK;
41127641703Sdrh }
41227641703Sdrh
41327641703Sdrh /*
414b62c335eSdrh ** Usage: sqlite3_exec DB SQL
415b62c335eSdrh **
416b62c335eSdrh ** Invoke the sqlite3_exec interface using the open database DB
417b62c335eSdrh */
test_exec(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)4187617e4a8Smistachkin static int SQLITE_TCLAPI test_exec(
419b62c335eSdrh void *NotUsed,
420b62c335eSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
421b62c335eSdrh int argc, /* Number of arguments */
422b62c335eSdrh char **argv /* Text of each argument */
423b62c335eSdrh ){
424b62c335eSdrh sqlite3 *db;
425b62c335eSdrh Tcl_DString str;
426b62c335eSdrh int rc;
427b62c335eSdrh char *zErr = 0;
4284e5dd851Sdrh char *zSql;
4294e5dd851Sdrh int i, j;
430b62c335eSdrh char zBuf[30];
431b62c335eSdrh if( argc!=3 ){
432b62c335eSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
433b62c335eSdrh " DB SQL", 0);
434b62c335eSdrh return TCL_ERROR;
435b62c335eSdrh }
436b62c335eSdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
437b62c335eSdrh Tcl_DStringInit(&str);
4384e5dd851Sdrh zSql = sqlite3_mprintf("%s", argv[2]);
4394e5dd851Sdrh for(i=j=0; zSql[i];){
4404e5dd851Sdrh if( zSql[i]=='%' ){
4414e5dd851Sdrh zSql[j++] = (testHexToInt(zSql[i+1])<<4) + testHexToInt(zSql[i+2]);
4424e5dd851Sdrh i += 3;
4434e5dd851Sdrh }else{
4444e5dd851Sdrh zSql[j++] = zSql[i++];
4454e5dd851Sdrh }
4464e5dd851Sdrh }
4474e5dd851Sdrh zSql[j] = 0;
4484e5dd851Sdrh rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
4494e5dd851Sdrh sqlite3_free(zSql);
45065545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
451b62c335eSdrh Tcl_AppendElement(interp, zBuf);
452b62c335eSdrh Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
453b62c335eSdrh Tcl_DStringFree(&str);
454b62c335eSdrh if( zErr ) sqlite3_free(zErr);
455b62c335eSdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
456b62c335eSdrh return TCL_OK;
457b62c335eSdrh }
458b62c335eSdrh
459b62c335eSdrh /*
460b62c335eSdrh ** Usage: sqlite3_exec_nr DB SQL
461b62c335eSdrh **
462b62c335eSdrh ** Invoke the sqlite3_exec interface using the open database DB. Discard
463b62c335eSdrh ** all results
464b62c335eSdrh */
test_exec_nr(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)4657617e4a8Smistachkin static int SQLITE_TCLAPI test_exec_nr(
466b62c335eSdrh void *NotUsed,
467b62c335eSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
468b62c335eSdrh int argc, /* Number of arguments */
469b62c335eSdrh char **argv /* Text of each argument */
470b62c335eSdrh ){
471b62c335eSdrh sqlite3 *db;
472b62c335eSdrh int rc;
473b62c335eSdrh char *zErr = 0;
474b62c335eSdrh if( argc!=3 ){
475b62c335eSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
476b62c335eSdrh " DB SQL", 0);
477b62c335eSdrh return TCL_ERROR;
478b62c335eSdrh }
479b62c335eSdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
480b62c335eSdrh rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
481b62c335eSdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
482b62c335eSdrh return TCL_OK;
483b62c335eSdrh }
484b62c335eSdrh
485b62c335eSdrh /*
4866f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ...
487d93d8a81Sdrh **
488bc6160b0Sdrh ** Test the %z format of sqlite_mprintf(). Use multiple mprintf() calls to
489d93d8a81Sdrh ** concatenate arg0 through argn using separator as the separator.
490d93d8a81Sdrh ** Return the result.
491d93d8a81Sdrh */
test_mprintf_z(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)4927617e4a8Smistachkin static int SQLITE_TCLAPI test_mprintf_z(
493d93d8a81Sdrh void *NotUsed,
494d93d8a81Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
495d93d8a81Sdrh int argc, /* Number of arguments */
496d93d8a81Sdrh char **argv /* Text of each argument */
497d93d8a81Sdrh ){
498d93d8a81Sdrh char *zResult = 0;
499d93d8a81Sdrh int i;
500d93d8a81Sdrh
501ca0c8971Sdanielk1977 for(i=2; i<argc && (i==2 || zResult); i++){
502bc6160b0Sdrh zResult = sqlite3_mprintf("%z%s%s", zResult, argv[1], argv[i]);
503d93d8a81Sdrh }
504d93d8a81Sdrh Tcl_AppendResult(interp, zResult, 0);
50517435752Sdrh sqlite3_free(zResult);
506d93d8a81Sdrh return TCL_OK;
507d93d8a81Sdrh }
508d93d8a81Sdrh
509d93d8a81Sdrh /*
51005a82983Sdrh ** Usage: sqlite3_mprintf_n_test STRING
51105a82983Sdrh **
512bc6160b0Sdrh ** Test the %n format of sqlite_mprintf(). Return the length of the
51305a82983Sdrh ** input string.
51405a82983Sdrh */
test_mprintf_n(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)5157617e4a8Smistachkin static int SQLITE_TCLAPI test_mprintf_n(
51605a82983Sdrh void *NotUsed,
51705a82983Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
51805a82983Sdrh int argc, /* Number of arguments */
51905a82983Sdrh char **argv /* Text of each argument */
52005a82983Sdrh ){
52105a82983Sdrh char *zStr;
52205a82983Sdrh int n = 0;
523bc6160b0Sdrh zStr = sqlite3_mprintf("%s%n", argv[1], &n);
52417435752Sdrh sqlite3_free(zStr);
52505a82983Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(n));
52605a82983Sdrh return TCL_OK;
52705a82983Sdrh }
52805a82983Sdrh
52905a82983Sdrh /*
53068853907Sdrh ** Usage: sqlite3_snprintf_int SIZE FORMAT INT
53168853907Sdrh **
53268853907Sdrh ** Test the of sqlite3_snprintf() routine. SIZE is the size of the
53368853907Sdrh ** output buffer in bytes. The maximum size is 100. FORMAT is the
53468853907Sdrh ** format string. INT is a single integer argument. The FORMAT
53568853907Sdrh ** string must require no more than this one integer argument. If
53668853907Sdrh ** You pass in a format string that requires more than one argument,
53768853907Sdrh ** bad things will happen.
53868853907Sdrh */
test_snprintf_int(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)5397617e4a8Smistachkin static int SQLITE_TCLAPI test_snprintf_int(
54068853907Sdrh void *NotUsed,
54168853907Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
54268853907Sdrh int argc, /* Number of arguments */
54368853907Sdrh char **argv /* Text of each argument */
54468853907Sdrh ){
54568853907Sdrh char zStr[100];
54668853907Sdrh int n = atoi(argv[1]);
54768853907Sdrh const char *zFormat = argv[2];
54868853907Sdrh int a1 = atoi(argv[3]);
549daf276d4Sdrh if( n>sizeof(zStr) ) n = sizeof(zStr);
5507694574aSdrh sqlite3_snprintf(sizeof(zStr), zStr, "abcdefghijklmnopqrstuvwxyz");
55168853907Sdrh sqlite3_snprintf(n, zStr, zFormat, a1);
55268853907Sdrh Tcl_AppendResult(interp, zStr, 0);
55368853907Sdrh return TCL_OK;
55468853907Sdrh }
55568853907Sdrh
5568225f5acSshane #ifndef SQLITE_OMIT_GET_TABLE
5578225f5acSshane
55868853907Sdrh /*
559d2b3e23bSdrh ** Usage: sqlite3_get_table_printf DB FORMAT STRING ?--no-counts?
560d1bf3512Sdrh **
5616f8a503dSdanielk1977 ** Invoke the sqlite3_get_table_printf() interface using the open database
562d1bf3512Sdrh ** DB. The SQL is the string FORMAT. The format string should contain
563d1bf3512Sdrh ** one %s or %q. STRING is the value inserted into %s or %q.
564d1bf3512Sdrh */
test_get_table_printf(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)5657617e4a8Smistachkin static int SQLITE_TCLAPI test_get_table_printf(
566d1bf3512Sdrh void *NotUsed,
567d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
568d1bf3512Sdrh int argc, /* Number of arguments */
569d1bf3512Sdrh char **argv /* Text of each argument */
570d1bf3512Sdrh ){
5719bb575fdSdrh sqlite3 *db;
572d1bf3512Sdrh Tcl_DString str;
573d1bf3512Sdrh int rc;
574d1bf3512Sdrh char *zErr = 0;
57527b2f053Smistachkin int nRow = 0, nCol = 0;
576d1bf3512Sdrh char **aResult;
577d1bf3512Sdrh int i;
578d1bf3512Sdrh char zBuf[30];
5791211de37Sdrh char *zSql;
580d2b3e23bSdrh int resCount = -1;
581d2b3e23bSdrh if( argc==5 ){
582d2b3e23bSdrh if( Tcl_GetInt(interp, argv[4], &resCount) ) return TCL_ERROR;
583d2b3e23bSdrh }
584d2b3e23bSdrh if( argc!=4 && argc!=5 ){
585d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
586d2b3e23bSdrh " DB FORMAT STRING ?COUNT?", 0);
587d1bf3512Sdrh return TCL_ERROR;
588d1bf3512Sdrh }
589b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
590d1bf3512Sdrh Tcl_DStringInit(&str);
5911211de37Sdrh zSql = sqlite3_mprintf(argv[2],argv[3]);
592d2b3e23bSdrh if( argc==5 ){
593d2b3e23bSdrh rc = sqlite3_get_table(db, zSql, &aResult, 0, 0, &zErr);
594d2b3e23bSdrh }else{
5951211de37Sdrh rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
596d2b3e23bSdrh resCount = (nRow+1)*nCol;
597d2b3e23bSdrh }
5981211de37Sdrh sqlite3_free(zSql);
59965545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
600d1bf3512Sdrh Tcl_AppendElement(interp, zBuf);
601d1bf3512Sdrh if( rc==SQLITE_OK ){
602d2b3e23bSdrh if( argc==4 ){
60365545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nRow);
604d1bf3512Sdrh Tcl_AppendElement(interp, zBuf);
60565545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nCol);
606d1bf3512Sdrh Tcl_AppendElement(interp, zBuf);
607d2b3e23bSdrh }
608d2b3e23bSdrh for(i=0; i<resCount; i++){
609d1bf3512Sdrh Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
610d1bf3512Sdrh }
611d1bf3512Sdrh }else{
612d1bf3512Sdrh Tcl_AppendElement(interp, zErr);
613d1bf3512Sdrh }
6146f8a503dSdanielk1977 sqlite3_free_table(aResult);
615926aab22Sdanielk1977 if( zErr ) sqlite3_free(zErr);
616c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
617d1bf3512Sdrh return TCL_OK;
618d1bf3512Sdrh }
619d1bf3512Sdrh
6208225f5acSshane #endif /* SQLITE_OMIT_GET_TABLE */
6218225f5acSshane
622af9ff33aSdrh
623af9ff33aSdrh /*
6246f8a503dSdanielk1977 ** Usage: sqlite3_last_insert_rowid DB
625af9ff33aSdrh **
626af9ff33aSdrh ** Returns the integer ROWID of the most recent insert.
627af9ff33aSdrh */
test_last_rowid(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)6287617e4a8Smistachkin static int SQLITE_TCLAPI test_last_rowid(
629af9ff33aSdrh void *NotUsed,
630af9ff33aSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
631af9ff33aSdrh int argc, /* Number of arguments */
632af9ff33aSdrh char **argv /* Text of each argument */
633af9ff33aSdrh ){
6349bb575fdSdrh sqlite3 *db;
635af9ff33aSdrh char zBuf[30];
636af9ff33aSdrh
637af9ff33aSdrh if( argc!=2 ){
638af9ff33aSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
639af9ff33aSdrh return TCL_ERROR;
640af9ff33aSdrh }
641b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
64265545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", sqlite3_last_insert_rowid(db));
643af9ff33aSdrh Tcl_AppendResult(interp, zBuf, 0);
644af9ff33aSdrh return SQLITE_OK;
645af9ff33aSdrh }
646af9ff33aSdrh
647d1bf3512Sdrh /*
64825d6543dSdrh ** Usage: sqlite3_key DB KEY
64925d6543dSdrh **
65025d6543dSdrh ** Set the codec key.
65125d6543dSdrh */
test_key(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)6527617e4a8Smistachkin static int SQLITE_TCLAPI test_key(
65325d6543dSdrh void *NotUsed,
65425d6543dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
65525d6543dSdrh int argc, /* Number of arguments */
65625d6543dSdrh char **argv /* Text of each argument */
65725d6543dSdrh ){
65825d6543dSdrh return TCL_OK;
65925d6543dSdrh }
66025d6543dSdrh
66125d6543dSdrh /*
66225d6543dSdrh ** Usage: sqlite3_rekey DB KEY
66325d6543dSdrh **
66425d6543dSdrh ** Change the codec key.
66525d6543dSdrh */
test_rekey(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)6667617e4a8Smistachkin static int SQLITE_TCLAPI test_rekey(
66725d6543dSdrh void *NotUsed,
66825d6543dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
66925d6543dSdrh int argc, /* Number of arguments */
67025d6543dSdrh char **argv /* Text of each argument */
67125d6543dSdrh ){
67225d6543dSdrh return TCL_OK;
67325d6543dSdrh }
67425d6543dSdrh
67525d6543dSdrh /*
6766f8a503dSdanielk1977 ** Usage: sqlite3_close DB
677d1bf3512Sdrh **
6786f8a503dSdanielk1977 ** Closes the database opened by sqlite3_open.
679d1bf3512Sdrh */
sqlite_test_close(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)6807617e4a8Smistachkin static int SQLITE_TCLAPI sqlite_test_close(
681d1bf3512Sdrh void *NotUsed,
682d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
683d1bf3512Sdrh int argc, /* Number of arguments */
684d1bf3512Sdrh char **argv /* Text of each argument */
685d1bf3512Sdrh ){
6869bb575fdSdrh sqlite3 *db;
68796d81f99Sdanielk1977 int rc;
688d1bf3512Sdrh if( argc!=2 ){
689d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
690d1bf3512Sdrh " FILENAME\"", 0);
691d1bf3512Sdrh return TCL_ERROR;
692d1bf3512Sdrh }
693b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
69496d81f99Sdanielk1977 rc = sqlite3_close(db);
6954f0c5878Sdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
696d1bf3512Sdrh return TCL_OK;
697d1bf3512Sdrh }
698d1bf3512Sdrh
699d1bf3512Sdrh /*
700617dc860Sdan ** Usage: sqlite3_close_v2 DB
701617dc860Sdan **
702617dc860Sdan ** Closes the database opened by sqlite3_open.
703617dc860Sdan */
sqlite_test_close_v2(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)7047617e4a8Smistachkin static int SQLITE_TCLAPI sqlite_test_close_v2(
705617dc860Sdan void *NotUsed,
706617dc860Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
707617dc860Sdan int argc, /* Number of arguments */
708617dc860Sdan char **argv /* Text of each argument */
709617dc860Sdan ){
710617dc860Sdan sqlite3 *db;
711617dc860Sdan int rc;
712617dc860Sdan if( argc!=2 ){
713617dc860Sdan Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
714617dc860Sdan " FILENAME\"", 0);
715617dc860Sdan return TCL_ERROR;
716617dc860Sdan }
717617dc860Sdan if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
718617dc860Sdan rc = sqlite3_close_v2(db);
719617dc860Sdan Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
720617dc860Sdan return TCL_OK;
721617dc860Sdan }
722617dc860Sdan
723617dc860Sdan /*
724c22bd47dSdrh ** Implementation of the x_coalesce() function.
725c22bd47dSdrh ** Return the first argument non-NULL argument.
726c22bd47dSdrh */
t1_ifnullFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)7274f0c5878Sdrh static void t1_ifnullFunc(
7284f0c5878Sdrh sqlite3_context *context,
7294f0c5878Sdrh int argc,
7304f0c5878Sdrh sqlite3_value **argv
7314f0c5878Sdrh ){
732c22bd47dSdrh int i;
733c22bd47dSdrh for(i=0; i<argc; i++){
7349c054830Sdrh if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
7359310ef23Sdrh int n = sqlite3_value_bytes(argv[i]);
73603d847eaSdrh sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]),
7379310ef23Sdrh n, SQLITE_TRANSIENT);
738c22bd47dSdrh break;
739c22bd47dSdrh }
740c22bd47dSdrh }
741c22bd47dSdrh }
742c22bd47dSdrh
743c22bd47dSdrh /*
744f0313813Sdrh ** These are test functions. hex8() interprets its argument as
745f0313813Sdrh ** UTF8 and returns a hex encoding. hex16le() interprets its argument
746f0313813Sdrh ** as UTF16le and returns a hex encoding.
747f0313813Sdrh */
hex8Func(sqlite3_context * p,int argc,sqlite3_value ** argv)748f0313813Sdrh static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){
749f0313813Sdrh const unsigned char *z;
750f0313813Sdrh int i;
751f0313813Sdrh char zBuf[200];
752f0313813Sdrh z = sqlite3_value_text(argv[0]);
753f0313813Sdrh for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){
75465545b59Sdrh sqlite3_snprintf(sizeof(zBuf)-i*2, &zBuf[i*2], "%02x", z[i]);
755f0313813Sdrh }
756f0313813Sdrh zBuf[i*2] = 0;
757f0313813Sdrh sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
758f0313813Sdrh }
759af30469dSdrh #ifndef SQLITE_OMIT_UTF16
hex16Func(sqlite3_context * p,int argc,sqlite3_value ** argv)760f0313813Sdrh static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){
761f0313813Sdrh const unsigned short int *z;
762f0313813Sdrh int i;
763f0313813Sdrh char zBuf[400];
764f0313813Sdrh z = sqlite3_value_text16(argv[0]);
765f0313813Sdrh for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){
76665545b59Sdrh sqlite3_snprintf(sizeof(zBuf)-i*4, &zBuf[i*4],"%04x", z[i]&0xff);
767f0313813Sdrh }
768f0313813Sdrh zBuf[i*4] = 0;
769f0313813Sdrh sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
770f0313813Sdrh }
771af30469dSdrh #endif
772f0313813Sdrh
773f0313813Sdrh /*
774d1d9fc33Sdrh ** A structure into which to accumulate text.
775d1d9fc33Sdrh */
776d1d9fc33Sdrh struct dstr {
777d1d9fc33Sdrh int nAlloc; /* Space allocated */
778d1d9fc33Sdrh int nUsed; /* Space used */
779d1d9fc33Sdrh char *z; /* The space */
780d1d9fc33Sdrh };
781d1d9fc33Sdrh
782d1d9fc33Sdrh /*
783d1d9fc33Sdrh ** Append text to a dstr
784d1d9fc33Sdrh */
dstrAppend(struct dstr * p,const char * z,int divider)785d1d9fc33Sdrh static void dstrAppend(struct dstr *p, const char *z, int divider){
78683cc1392Sdrh int n = (int)strlen(z);
787d1d9fc33Sdrh if( p->nUsed + n + 2 > p->nAlloc ){
788d1d9fc33Sdrh char *zNew;
789d1d9fc33Sdrh p->nAlloc = p->nAlloc*2 + n + 200;
79017435752Sdrh zNew = sqlite3_realloc(p->z, p->nAlloc);
791d1d9fc33Sdrh if( zNew==0 ){
79217435752Sdrh sqlite3_free(p->z);
793d1d9fc33Sdrh memset(p, 0, sizeof(*p));
794d1d9fc33Sdrh return;
795d1d9fc33Sdrh }
796d1d9fc33Sdrh p->z = zNew;
797d1d9fc33Sdrh }
798d1d9fc33Sdrh if( divider && p->nUsed>0 ){
799d1d9fc33Sdrh p->z[p->nUsed++] = divider;
800d1d9fc33Sdrh }
801d1d9fc33Sdrh memcpy(&p->z[p->nUsed], z, n+1);
802d1d9fc33Sdrh p->nUsed += n;
803d1d9fc33Sdrh }
804d1d9fc33Sdrh
805d1d9fc33Sdrh /*
8064adee20fSdanielk1977 ** Invoked for each callback from sqlite3ExecFunc
807d1d9fc33Sdrh */
execFuncCallback(void * pData,int argc,char ** argv,char ** NotUsed)808d1d9fc33Sdrh static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
809d1d9fc33Sdrh struct dstr *p = (struct dstr*)pData;
810d1d9fc33Sdrh int i;
811d1d9fc33Sdrh for(i=0; i<argc; i++){
812d1d9fc33Sdrh if( argv[i]==0 ){
813d1d9fc33Sdrh dstrAppend(p, "NULL", ' ');
814d1d9fc33Sdrh }else{
815d1d9fc33Sdrh dstrAppend(p, argv[i], ' ');
816d1d9fc33Sdrh }
817d1d9fc33Sdrh }
818d1d9fc33Sdrh return 0;
819d1d9fc33Sdrh }
820d1d9fc33Sdrh
821d1d9fc33Sdrh /*
822e35ee196Sdanielk1977 ** Implementation of the x_sqlite_exec() function. This function takes
823c22bd47dSdrh ** a single argument and attempts to execute that argument as SQL code.
8246cbe1f1bSdrh ** This is illegal and should set the SQLITE_MISUSE flag on the database.
825c22bd47dSdrh **
8266f8a503dSdanielk1977 ** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec()
827d1d9fc33Sdrh ** from within a function call.
828d1d9fc33Sdrh **
829c22bd47dSdrh ** This routine simulates the effect of having two threads attempt to
830c22bd47dSdrh ** use the same database at the same time.
831c22bd47dSdrh */
sqlite3ExecFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)83251ad0ecdSdanielk1977 static void sqlite3ExecFunc(
8330ae8b831Sdanielk1977 sqlite3_context *context,
83451ad0ecdSdanielk1977 int argc,
83551ad0ecdSdanielk1977 sqlite3_value **argv
83651ad0ecdSdanielk1977 ){
837d1d9fc33Sdrh struct dstr x;
838d1d9fc33Sdrh memset(&x, 0, sizeof(x));
8393752785fSdrh (void)sqlite3_exec((sqlite3*)sqlite3_user_data(context),
84003d847eaSdrh (char*)sqlite3_value_text(argv[0]),
841d1d9fc33Sdrh execFuncCallback, &x, 0);
842d8123366Sdanielk1977 sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
84317435752Sdrh sqlite3_free(x.z);
844c22bd47dSdrh }
845c22bd47dSdrh
846c22bd47dSdrh /*
847d7263927Sdanielk1977 ** Implementation of tkt2213func(), a scalar function that takes exactly
848d7263927Sdanielk1977 ** one argument. It has two interesting features:
849d7263927Sdanielk1977 **
850d7263927Sdanielk1977 ** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*.
851d7263927Sdanielk1977 ** If the three pointers returned are not the same an SQL error is raised.
852d7263927Sdanielk1977 **
85385b623f2Sdrh ** * Otherwise it returns a copy of the text representation of its
854d7263927Sdanielk1977 ** argument in such a way as the VDBE representation is a Mem* cell
855d7263927Sdanielk1977 ** with the MEM_Term flag clear.
856d7263927Sdanielk1977 **
857d7263927Sdanielk1977 ** Ticket #2213 can therefore be tested by evaluating the following
858d7263927Sdanielk1977 ** SQL expression:
859d7263927Sdanielk1977 **
860d7263927Sdanielk1977 ** tkt2213func(tkt2213func('a string'));
861d7263927Sdanielk1977 */
tkt2213Function(sqlite3_context * context,int argc,sqlite3_value ** argv)862d7263927Sdanielk1977 static void tkt2213Function(
863d7263927Sdanielk1977 sqlite3_context *context,
864d7263927Sdanielk1977 int argc,
865d7263927Sdanielk1977 sqlite3_value **argv
866d7263927Sdanielk1977 ){
867d7263927Sdanielk1977 int nText;
868d7263927Sdanielk1977 unsigned char const *zText1;
869d7263927Sdanielk1977 unsigned char const *zText2;
870d7263927Sdanielk1977 unsigned char const *zText3;
871d7263927Sdanielk1977
872d7263927Sdanielk1977 nText = sqlite3_value_bytes(argv[0]);
873d7263927Sdanielk1977 zText1 = sqlite3_value_text(argv[0]);
874d7263927Sdanielk1977 zText2 = sqlite3_value_text(argv[0]);
875d7263927Sdanielk1977 zText3 = sqlite3_value_text(argv[0]);
876d7263927Sdanielk1977
877d7263927Sdanielk1977 if( zText1!=zText2 || zText2!=zText3 ){
878d7263927Sdanielk1977 sqlite3_result_error(context, "tkt2213 is not fixed", -1);
879d7263927Sdanielk1977 }else{
880d7263927Sdanielk1977 char *zCopy = (char *)sqlite3_malloc(nText);
881d7263927Sdanielk1977 memcpy(zCopy, zText1, nText);
882d7263927Sdanielk1977 sqlite3_result_text(context, zCopy, nText, sqlite3_free);
883d7263927Sdanielk1977 }
884d7263927Sdanielk1977 }
885d7263927Sdanielk1977
886d7263927Sdanielk1977 /*
8879310ef23Sdrh ** The following SQL function takes 4 arguments. The 2nd and
8889310ef23Sdrh ** 4th argument must be one of these strings: 'text', 'text16',
8899310ef23Sdrh ** or 'blob' corresponding to API functions
8909310ef23Sdrh **
8919310ef23Sdrh ** sqlite3_value_text()
8929310ef23Sdrh ** sqlite3_value_text16()
8939310ef23Sdrh ** sqlite3_value_blob()
8949310ef23Sdrh **
8959310ef23Sdrh ** The third argument is a string, either 'bytes' or 'bytes16' or 'noop',
8969310ef23Sdrh ** corresponding to APIs:
8979310ef23Sdrh **
8989310ef23Sdrh ** sqlite3_value_bytes()
8999310ef23Sdrh ** sqlite3_value_bytes16()
9009310ef23Sdrh ** noop
9019310ef23Sdrh **
9029310ef23Sdrh ** The APIs designated by the 2nd through 4th arguments are applied
9039310ef23Sdrh ** to the first argument in order. If the pointers returned by the
9049310ef23Sdrh ** second and fourth are different, this routine returns 1. Otherwise,
9059310ef23Sdrh ** this routine returns 0.
9069310ef23Sdrh **
9079310ef23Sdrh ** This function is used to test to see when returned pointers from
9089310ef23Sdrh ** the _text(), _text16() and _blob() APIs become invalidated.
9099310ef23Sdrh */
ptrChngFunction(sqlite3_context * context,int argc,sqlite3_value ** argv)9109310ef23Sdrh static void ptrChngFunction(
9119310ef23Sdrh sqlite3_context *context,
9129310ef23Sdrh int argc,
9139310ef23Sdrh sqlite3_value **argv
9149310ef23Sdrh ){
9159310ef23Sdrh const void *p1, *p2;
9169310ef23Sdrh const char *zCmd;
9179310ef23Sdrh if( argc!=4 ) return;
9189310ef23Sdrh zCmd = (const char*)sqlite3_value_text(argv[1]);
9199310ef23Sdrh if( zCmd==0 ) return;
9209310ef23Sdrh if( strcmp(zCmd,"text")==0 ){
9219310ef23Sdrh p1 = (const void*)sqlite3_value_text(argv[0]);
9229310ef23Sdrh #ifndef SQLITE_OMIT_UTF16
9239310ef23Sdrh }else if( strcmp(zCmd, "text16")==0 ){
9249310ef23Sdrh p1 = (const void*)sqlite3_value_text16(argv[0]);
9259310ef23Sdrh #endif
9269310ef23Sdrh }else if( strcmp(zCmd, "blob")==0 ){
9279310ef23Sdrh p1 = (const void*)sqlite3_value_blob(argv[0]);
9289310ef23Sdrh }else{
9299310ef23Sdrh return;
9309310ef23Sdrh }
9319310ef23Sdrh zCmd = (const char*)sqlite3_value_text(argv[2]);
9329310ef23Sdrh if( zCmd==0 ) return;
9339310ef23Sdrh if( strcmp(zCmd,"bytes")==0 ){
9349310ef23Sdrh sqlite3_value_bytes(argv[0]);
9359310ef23Sdrh #ifndef SQLITE_OMIT_UTF16
9369310ef23Sdrh }else if( strcmp(zCmd, "bytes16")==0 ){
9379310ef23Sdrh sqlite3_value_bytes16(argv[0]);
9389310ef23Sdrh #endif
9399310ef23Sdrh }else if( strcmp(zCmd, "noop")==0 ){
9409310ef23Sdrh /* do nothing */
9419310ef23Sdrh }else{
9429310ef23Sdrh return;
9439310ef23Sdrh }
9449310ef23Sdrh zCmd = (const char*)sqlite3_value_text(argv[3]);
9459310ef23Sdrh if( zCmd==0 ) return;
9469310ef23Sdrh if( strcmp(zCmd,"text")==0 ){
9479310ef23Sdrh p2 = (const void*)sqlite3_value_text(argv[0]);
9489310ef23Sdrh #ifndef SQLITE_OMIT_UTF16
9499310ef23Sdrh }else if( strcmp(zCmd, "text16")==0 ){
9509310ef23Sdrh p2 = (const void*)sqlite3_value_text16(argv[0]);
9519310ef23Sdrh #endif
9529310ef23Sdrh }else if( strcmp(zCmd, "blob")==0 ){
9539310ef23Sdrh p2 = (const void*)sqlite3_value_blob(argv[0]);
9549310ef23Sdrh }else{
9559310ef23Sdrh return;
9569310ef23Sdrh }
9579310ef23Sdrh sqlite3_result_int(context, p1!=p2);
9589310ef23Sdrh }
9599310ef23Sdrh
9604a8ee3dfSdrh /*
9614a8ee3dfSdrh ** This SQL function returns a different answer each time it is called, even if
9624a8ee3dfSdrh ** the arguments are the same.
9634a8ee3dfSdrh */
nondeterministicFunction(sqlite3_context * context,int argc,sqlite3_value ** argv)9644a8ee3dfSdrh static void nondeterministicFunction(
9654a8ee3dfSdrh sqlite3_context *context,
9664a8ee3dfSdrh int argc,
9674a8ee3dfSdrh sqlite3_value **argv
9684a8ee3dfSdrh ){
9694a8ee3dfSdrh static int cnt = 0;
9704a8ee3dfSdrh sqlite3_result_int(context, cnt++);
9714a8ee3dfSdrh }
9729310ef23Sdrh
9739310ef23Sdrh /*
9740c8f4038Sdrh ** This SQL function returns the integer value of its argument as a MEM_IntReal
9750c8f4038Sdrh ** value.
9760c8f4038Sdrh */
intrealFunction(sqlite3_context * context,int argc,sqlite3_value ** argv)9770c8f4038Sdrh static void intrealFunction(
9780c8f4038Sdrh sqlite3_context *context,
9790c8f4038Sdrh int argc,
9800c8f4038Sdrh sqlite3_value **argv
9810c8f4038Sdrh ){
9820c8f4038Sdrh sqlite3_int64 v = sqlite3_value_int64(argv[0]);
9830c8f4038Sdrh sqlite3_result_int64(context, v);
9840c8f4038Sdrh sqlite3_test_control(SQLITE_TESTCTRL_RESULT_INTREAL, context);
9850c8f4038Sdrh }
9860c8f4038Sdrh
9870c8f4038Sdrh /*
9884a8ee3dfSdrh ** Usage: sqlite3_create_function DB
989c22bd47dSdrh **
9906f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order
991c22bd47dSdrh ** to create a function named "x_coalesce". This function does the same thing
992c22bd47dSdrh ** as the "coalesce" function. This function also registers an SQL function
993e35ee196Sdanielk1977 ** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec()
994c22bd47dSdrh ** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
995c22bd47dSdrh ** The effect is similar to trying to use the same database connection from
996c22bd47dSdrh ** two threads at the same time.
997c22bd47dSdrh **
998c22bd47dSdrh ** The original motivation for this routine was to be able to call the
9996f8a503dSdanielk1977 ** sqlite3_create_function function while a query is in progress in order
1000c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic.
1001c22bd47dSdrh */
test_create_function(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)10027617e4a8Smistachkin static int SQLITE_TCLAPI test_create_function(
1003c22bd47dSdrh void *NotUsed,
1004c22bd47dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1005c22bd47dSdrh int argc, /* Number of arguments */
1006c22bd47dSdrh char **argv /* Text of each argument */
1007c22bd47dSdrh ){
1008c60d0446Sdrh int rc;
10099bb575fdSdrh sqlite3 *db;
1010312d6b36Sdanielk1977
1011c22bd47dSdrh if( argc!=2 ){
1012c22bd47dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
10134397de57Sdanielk1977 " DB\"", 0);
1014c22bd47dSdrh return TCL_ERROR;
1015c22bd47dSdrh }
1016b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
10174a8ee3dfSdrh rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_UTF8, 0,
10184f0c5878Sdrh t1_ifnullFunc, 0, 0);
1019235a818eSdrh if( rc==SQLITE_OK ){
10204a8ee3dfSdrh rc = sqlite3_create_function(db, "hex8", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
10214a8ee3dfSdrh 0, hex8Func, 0, 0);
1022235a818eSdrh }
1023af30469dSdrh #ifndef SQLITE_OMIT_UTF16
1024235a818eSdrh if( rc==SQLITE_OK ){
10254a8ee3dfSdrh rc = sqlite3_create_function(db, "hex16", 1, SQLITE_UTF16 | SQLITE_DETERMINISTIC,
10264a8ee3dfSdrh 0, hex16Func, 0, 0);
1027235a818eSdrh }
1028af30469dSdrh #endif
1029d7263927Sdanielk1977 if( rc==SQLITE_OK ){
1030d7263927Sdanielk1977 rc = sqlite3_create_function(db, "tkt2213func", 1, SQLITE_ANY, 0,
1031d7263927Sdanielk1977 tkt2213Function, 0, 0);
1032d7263927Sdanielk1977 }
10339310ef23Sdrh if( rc==SQLITE_OK ){
10349310ef23Sdrh rc = sqlite3_create_function(db, "pointer_change", 4, SQLITE_ANY, 0,
10359310ef23Sdrh ptrChngFunction, 0, 0);
10369310ef23Sdrh }
1037312d6b36Sdanielk1977
10384a8ee3dfSdrh /* Functions counter1() and counter2() have the same implementation - they
10394a8ee3dfSdrh ** both return an ascending integer with each call. But counter1() is marked
10404a8ee3dfSdrh ** as non-deterministic and counter2() is marked as deterministic.
10414a8ee3dfSdrh */
10424a8ee3dfSdrh if( rc==SQLITE_OK ){
10434a8ee3dfSdrh rc = sqlite3_create_function(db, "counter1", -1, SQLITE_UTF8,
10444a8ee3dfSdrh 0, nondeterministicFunction, 0, 0);
10454a8ee3dfSdrh }
10464a8ee3dfSdrh if( rc==SQLITE_OK ){
10474a8ee3dfSdrh rc = sqlite3_create_function(db, "counter2", -1, SQLITE_UTF8|SQLITE_DETERMINISTIC,
10484a8ee3dfSdrh 0, nondeterministicFunction, 0, 0);
10494a8ee3dfSdrh }
10504a8ee3dfSdrh
10510c8f4038Sdrh /* The intreal() function converts its argument to an integer and returns
10520c8f4038Sdrh ** it as a MEM_IntReal.
10530c8f4038Sdrh */
10540c8f4038Sdrh if( rc==SQLITE_OK ){
10550c8f4038Sdrh rc = sqlite3_create_function(db, "intreal", 1, SQLITE_UTF8,
10560c8f4038Sdrh 0, intrealFunction, 0, 0);
10570c8f4038Sdrh }
10580c8f4038Sdrh
10595436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
1060312d6b36Sdanielk1977 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
1061312d6b36Sdanielk1977 ** because it is not tested anywhere else. */
1062c60d0446Sdrh if( rc==SQLITE_OK ){
1063eee4c8caSdrh const void *zUtf16;
1064576ec6b3Sdanielk1977 sqlite3_value *pVal;
1065f3a65f7eSdrh sqlite3_mutex_enter(db->mutex);
1066f3a65f7eSdrh pVal = sqlite3ValueNew(db);
1067b21c8cd4Sdrh sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
1068a7a8e14bSdanielk1977 zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
1069f3a65f7eSdrh if( db->mallocFailed ){
1070f3a65f7eSdrh rc = SQLITE_NOMEM;
1071f3a65f7eSdrh }else{
1072a7a8e14bSdanielk1977 rc = sqlite3_create_function16(db, zUtf16,
1073312d6b36Sdanielk1977 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
1074f3a65f7eSdrh }
1075312d6b36Sdanielk1977 sqlite3ValueFree(pVal);
1076f3a65f7eSdrh sqlite3_mutex_leave(db->mutex);
1077c60d0446Sdrh }
10785436dc2dSdrh #endif
10795436dc2dSdrh
1080c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
10814f0c5878Sdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
1082c22bd47dSdrh return TCL_OK;
1083c22bd47dSdrh }
1084c22bd47dSdrh
1085c22bd47dSdrh /*
10868c754a36Sdrh ** Usage: sqlite3_drop_modules DB ?NAME ...?
10875df84280Sdrh **
10888c754a36Sdrh ** Invoke the sqlite3_drop_modules(D,L) interface on database
10895df84280Sdrh ** connection DB, in order to drop all modules except those named in
10905df84280Sdrh ** the argument.
10915df84280Sdrh */
test_drop_modules(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)10928c754a36Sdrh static int SQLITE_TCLAPI test_drop_modules(
10935df84280Sdrh void *NotUsed,
10945df84280Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
10955df84280Sdrh int argc, /* Number of arguments */
10965df84280Sdrh char **argv /* Text of each argument */
10975df84280Sdrh ){
10985df84280Sdrh sqlite3 *db;
10995df84280Sdrh
11002999068dSdan if( argc<2 ){
11015df84280Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
11025df84280Sdrh " DB\"", 0);
11035df84280Sdrh return TCL_ERROR;
11045df84280Sdrh }
11055df84280Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
1106e2b7a769Sdrh #ifndef SQLITE_OMIT_VIRTUALTABLE
11078c754a36Sdrh sqlite3_drop_modules(db, argc>2 ? (const char**)(argv+2) : 0);
1108e2b7a769Sdrh #endif
11095df84280Sdrh return TCL_OK;
11105df84280Sdrh }
11115df84280Sdrh
11125df84280Sdrh /*
1113c22bd47dSdrh ** Routines to implement the x_count() aggregate function.
111490669c1dSdrh **
111590669c1dSdrh ** x_count() counts the number of non-null arguments. But there are
111690669c1dSdrh ** some twists for testing purposes.
111790669c1dSdrh **
111890669c1dSdrh ** If the argument to x_count() is 40 then a UTF-8 error is reported
111990669c1dSdrh ** on the step function. If x_count(41) is seen, then a UTF-16 error
112090669c1dSdrh ** is reported on the step function. If the total count is 42, then
112190669c1dSdrh ** a UTF-8 error is reported on the finalize function.
1122c22bd47dSdrh */
11234f0c5878Sdrh typedef struct t1CountCtx t1CountCtx;
11244f0c5878Sdrh struct t1CountCtx {
1125c22bd47dSdrh int n;
1126c22bd47dSdrh };
t1CountStep(sqlite3_context * context,int argc,sqlite3_value ** argv)11274f0c5878Sdrh static void t1CountStep(
11284f0c5878Sdrh sqlite3_context *context,
11294f0c5878Sdrh int argc,
11304f0c5878Sdrh sqlite3_value **argv
11314f0c5878Sdrh ){
11324f0c5878Sdrh t1CountCtx *p;
11334f26d6c4Sdrh p = sqlite3_aggregate_context(context, sizeof(*p));
11349c054830Sdrh if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
1135c22bd47dSdrh p->n++;
1136c22bd47dSdrh }
113790669c1dSdrh if( argc>0 ){
113890669c1dSdrh int v = sqlite3_value_int(argv[0]);
113990669c1dSdrh if( v==40 ){
114090669c1dSdrh sqlite3_result_error(context, "value of 40 handed to x_count", -1);
1141a1686c9aSdanielk1977 #ifndef SQLITE_OMIT_UTF16
114290669c1dSdrh }else if( v==41 ){
114390669c1dSdrh const char zUtf16ErrMsg[] = { 0, 0x61, 0, 0x62, 0, 0x63, 0, 0, 0};
114490669c1dSdrh sqlite3_result_error16(context, &zUtf16ErrMsg[1-SQLITE_BIGENDIAN], -1);
1145a1686c9aSdanielk1977 #endif
114690669c1dSdrh }
114790669c1dSdrh }
1148c22bd47dSdrh }
t1CountFinalize(sqlite3_context * context)11494f0c5878Sdrh static void t1CountFinalize(sqlite3_context *context){
11504f0c5878Sdrh t1CountCtx *p;
11514f26d6c4Sdrh p = sqlite3_aggregate_context(context, sizeof(*p));
115290669c1dSdrh if( p ){
115390669c1dSdrh if( p->n==42 ){
115490669c1dSdrh sqlite3_result_error(context, "x_count totals to 42", -1);
115590669c1dSdrh }else{
1156c572ef7fSdanielk1977 sqlite3_result_int(context, p ? p->n : 0);
1157c22bd47dSdrh }
115890669c1dSdrh }
115990669c1dSdrh }
1160c22bd47dSdrh
1161c5512882Sdanielk1977 #ifndef SQLITE_OMIT_DEPRECATED
legacyCountStep(sqlite3_context * context,int argc,sqlite3_value ** argv)1162fa18beceSdanielk1977 static void legacyCountStep(
1163fa18beceSdanielk1977 sqlite3_context *context,
1164fa18beceSdanielk1977 int argc,
1165fa18beceSdanielk1977 sqlite3_value **argv
1166fa18beceSdanielk1977 ){
1167fa18beceSdanielk1977 /* no-op */
1168fa18beceSdanielk1977 }
1169eec556d3Sshane
legacyCountFinalize(sqlite3_context * context)1170fa18beceSdanielk1977 static void legacyCountFinalize(sqlite3_context *context){
1171fa18beceSdanielk1977 sqlite3_result_int(context, sqlite3_aggregate_count(context));
1172fa18beceSdanielk1977 }
1173eec556d3Sshane #endif
1174fa18beceSdanielk1977
1175c22bd47dSdrh /*
1176fa18beceSdanielk1977 ** Usage: sqlite3_create_aggregate DB
1177c22bd47dSdrh **
11786f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order
1179fa18beceSdanielk1977 ** to create a function named "x_count". This function is similar
1180fa18beceSdanielk1977 ** to the built-in count() function, with a few special quirks
1181fa18beceSdanielk1977 ** for testing the sqlite3_result_error() APIs.
1182c22bd47dSdrh **
1183c22bd47dSdrh ** The original motivation for this routine was to be able to call the
11846f8a503dSdanielk1977 ** sqlite3_create_aggregate function while a query is in progress in order
118590669c1dSdrh ** to test the SQLITE_MISUSE detection logic. See misuse.test.
118690669c1dSdrh **
118790669c1dSdrh ** This routine was later extended to test the use of sqlite3_result_error()
118890669c1dSdrh ** within aggregate functions.
1189fa18beceSdanielk1977 **
1190fa18beceSdanielk1977 ** Later: It is now also extended to register the aggregate function
1191fa18beceSdanielk1977 ** "legacy_count()" with the supplied database handle. This is used
1192fa18beceSdanielk1977 ** to test the deprecated sqlite3_aggregate_count() API.
1193c22bd47dSdrh */
test_create_aggregate(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)11947617e4a8Smistachkin static int SQLITE_TCLAPI test_create_aggregate(
1195c22bd47dSdrh void *NotUsed,
1196c22bd47dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1197c22bd47dSdrh int argc, /* Number of arguments */
1198c22bd47dSdrh char **argv /* Text of each argument */
1199c22bd47dSdrh ){
12009bb575fdSdrh sqlite3 *db;
1201c60d0446Sdrh int rc;
1202c22bd47dSdrh if( argc!=2 ){
1203c22bd47dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1204c22bd47dSdrh " FILENAME\"", 0);
1205c22bd47dSdrh return TCL_ERROR;
1206c22bd47dSdrh }
1207b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
1208c60d0446Sdrh rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
12094f0c5878Sdrh t1CountStep,t1CountFinalize);
1210c60d0446Sdrh if( rc==SQLITE_OK ){
1211fa18beceSdanielk1977 rc = sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
12124f0c5878Sdrh t1CountStep,t1CountFinalize);
1213c60d0446Sdrh }
1214eec556d3Sshane #ifndef SQLITE_OMIT_DEPRECATED
1215fa18beceSdanielk1977 if( rc==SQLITE_OK ){
1216fa18beceSdanielk1977 rc = sqlite3_create_function(db, "legacy_count", 0, SQLITE_ANY, 0, 0,
1217fa18beceSdanielk1977 legacyCountStep, legacyCountFinalize
1218fa18beceSdanielk1977 );
1219fa18beceSdanielk1977 }
1220eec556d3Sshane #endif
1221c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
1222fa18beceSdanielk1977 Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
1223c22bd47dSdrh return TCL_OK;
1224c22bd47dSdrh }
1225c22bd47dSdrh
1226c22bd47dSdrh
12273c23a885Sdrh /*
12283c23a885Sdrh ** Usage: printf TEXT
12293c23a885Sdrh **
12303c23a885Sdrh ** Send output to printf. Use this rather than puts to merge the output
12313c23a885Sdrh ** in the correct sequence with debugging printfs inserted into C code.
12323c23a885Sdrh ** Puts uses a separate buffer and debugging statements will be out of
12333c23a885Sdrh ** sequence if it is used.
12343c23a885Sdrh */
test_printf(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)12357617e4a8Smistachkin static int SQLITE_TCLAPI test_printf(
12363c23a885Sdrh void *NotUsed,
12373c23a885Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
12383c23a885Sdrh int argc, /* Number of arguments */
12393c23a885Sdrh char **argv /* Text of each argument */
12403c23a885Sdrh ){
12413c23a885Sdrh if( argc!=2 ){
12423c23a885Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
12433c23a885Sdrh " TEXT\"", 0);
12443c23a885Sdrh return TCL_ERROR;
12453c23a885Sdrh }
12463c23a885Sdrh printf("%s\n", argv[1]);
12473c23a885Sdrh return TCL_OK;
12483c23a885Sdrh }
12493c23a885Sdrh
12503c23a885Sdrh
1251c22bd47dSdrh
1252c22bd47dSdrh /*
12536f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
1254d1bf3512Sdrh **
1255d1bf3512Sdrh ** Call mprintf with three integer arguments
1256d1bf3512Sdrh */
sqlite3_mprintf_int(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)12577617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_mprintf_int(
1258d1bf3512Sdrh void *NotUsed,
1259d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1260d1bf3512Sdrh int argc, /* Number of arguments */
1261d1bf3512Sdrh char **argv /* Text of each argument */
1262d1bf3512Sdrh ){
1263d1bf3512Sdrh int a[3], i;
1264d1bf3512Sdrh char *z;
1265d1bf3512Sdrh if( argc!=5 ){
1266d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1267d1bf3512Sdrh " FORMAT INT INT INT\"", 0);
1268d1bf3512Sdrh return TCL_ERROR;
1269d1bf3512Sdrh }
1270d1bf3512Sdrh for(i=2; i<5; i++){
1271d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
1272d1bf3512Sdrh }
12736f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
1274d1bf3512Sdrh Tcl_AppendResult(interp, z, 0);
12753f4fedb2Sdrh sqlite3_free(z);
1276d1bf3512Sdrh return TCL_OK;
1277d1bf3512Sdrh }
1278d1bf3512Sdrh
1279d1bf3512Sdrh /*
1280e9707671Sdrh ** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
1281e9707671Sdrh **
1282e9707671Sdrh ** Call mprintf with three 64-bit integer arguments
1283e9707671Sdrh */
sqlite3_mprintf_int64(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)12847617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_mprintf_int64(
1285e9707671Sdrh void *NotUsed,
1286e9707671Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1287e9707671Sdrh int argc, /* Number of arguments */
1288e9707671Sdrh char **argv /* Text of each argument */
1289e9707671Sdrh ){
1290e9707671Sdrh int i;
1291e9707671Sdrh sqlite_int64 a[3];
1292e9707671Sdrh char *z;
1293e9707671Sdrh if( argc!=5 ){
1294e9707671Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1295e9707671Sdrh " FORMAT INT INT INT\"", 0);
1296e9707671Sdrh return TCL_ERROR;
1297e9707671Sdrh }
1298e9707671Sdrh for(i=2; i<5; i++){
1299609d5846Sdrh if( sqlite3Atoi64(argv[i], &a[i-2], sqlite3Strlen30(argv[i]), SQLITE_UTF8) ){
1300e9707671Sdrh Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
1301e9707671Sdrh return TCL_ERROR;
1302e9707671Sdrh }
1303e9707671Sdrh }
1304e9707671Sdrh z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
1305e9707671Sdrh Tcl_AppendResult(interp, z, 0);
1306e9707671Sdrh sqlite3_free(z);
1307e9707671Sdrh return TCL_OK;
1308e9707671Sdrh }
1309e9707671Sdrh
1310e9707671Sdrh /*
1311c5cad1e3Sdrh ** Usage: sqlite3_mprintf_long FORMAT INTEGER INTEGER INTEGER
1312c5cad1e3Sdrh **
1313c5cad1e3Sdrh ** Call mprintf with three long integer arguments. This might be the
1314c5cad1e3Sdrh ** same as sqlite3_mprintf_int or sqlite3_mprintf_int64, depending on
1315c5cad1e3Sdrh ** platform.
1316c5cad1e3Sdrh */
sqlite3_mprintf_long(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)13177617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_mprintf_long(
1318c5cad1e3Sdrh void *NotUsed,
1319c5cad1e3Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1320c5cad1e3Sdrh int argc, /* Number of arguments */
1321c5cad1e3Sdrh char **argv /* Text of each argument */
1322c5cad1e3Sdrh ){
1323c5cad1e3Sdrh int i;
1324c5cad1e3Sdrh long int a[3];
1325c5cad1e3Sdrh int b[3];
1326c5cad1e3Sdrh char *z;
1327c5cad1e3Sdrh if( argc!=5 ){
1328c5cad1e3Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1329c5cad1e3Sdrh " FORMAT INT INT INT\"", 0);
1330c5cad1e3Sdrh return TCL_ERROR;
1331c5cad1e3Sdrh }
1332c5cad1e3Sdrh for(i=2; i<5; i++){
1333c5cad1e3Sdrh if( Tcl_GetInt(interp, argv[i], &b[i-2]) ) return TCL_ERROR;
1334c5cad1e3Sdrh a[i-2] = (long int)b[i-2];
13357ed0cae2Sdrh a[i-2] &= (((u64)1)<<(sizeof(int)*8))-1;
1336c5cad1e3Sdrh }
1337c5cad1e3Sdrh z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
1338c5cad1e3Sdrh Tcl_AppendResult(interp, z, 0);
1339c5cad1e3Sdrh sqlite3_free(z);
1340c5cad1e3Sdrh return TCL_OK;
1341c5cad1e3Sdrh }
1342c5cad1e3Sdrh
1343c5cad1e3Sdrh /*
13446f8a503dSdanielk1977 ** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
1345d1bf3512Sdrh **
1346d1bf3512Sdrh ** Call mprintf with two integer arguments and one string argument
1347d1bf3512Sdrh */
sqlite3_mprintf_str(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)13487617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_mprintf_str(
1349d1bf3512Sdrh void *NotUsed,
1350d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1351d1bf3512Sdrh int argc, /* Number of arguments */
1352d1bf3512Sdrh char **argv /* Text of each argument */
1353d1bf3512Sdrh ){
1354d1bf3512Sdrh int a[3], i;
1355d1bf3512Sdrh char *z;
1356f220b24fSchw if( argc<4 || argc>5 ){
1357d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1358f220b24fSchw " FORMAT INT INT ?STRING?\"", 0);
1359d1bf3512Sdrh return TCL_ERROR;
1360d1bf3512Sdrh }
1361d1bf3512Sdrh for(i=2; i<4; i++){
1362d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
1363d1bf3512Sdrh }
13646f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
1365d1bf3512Sdrh Tcl_AppendResult(interp, z, 0);
13663f4fedb2Sdrh sqlite3_free(z);
1367d1bf3512Sdrh return TCL_OK;
1368d1bf3512Sdrh }
1369d1bf3512Sdrh
1370d1bf3512Sdrh /*
1371b3738b6cSdrh ** Usage: sqlite3_snprintf_str INTEGER FORMAT INTEGER INTEGER STRING
1372b3738b6cSdrh **
1373b3738b6cSdrh ** Call mprintf with two integer arguments and one string argument
1374b3738b6cSdrh */
sqlite3_snprintf_str(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)13757617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_snprintf_str(
1376b3738b6cSdrh void *NotUsed,
1377b3738b6cSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1378b3738b6cSdrh int argc, /* Number of arguments */
1379b3738b6cSdrh char **argv /* Text of each argument */
1380b3738b6cSdrh ){
1381b3738b6cSdrh int a[3], i;
1382b3738b6cSdrh int n;
1383b3738b6cSdrh char *z;
1384b3738b6cSdrh if( argc<5 || argc>6 ){
1385b3738b6cSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1386b3738b6cSdrh " INT FORMAT INT INT ?STRING?\"", 0);
1387b3738b6cSdrh return TCL_ERROR;
1388b3738b6cSdrh }
1389b3738b6cSdrh if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
1390b3738b6cSdrh if( n<0 ){
1391b3738b6cSdrh Tcl_AppendResult(interp, "N must be non-negative", 0);
1392b3738b6cSdrh return TCL_ERROR;
1393b3738b6cSdrh }
1394b3738b6cSdrh for(i=3; i<5; i++){
1395b3738b6cSdrh if( Tcl_GetInt(interp, argv[i], &a[i-3]) ) return TCL_ERROR;
1396b3738b6cSdrh }
1397b3738b6cSdrh z = sqlite3_malloc( n+1 );
1398b3738b6cSdrh sqlite3_snprintf(n, z, argv[2], a[0], a[1], argc>4 ? argv[5] : NULL);
1399b3738b6cSdrh Tcl_AppendResult(interp, z, 0);
1400b3738b6cSdrh sqlite3_free(z);
1401b3738b6cSdrh return TCL_OK;
1402b3738b6cSdrh }
1403b3738b6cSdrh
1404b3738b6cSdrh /*
140563782855Sdrh ** Usage: sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE
1406d1bf3512Sdrh **
1407d1bf3512Sdrh ** Call mprintf with two integer arguments and one double argument
1408d1bf3512Sdrh */
sqlite3_mprintf_double(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)14097617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_mprintf_double(
1410d1bf3512Sdrh void *NotUsed,
1411d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1412d1bf3512Sdrh int argc, /* Number of arguments */
1413d1bf3512Sdrh char **argv /* Text of each argument */
1414d1bf3512Sdrh ){
1415d1bf3512Sdrh int a[3], i;
1416d1bf3512Sdrh double r;
1417d1bf3512Sdrh char *z;
1418d1bf3512Sdrh if( argc!=5 ){
1419d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
142063782855Sdrh " FORMAT INT INT DOUBLE\"", 0);
1421d1bf3512Sdrh return TCL_ERROR;
1422d1bf3512Sdrh }
1423d1bf3512Sdrh for(i=2; i<4; i++){
1424d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
1425d1bf3512Sdrh }
1426d1bf3512Sdrh if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
14276f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], a[0], a[1], r);
1428d1bf3512Sdrh Tcl_AppendResult(interp, z, 0);
14293f4fedb2Sdrh sqlite3_free(z);
1430d1bf3512Sdrh return TCL_OK;
1431d1bf3512Sdrh }
1432d1bf3512Sdrh
1433d1bf3512Sdrh /*
143463782855Sdrh ** Usage: sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE
1435b621c237Sdrh **
1436b621c237Sdrh ** Call mprintf with a single double argument which is the product of the
1437b621c237Sdrh ** two arguments given above. This is used to generate overflow and underflow
1438b621c237Sdrh ** doubles to test that they are converted properly.
1439b621c237Sdrh */
sqlite3_mprintf_scaled(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)14407617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_mprintf_scaled(
1441b621c237Sdrh void *NotUsed,
1442b621c237Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1443b621c237Sdrh int argc, /* Number of arguments */
1444b621c237Sdrh char **argv /* Text of each argument */
1445b621c237Sdrh ){
1446b621c237Sdrh int i;
1447b621c237Sdrh double r[2];
1448b621c237Sdrh char *z;
1449b621c237Sdrh if( argc!=4 ){
1450b621c237Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1451b621c237Sdrh " FORMAT DOUBLE DOUBLE\"", 0);
1452b621c237Sdrh return TCL_ERROR;
1453b621c237Sdrh }
1454b621c237Sdrh for(i=2; i<4; i++){
1455b621c237Sdrh if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
1456b621c237Sdrh }
14576f8a503dSdanielk1977 z = sqlite3_mprintf(argv[1], r[0]*r[1]);
1458b621c237Sdrh Tcl_AppendResult(interp, z, 0);
14593f4fedb2Sdrh sqlite3_free(z);
1460b621c237Sdrh return TCL_OK;
1461b621c237Sdrh }
1462b621c237Sdrh
1463b621c237Sdrh /*
1464e29b1a05Sdrh ** Usage: sqlite3_mprintf_stronly FORMAT STRING
1465e29b1a05Sdrh **
1466e29b1a05Sdrh ** Call mprintf with a single double argument which is the product of the
1467e29b1a05Sdrh ** two arguments given above. This is used to generate overflow and underflow
1468e29b1a05Sdrh ** doubles to test that they are converted properly.
1469e29b1a05Sdrh */
sqlite3_mprintf_stronly(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)14707617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_mprintf_stronly(
1471e29b1a05Sdrh void *NotUsed,
1472e29b1a05Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1473e29b1a05Sdrh int argc, /* Number of arguments */
1474e29b1a05Sdrh char **argv /* Text of each argument */
1475e29b1a05Sdrh ){
1476e29b1a05Sdrh char *z;
1477e29b1a05Sdrh if( argc!=3 ){
1478e29b1a05Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1479e29b1a05Sdrh " FORMAT STRING\"", 0);
1480e29b1a05Sdrh return TCL_ERROR;
1481e29b1a05Sdrh }
1482e29b1a05Sdrh z = sqlite3_mprintf(argv[1], argv[2]);
1483e29b1a05Sdrh Tcl_AppendResult(interp, z, 0);
1484e29b1a05Sdrh sqlite3_free(z);
1485e29b1a05Sdrh return TCL_OK;
1486e29b1a05Sdrh }
1487e29b1a05Sdrh
1488e29b1a05Sdrh /*
148963782855Sdrh ** Usage: sqlite3_mprintf_hexdouble FORMAT HEX
149063782855Sdrh **
149163782855Sdrh ** Call mprintf with a single double argument which is derived from the
149263782855Sdrh ** hexadecimal encoding of an IEEE double.
149363782855Sdrh */
sqlite3_mprintf_hexdouble(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)14947617e4a8Smistachkin static int SQLITE_TCLAPI sqlite3_mprintf_hexdouble(
149563782855Sdrh void *NotUsed,
149663782855Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
149763782855Sdrh int argc, /* Number of arguments */
149863782855Sdrh char **argv /* Text of each argument */
149963782855Sdrh ){
150063782855Sdrh char *z;
150163782855Sdrh double r;
15025e73db36Sshane unsigned int x1, x2;
15035e73db36Sshane sqlite_uint64 d;
150463782855Sdrh if( argc!=3 ){
150563782855Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
150663782855Sdrh " FORMAT STRING\"", 0);
150763782855Sdrh return TCL_ERROR;
150863782855Sdrh }
150963782855Sdrh if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){
151063782855Sdrh Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0);
151163782855Sdrh return TCL_ERROR;
151263782855Sdrh }
151363782855Sdrh d = x2;
151463782855Sdrh d = (d<<32) + x1;
151563782855Sdrh memcpy(&r, &d, sizeof(r));
151663782855Sdrh z = sqlite3_mprintf(argv[1], r);
151763782855Sdrh Tcl_AppendResult(interp, z, 0);
151863782855Sdrh sqlite3_free(z);
151963782855Sdrh return TCL_OK;
152063782855Sdrh }
152163782855Sdrh
152263782855Sdrh /*
1523c1def3e0Sdanielk1977 ** Usage: sqlite3_enable_shared_cache ?BOOLEAN?
1524aef0bf64Sdanielk1977 **
1525aef0bf64Sdanielk1977 */
15266f7adc8aSdrh #if !defined(SQLITE_OMIT_SHARED_CACHE)
test_enable_shared(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])15277617e4a8Smistachkin static int SQLITE_TCLAPI test_enable_shared(
152852622828Sdanielk1977 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1529aef0bf64Sdanielk1977 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1530aef0bf64Sdanielk1977 int objc, /* Number of arguments */
1531aef0bf64Sdanielk1977 Tcl_Obj *CONST objv[] /* Command arguments */
1532aef0bf64Sdanielk1977 ){
1533aef0bf64Sdanielk1977 int rc;
1534aef0bf64Sdanielk1977 int enable;
153552622828Sdanielk1977 int ret = 0;
1536aef0bf64Sdanielk1977
1537c1def3e0Sdanielk1977 if( objc!=2 && objc!=1 ){
1538c1def3e0Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?");
1539aef0bf64Sdanielk1977 return TCL_ERROR;
1540aef0bf64Sdanielk1977 }
1541502b4e00Sdanielk1977 ret = sqlite3GlobalConfig.sharedCacheEnabled;
1542c1def3e0Sdanielk1977
1543c1def3e0Sdanielk1977 if( objc==2 ){
1544c1def3e0Sdanielk1977 if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){
1545c1def3e0Sdanielk1977 return TCL_ERROR;
1546c1def3e0Sdanielk1977 }
15476f7adc8aSdrh rc = sqlite3_enable_shared_cache(enable);
1548aef0bf64Sdanielk1977 if( rc!=SQLITE_OK ){
1549aef0bf64Sdanielk1977 Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
1550aef0bf64Sdanielk1977 return TCL_ERROR;
1551aef0bf64Sdanielk1977 }
1552c1def3e0Sdanielk1977 }
155352622828Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret));
1554aef0bf64Sdanielk1977 return TCL_OK;
1555aef0bf64Sdanielk1977 }
1556aef0bf64Sdanielk1977 #endif
1557aef0bf64Sdanielk1977
155816a9b836Sdrh
155916a9b836Sdrh
1560aef0bf64Sdanielk1977 /*
15614ac285a1Sdrh ** Usage: sqlite3_extended_result_codes DB BOOLEAN
15624ac285a1Sdrh **
15634ac285a1Sdrh */
test_extended_result_codes(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])15647617e4a8Smistachkin static int SQLITE_TCLAPI test_extended_result_codes(
15654ac285a1Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
15664ac285a1Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
15674ac285a1Sdrh int objc, /* Number of arguments */
15684ac285a1Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
15694ac285a1Sdrh ){
15704ac285a1Sdrh int enable;
15714ac285a1Sdrh sqlite3 *db;
15724ac285a1Sdrh
15734ac285a1Sdrh if( objc!=3 ){
15744ac285a1Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN");
15754ac285a1Sdrh return TCL_ERROR;
15764ac285a1Sdrh }
15774ac285a1Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
15784ac285a1Sdrh if( Tcl_GetBooleanFromObj(interp, objv[2], &enable) ) return TCL_ERROR;
15794ac285a1Sdrh sqlite3_extended_result_codes(db, enable);
15804ac285a1Sdrh return TCL_OK;
15814ac285a1Sdrh }
15824ac285a1Sdrh
15834ac285a1Sdrh /*
1584161fb796Sdanielk1977 ** Usage: sqlite3_libversion_number
1585161fb796Sdanielk1977 **
1586161fb796Sdanielk1977 */
test_libversion_number(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])15877617e4a8Smistachkin static int SQLITE_TCLAPI test_libversion_number(
1588161fb796Sdanielk1977 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1589161fb796Sdanielk1977 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1590161fb796Sdanielk1977 int objc, /* Number of arguments */
1591161fb796Sdanielk1977 Tcl_Obj *CONST objv[] /* Command arguments */
1592161fb796Sdanielk1977 ){
1593161fb796Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_libversion_number()));
1594161fb796Sdanielk1977 return TCL_OK;
1595161fb796Sdanielk1977 }
1596161fb796Sdanielk1977
1597161fb796Sdanielk1977 /*
1598deb802cdSdanielk1977 ** Usage: sqlite3_table_column_metadata DB dbname tblname colname
1599deb802cdSdanielk1977 **
1600deb802cdSdanielk1977 */
test_table_column_metadata(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])16017617e4a8Smistachkin static int SQLITE_TCLAPI test_table_column_metadata(
1602deb802cdSdanielk1977 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1603deb802cdSdanielk1977 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1604deb802cdSdanielk1977 int objc, /* Number of arguments */
1605deb802cdSdanielk1977 Tcl_Obj *CONST objv[] /* Command arguments */
1606deb802cdSdanielk1977 ){
1607deb802cdSdanielk1977 sqlite3 *db;
1608deb802cdSdanielk1977 const char *zDb;
1609deb802cdSdanielk1977 const char *zTbl;
1610deb802cdSdanielk1977 const char *zCol;
1611deb802cdSdanielk1977 int rc;
1612deb802cdSdanielk1977 Tcl_Obj *pRet;
1613deb802cdSdanielk1977
1614deb802cdSdanielk1977 const char *zDatatype;
1615deb802cdSdanielk1977 const char *zCollseq;
1616deb802cdSdanielk1977 int notnull;
1617deb802cdSdanielk1977 int primarykey;
1618deb802cdSdanielk1977 int autoincrement;
1619deb802cdSdanielk1977
162045d1b206Sdrh if( objc!=5 && objc!=4 ){
1621deb802cdSdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname");
1622deb802cdSdanielk1977 return TCL_ERROR;
1623deb802cdSdanielk1977 }
1624deb802cdSdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1625deb802cdSdanielk1977 zDb = Tcl_GetString(objv[2]);
1626deb802cdSdanielk1977 zTbl = Tcl_GetString(objv[3]);
162745d1b206Sdrh zCol = objc==5 ? Tcl_GetString(objv[4]) : 0;
1628deb802cdSdanielk1977
1629deb802cdSdanielk1977 if( strlen(zDb)==0 ) zDb = 0;
1630deb802cdSdanielk1977
1631deb802cdSdanielk1977 rc = sqlite3_table_column_metadata(db, zDb, zTbl, zCol,
1632deb802cdSdanielk1977 &zDatatype, &zCollseq, ¬null, &primarykey, &autoincrement);
1633deb802cdSdanielk1977
1634deb802cdSdanielk1977 if( rc!=SQLITE_OK ){
1635deb802cdSdanielk1977 Tcl_AppendResult(interp, sqlite3_errmsg(db), 0);
1636deb802cdSdanielk1977 return TCL_ERROR;
1637deb802cdSdanielk1977 }
1638deb802cdSdanielk1977
1639deb802cdSdanielk1977 pRet = Tcl_NewObj();
1640deb802cdSdanielk1977 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zDatatype, -1));
1641deb802cdSdanielk1977 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zCollseq, -1));
1642deb802cdSdanielk1977 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(notnull));
1643deb802cdSdanielk1977 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(primarykey));
1644deb802cdSdanielk1977 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(autoincrement));
1645deb802cdSdanielk1977 Tcl_SetObjResult(interp, pRet);
1646deb802cdSdanielk1977
1647deb802cdSdanielk1977 return TCL_OK;
1648deb802cdSdanielk1977 }
1649deb802cdSdanielk1977
1650dcbb5d3fSdanielk1977 #ifndef SQLITE_OMIT_INCRBLOB
1651dcbb5d3fSdanielk1977
blobHandleFromObj(Tcl_Interp * interp,Tcl_Obj * pObj,sqlite3_blob ** ppBlob)16527617e4a8Smistachkin static int SQLITE_TCLAPI blobHandleFromObj(
165361c7f59cSdan Tcl_Interp *interp,
165461c7f59cSdan Tcl_Obj *pObj,
165561c7f59cSdan sqlite3_blob **ppBlob
165661c7f59cSdan ){
165761c7f59cSdan char *z;
165861c7f59cSdan int n;
165961c7f59cSdan
166061c7f59cSdan z = Tcl_GetStringFromObj(pObj, &n);
166161c7f59cSdan if( n==0 ){
166261c7f59cSdan *ppBlob = 0;
166361c7f59cSdan }else{
166461c7f59cSdan int notUsed;
166561c7f59cSdan Tcl_Channel channel;
166661c7f59cSdan ClientData instanceData;
166761c7f59cSdan
166861c7f59cSdan channel = Tcl_GetChannel(interp, z, ¬Used);
166961c7f59cSdan if( !channel ) return TCL_ERROR;
167061c7f59cSdan
167161c7f59cSdan Tcl_Flush(channel);
167261c7f59cSdan Tcl_Seek(channel, 0, SEEK_SET);
167361c7f59cSdan
167461c7f59cSdan instanceData = Tcl_GetChannelInstanceData(channel);
167561c7f59cSdan *ppBlob = *((sqlite3_blob **)instanceData);
167661c7f59cSdan }
167761c7f59cSdan
167861c7f59cSdan return TCL_OK;
167961c7f59cSdan }
168061c7f59cSdan
test_blob_reopen(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])16817617e4a8Smistachkin static int SQLITE_TCLAPI test_blob_reopen(
16824e76cc36Sdan ClientData clientData, /* Not used */
16834e76cc36Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
16844e76cc36Sdan int objc, /* Number of arguments */
16854e76cc36Sdan Tcl_Obj *CONST objv[] /* Command arguments */
16864e76cc36Sdan ){
16874e76cc36Sdan Tcl_WideInt iRowid;
16884e76cc36Sdan sqlite3_blob *pBlob;
16894e76cc36Sdan int rc;
16904e76cc36Sdan
16914e76cc36Sdan if( objc!=3 ){
16924e76cc36Sdan Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL ROWID");
16934e76cc36Sdan return TCL_ERROR;
16944e76cc36Sdan }
16954e76cc36Sdan
169661c7f59cSdan if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
169761c7f59cSdan if( Tcl_GetWideIntFromObj(interp, objv[2], &iRowid) ) return TCL_ERROR;
16984e76cc36Sdan
16994e76cc36Sdan rc = sqlite3_blob_reopen(pBlob, iRowid);
17004e76cc36Sdan if( rc!=SQLITE_OK ){
1701e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
17024e76cc36Sdan }
17034e76cc36Sdan
17044e76cc36Sdan return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
17054e76cc36Sdan }
17064e76cc36Sdan
1707dcbb5d3fSdanielk1977 #endif
1708c2e87a3eSdrh
1709deb802cdSdanielk1977 /*
1710a393c036Sdanielk1977 ** Usage: sqlite3_create_collation_v2 DB-HANDLE NAME CMP-PROC DEL-PROC
1711a9808b31Sdanielk1977 **
1712a9808b31Sdanielk1977 ** This Tcl proc is used for testing the experimental
1713a393c036Sdanielk1977 ** sqlite3_create_collation_v2() interface.
1714a9808b31Sdanielk1977 */
1715a9808b31Sdanielk1977 struct TestCollationX {
1716a9808b31Sdanielk1977 Tcl_Interp *interp;
1717a9808b31Sdanielk1977 Tcl_Obj *pCmp;
1718a9808b31Sdanielk1977 Tcl_Obj *pDel;
1719a9808b31Sdanielk1977 };
1720a9808b31Sdanielk1977 typedef struct TestCollationX TestCollationX;
testCreateCollationDel(void * pCtx)1721a9808b31Sdanielk1977 static void testCreateCollationDel(void *pCtx){
1722a9808b31Sdanielk1977 TestCollationX *p = (TestCollationX *)pCtx;
1723a9808b31Sdanielk1977
1724a9808b31Sdanielk1977 int rc = Tcl_EvalObjEx(p->interp, p->pDel, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL);
1725a9808b31Sdanielk1977 if( rc!=TCL_OK ){
1726a9808b31Sdanielk1977 Tcl_BackgroundError(p->interp);
1727a9808b31Sdanielk1977 }
1728a9808b31Sdanielk1977
1729a9808b31Sdanielk1977 Tcl_DecrRefCount(p->pCmp);
1730a9808b31Sdanielk1977 Tcl_DecrRefCount(p->pDel);
1731a9808b31Sdanielk1977 sqlite3_free((void *)p);
1732a9808b31Sdanielk1977 }
testCreateCollationCmp(void * pCtx,int nLeft,const void * zLeft,int nRight,const void * zRight)1733a9808b31Sdanielk1977 static int testCreateCollationCmp(
1734a9808b31Sdanielk1977 void *pCtx,
1735a9808b31Sdanielk1977 int nLeft,
1736a9808b31Sdanielk1977 const void *zLeft,
1737a9808b31Sdanielk1977 int nRight,
1738a9808b31Sdanielk1977 const void *zRight
1739a9808b31Sdanielk1977 ){
1740a9808b31Sdanielk1977 TestCollationX *p = (TestCollationX *)pCtx;
1741a9808b31Sdanielk1977 Tcl_Obj *pScript = Tcl_DuplicateObj(p->pCmp);
1742a9808b31Sdanielk1977 int iRes = 0;
1743a9808b31Sdanielk1977
1744a9808b31Sdanielk1977 Tcl_IncrRefCount(pScript);
1745a9808b31Sdanielk1977 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zLeft, nLeft));
1746a9808b31Sdanielk1977 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zRight,nRight));
1747a9808b31Sdanielk1977
1748a9808b31Sdanielk1977 if( TCL_OK!=Tcl_EvalObjEx(p->interp, pScript, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL)
1749a9808b31Sdanielk1977 || TCL_OK!=Tcl_GetIntFromObj(p->interp, Tcl_GetObjResult(p->interp), &iRes)
1750a9808b31Sdanielk1977 ){
1751a9808b31Sdanielk1977 Tcl_BackgroundError(p->interp);
1752a9808b31Sdanielk1977 }
1753a9808b31Sdanielk1977 Tcl_DecrRefCount(pScript);
1754a9808b31Sdanielk1977
1755a9808b31Sdanielk1977 return iRes;
1756a9808b31Sdanielk1977 }
test_create_collation_v2(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])17577617e4a8Smistachkin static int SQLITE_TCLAPI test_create_collation_v2(
1758a9808b31Sdanielk1977 ClientData clientData, /* Not used */
1759a9808b31Sdanielk1977 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1760a9808b31Sdanielk1977 int objc, /* Number of arguments */
1761a9808b31Sdanielk1977 Tcl_Obj *CONST objv[] /* Command arguments */
1762a9808b31Sdanielk1977 ){
1763a9808b31Sdanielk1977 TestCollationX *p;
1764a9808b31Sdanielk1977 sqlite3 *db;
1765d55d57edSdrh int rc;
1766a9808b31Sdanielk1977
1767a9808b31Sdanielk1977 if( objc!=5 ){
1768a9808b31Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE NAME CMP-PROC DEL-PROC");
1769a9808b31Sdanielk1977 return TCL_ERROR;
1770a9808b31Sdanielk1977 }
1771a9808b31Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1772a9808b31Sdanielk1977
1773a9808b31Sdanielk1977 p = (TestCollationX *)sqlite3_malloc(sizeof(TestCollationX));
1774a9808b31Sdanielk1977 p->pCmp = objv[3];
1775a9808b31Sdanielk1977 p->pDel = objv[4];
1776a9808b31Sdanielk1977 p->interp = interp;
1777a9808b31Sdanielk1977 Tcl_IncrRefCount(p->pCmp);
1778a9808b31Sdanielk1977 Tcl_IncrRefCount(p->pDel);
1779a9808b31Sdanielk1977
1780d55d57edSdrh rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), 16,
1781d55d57edSdrh (void *)p, testCreateCollationCmp, testCreateCollationDel
1782d55d57edSdrh );
1783d55d57edSdrh if( rc!=SQLITE_MISUSE ){
1784d55d57edSdrh Tcl_AppendResult(interp, "sqlite3_create_collate_v2() failed to detect "
1785d55d57edSdrh "an invalid encoding", (char*)0);
1786d55d57edSdrh return TCL_ERROR;
1787d55d57edSdrh }
1788d55d57edSdrh rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), SQLITE_UTF8,
1789a9808b31Sdanielk1977 (void *)p, testCreateCollationCmp, testCreateCollationDel
1790a9808b31Sdanielk1977 );
1791a9808b31Sdanielk1977 return TCL_OK;
1792a9808b31Sdanielk1977 }
1793a9808b31Sdanielk1977
1794a9808b31Sdanielk1977 /*
1795d2199f0fSdan ** USAGE: sqlite3_create_function_v2 DB NAME NARG ENC ?SWITCHES?
1796d2199f0fSdan **
1797d2199f0fSdan ** Available switches are:
1798d2199f0fSdan **
1799d2199f0fSdan ** -func SCRIPT
1800d2199f0fSdan ** -step SCRIPT
1801d2199f0fSdan ** -final SCRIPT
1802d2199f0fSdan ** -destroy SCRIPT
1803d2199f0fSdan */
1804d2199f0fSdan typedef struct CreateFunctionV2 CreateFunctionV2;
1805d2199f0fSdan struct CreateFunctionV2 {
1806d2199f0fSdan Tcl_Interp *interp;
1807d2199f0fSdan Tcl_Obj *pFunc; /* Script for function invocation */
1808d2199f0fSdan Tcl_Obj *pStep; /* Script for agg. step invocation */
1809d2199f0fSdan Tcl_Obj *pFinal; /* Script for agg. finalization invocation */
1810d2199f0fSdan Tcl_Obj *pDestroy; /* Destructor script */
1811d2199f0fSdan };
cf2Func(sqlite3_context * ctx,int nArg,sqlite3_value ** aArg)1812d2199f0fSdan static void cf2Func(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
1813d2199f0fSdan }
cf2Step(sqlite3_context * ctx,int nArg,sqlite3_value ** aArg)1814d2199f0fSdan static void cf2Step(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
1815d2199f0fSdan }
cf2Final(sqlite3_context * ctx)1816d2199f0fSdan static void cf2Final(sqlite3_context *ctx){
1817d2199f0fSdan }
cf2Destroy(void * pUser)1818d2199f0fSdan static void cf2Destroy(void *pUser){
1819d2199f0fSdan CreateFunctionV2 *p = (CreateFunctionV2 *)pUser;
1820d2199f0fSdan
1821d2199f0fSdan if( p->interp && p->pDestroy ){
1822d2199f0fSdan int rc = Tcl_EvalObjEx(p->interp, p->pDestroy, 0);
1823d2199f0fSdan if( rc!=TCL_OK ) Tcl_BackgroundError(p->interp);
1824d2199f0fSdan }
1825d2199f0fSdan
1826d2199f0fSdan if( p->pFunc ) Tcl_DecrRefCount(p->pFunc);
1827d2199f0fSdan if( p->pStep ) Tcl_DecrRefCount(p->pStep);
1828d2199f0fSdan if( p->pFinal ) Tcl_DecrRefCount(p->pFinal);
1829d2199f0fSdan if( p->pDestroy ) Tcl_DecrRefCount(p->pDestroy);
1830d2199f0fSdan sqlite3_free(p);
1831d2199f0fSdan }
test_create_function_v2(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])18327617e4a8Smistachkin static int SQLITE_TCLAPI test_create_function_v2(
1833d2199f0fSdan ClientData clientData, /* Not used */
1834d2199f0fSdan Tcl_Interp *interp, /* The invoking TCL interpreter */
1835d2199f0fSdan int objc, /* Number of arguments */
1836d2199f0fSdan Tcl_Obj *CONST objv[] /* Command arguments */
1837d2199f0fSdan ){
1838d2199f0fSdan sqlite3 *db;
1839d2199f0fSdan const char *zFunc;
1840d2199f0fSdan int nArg;
1841d2199f0fSdan int enc;
1842d2199f0fSdan CreateFunctionV2 *p;
1843d2199f0fSdan int i;
1844d2199f0fSdan int rc;
1845d2199f0fSdan
1846d2199f0fSdan struct EncTable {
1847d2199f0fSdan const char *zEnc;
1848d2199f0fSdan int enc;
1849d2199f0fSdan } aEnc[] = {
1850d2199f0fSdan {"utf8", SQLITE_UTF8 },
1851d2199f0fSdan {"utf16", SQLITE_UTF16 },
1852d2199f0fSdan {"utf16le", SQLITE_UTF16LE },
1853d2199f0fSdan {"utf16be", SQLITE_UTF16BE },
1854d2199f0fSdan {"any", SQLITE_ANY },
18559b6a2833Sdan {"0", 0 },
18569b6a2833Sdan {0, 0 }
1857d2199f0fSdan };
1858d2199f0fSdan
1859d2199f0fSdan if( objc<5 || (objc%2)==0 ){
1860d2199f0fSdan Tcl_WrongNumArgs(interp, 1, objv, "DB NAME NARG ENC SWITCHES...");
1861d2199f0fSdan return TCL_ERROR;
1862d2199f0fSdan }
1863d2199f0fSdan
1864d2199f0fSdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1865d2199f0fSdan zFunc = Tcl_GetString(objv[2]);
1866d2199f0fSdan if( Tcl_GetIntFromObj(interp, objv[3], &nArg) ) return TCL_ERROR;
1867d2199f0fSdan if( Tcl_GetIndexFromObjStruct(interp, objv[4], aEnc, sizeof(aEnc[0]),
1868d2199f0fSdan "encoding", 0, &enc)
1869d2199f0fSdan ){
1870d2199f0fSdan return TCL_ERROR;
1871d2199f0fSdan }
1872d2199f0fSdan enc = aEnc[enc].enc;
1873d2199f0fSdan
1874d2199f0fSdan p = sqlite3_malloc(sizeof(CreateFunctionV2));
1875d2199f0fSdan assert( p );
1876d2199f0fSdan memset(p, 0, sizeof(CreateFunctionV2));
1877d2199f0fSdan p->interp = interp;
1878d2199f0fSdan
1879d2199f0fSdan for(i=5; i<objc; i+=2){
1880d2199f0fSdan int iSwitch;
1881d2199f0fSdan const char *azSwitch[] = {"-func", "-step", "-final", "-destroy", 0};
1882d2199f0fSdan if( Tcl_GetIndexFromObj(interp, objv[i], azSwitch, "switch", 0, &iSwitch) ){
1883d2199f0fSdan sqlite3_free(p);
1884d2199f0fSdan return TCL_ERROR;
1885d2199f0fSdan }
1886d2199f0fSdan
1887d2199f0fSdan switch( iSwitch ){
1888d2199f0fSdan case 0: p->pFunc = objv[i+1]; break;
1889d2199f0fSdan case 1: p->pStep = objv[i+1]; break;
1890d2199f0fSdan case 2: p->pFinal = objv[i+1]; break;
1891d2199f0fSdan case 3: p->pDestroy = objv[i+1]; break;
1892d2199f0fSdan }
1893d2199f0fSdan }
1894d2199f0fSdan if( p->pFunc ) p->pFunc = Tcl_DuplicateObj(p->pFunc);
1895d2199f0fSdan if( p->pStep ) p->pStep = Tcl_DuplicateObj(p->pStep);
1896d2199f0fSdan if( p->pFinal ) p->pFinal = Tcl_DuplicateObj(p->pFinal);
1897d2199f0fSdan if( p->pDestroy ) p->pDestroy = Tcl_DuplicateObj(p->pDestroy);
1898d2199f0fSdan
1899d2199f0fSdan if( p->pFunc ) Tcl_IncrRefCount(p->pFunc);
1900d2199f0fSdan if( p->pStep ) Tcl_IncrRefCount(p->pStep);
1901d2199f0fSdan if( p->pFinal ) Tcl_IncrRefCount(p->pFinal);
1902d2199f0fSdan if( p->pDestroy ) Tcl_IncrRefCount(p->pDestroy);
1903d2199f0fSdan
1904d2199f0fSdan rc = sqlite3_create_function_v2(db, zFunc, nArg, enc, (void *)p,
1905d2199f0fSdan (p->pFunc ? cf2Func : 0),
1906d2199f0fSdan (p->pStep ? cf2Step : 0),
1907d2199f0fSdan (p->pFinal ? cf2Final : 0),
1908d2199f0fSdan cf2Destroy
1909d2199f0fSdan );
1910d2199f0fSdan if( rc!=SQLITE_OK ){
1911d2199f0fSdan Tcl_ResetResult(interp);
1912e84d8d32Smistachkin Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
1913d2199f0fSdan return TCL_ERROR;
1914d2199f0fSdan }
1915d2199f0fSdan return TCL_OK;
1916d2199f0fSdan }
1917d2199f0fSdan
1918d2199f0fSdan /*
191969e777f3Sdanielk1977 ** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC?
192069e777f3Sdanielk1977 */
test_load_extension(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])19217617e4a8Smistachkin static int SQLITE_TCLAPI test_load_extension(
192269e777f3Sdanielk1977 ClientData clientData, /* Not used */
192369e777f3Sdanielk1977 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
192469e777f3Sdanielk1977 int objc, /* Number of arguments */
192569e777f3Sdanielk1977 Tcl_Obj *CONST objv[] /* Command arguments */
192669e777f3Sdanielk1977 ){
192769e777f3Sdanielk1977 Tcl_CmdInfo cmdInfo;
192869e777f3Sdanielk1977 sqlite3 *db;
192969e777f3Sdanielk1977 int rc;
193069e777f3Sdanielk1977 char *zDb;
193169e777f3Sdanielk1977 char *zFile;
193269e777f3Sdanielk1977 char *zProc = 0;
193369e777f3Sdanielk1977 char *zErr = 0;
193469e777f3Sdanielk1977
193569e777f3Sdanielk1977 if( objc!=4 && objc!=3 ){
193669e777f3Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?");
193769e777f3Sdanielk1977 return TCL_ERROR;
193869e777f3Sdanielk1977 }
193969e777f3Sdanielk1977 zDb = Tcl_GetString(objv[1]);
194069e777f3Sdanielk1977 zFile = Tcl_GetString(objv[2]);
194169e777f3Sdanielk1977 if( objc==4 ){
194269e777f3Sdanielk1977 zProc = Tcl_GetString(objv[3]);
194369e777f3Sdanielk1977 }
194469e777f3Sdanielk1977
194569e777f3Sdanielk1977 /* Extract the C database handle from the Tcl command name */
194669e777f3Sdanielk1977 if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
194769e777f3Sdanielk1977 Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
194869e777f3Sdanielk1977 return TCL_ERROR;
194969e777f3Sdanielk1977 }
195069e777f3Sdanielk1977 db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
195169e777f3Sdanielk1977 assert(db);
195269e777f3Sdanielk1977
195369e777f3Sdanielk1977 /* Call the underlying C function. If an error occurs, set rc to
195469e777f3Sdanielk1977 ** TCL_ERROR and load any error string into the interpreter. If no
195569e777f3Sdanielk1977 ** error occurs, set rc to TCL_OK.
195669e777f3Sdanielk1977 */
1957c2e87a3eSdrh #ifdef SQLITE_OMIT_LOAD_EXTENSION
1958c2e87a3eSdrh rc = SQLITE_ERROR;
1959c2e87a3eSdrh zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()");
19609493cafeSdrh (void)zProc;
19619493cafeSdrh (void)zFile;
1962c2e87a3eSdrh #else
196369e777f3Sdanielk1977 rc = sqlite3_load_extension(db, zFile, zProc, &zErr);
1964c2e87a3eSdrh #endif
196569e777f3Sdanielk1977 if( rc!=SQLITE_OK ){
196669e777f3Sdanielk1977 Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE);
196769e777f3Sdanielk1977 rc = TCL_ERROR;
196869e777f3Sdanielk1977 }else{
196969e777f3Sdanielk1977 rc = TCL_OK;
197069e777f3Sdanielk1977 }
197169e777f3Sdanielk1977 sqlite3_free(zErr);
197269e777f3Sdanielk1977
197369e777f3Sdanielk1977 return rc;
197469e777f3Sdanielk1977 }
197569e777f3Sdanielk1977
197669e777f3Sdanielk1977 /*
1977c2e87a3eSdrh ** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF
1978c2e87a3eSdrh */
test_enable_load(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])19797617e4a8Smistachkin static int SQLITE_TCLAPI test_enable_load(
1980c2e87a3eSdrh ClientData clientData, /* Not used */
1981c2e87a3eSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1982c2e87a3eSdrh int objc, /* Number of arguments */
1983c2e87a3eSdrh Tcl_Obj *CONST objv[] /* Command arguments */
1984c2e87a3eSdrh ){
1985c2e87a3eSdrh Tcl_CmdInfo cmdInfo;
1986c2e87a3eSdrh sqlite3 *db;
1987c2e87a3eSdrh char *zDb;
1988c2e87a3eSdrh int onoff;
1989c2e87a3eSdrh
1990c2e87a3eSdrh if( objc!=3 ){
1991c2e87a3eSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF");
1992c2e87a3eSdrh return TCL_ERROR;
1993c2e87a3eSdrh }
1994c2e87a3eSdrh zDb = Tcl_GetString(objv[1]);
1995c2e87a3eSdrh
1996c2e87a3eSdrh /* Extract the C database handle from the Tcl command name */
1997c2e87a3eSdrh if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
1998c2e87a3eSdrh Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
1999c2e87a3eSdrh return TCL_ERROR;
2000c2e87a3eSdrh }
2001c2e87a3eSdrh db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
2002c2e87a3eSdrh assert(db);
2003c2e87a3eSdrh
2004c2e87a3eSdrh /* Get the onoff parameter */
2005c2e87a3eSdrh if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){
2006c2e87a3eSdrh return TCL_ERROR;
2007c2e87a3eSdrh }
2008c2e87a3eSdrh
2009c2e87a3eSdrh #ifdef SQLITE_OMIT_LOAD_EXTENSION
2010c2e87a3eSdrh Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()");
2011c2e87a3eSdrh return TCL_ERROR;
2012c2e87a3eSdrh #else
2013c2e87a3eSdrh sqlite3_enable_load_extension(db, onoff);
2014c2e87a3eSdrh return TCL_OK;
2015c2e87a3eSdrh #endif
2016c2e87a3eSdrh }
2017c2e87a3eSdrh
2018c2e87a3eSdrh /*
201928b4e489Sdrh ** Usage: sqlite_abort
202028b4e489Sdrh **
202128b4e489Sdrh ** Shutdown the process immediately. This is not a clean shutdown.
202228b4e489Sdrh ** This command is used to test the recoverability of a database in
202328b4e489Sdrh ** the event of a program crash.
202428b4e489Sdrh */
sqlite_abort(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)20257617e4a8Smistachkin static int SQLITE_TCLAPI sqlite_abort(
202628b4e489Sdrh void *NotUsed,
202728b4e489Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
202828b4e489Sdrh int argc, /* Number of arguments */
202928b4e489Sdrh char **argv /* Text of each argument */
203028b4e489Sdrh ){
20312ceced15Sshaneh #if defined(_MSC_VER)
20322ceced15Sshaneh /* We do this, otherwise the test will halt with a popup message
20332ceced15Sshaneh * that we have to click away before the test will continue.
20342ceced15Sshaneh */
20352ceced15Sshaneh _set_abort_behavior( 0, _CALL_REPORTFAULT );
20362ceced15Sshaneh #endif
2037d3f6b81aSdan exit(255);
203828b4e489Sdrh assert( interp==0 ); /* This will always fail */
203928b4e489Sdrh return TCL_OK;
204028b4e489Sdrh }
204128b4e489Sdrh
204228b4e489Sdrh /*
20436cbe1f1bSdrh ** The following routine is a user-defined SQL function whose purpose
20446cbe1f1bSdrh ** is to test the sqlite_set_result() API.
20456cbe1f1bSdrh */
testFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)20460ae8b831Sdanielk1977 static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
20476cbe1f1bSdrh while( argc>=2 ){
204803d847eaSdrh const char *zArg0 = (char*)sqlite3_value_text(argv[0]);
20496d88bad4Sdanielk1977 if( zArg0 ){
20506d88bad4Sdanielk1977 if( 0==sqlite3StrICmp(zArg0, "int") ){
20516d88bad4Sdanielk1977 sqlite3_result_int(context, sqlite3_value_int(argv[1]));
20526d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
20536d88bad4Sdanielk1977 sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
205451ad0ecdSdanielk1977 }else if( sqlite3StrICmp(zArg0,"string")==0 ){
205503d847eaSdrh sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1,
2056d8123366Sdanielk1977 SQLITE_TRANSIENT);
205751ad0ecdSdanielk1977 }else if( sqlite3StrICmp(zArg0,"double")==0 ){
20586d88bad4Sdanielk1977 sqlite3_result_double(context, sqlite3_value_double(argv[1]));
20596d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"null")==0 ){
20606d88bad4Sdanielk1977 sqlite3_result_null(context);
20616d88bad4Sdanielk1977 }else if( sqlite3StrICmp(zArg0,"value")==0 ){
20626d88bad4Sdanielk1977 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
20636cbe1f1bSdrh }else{
20646d88bad4Sdanielk1977 goto error_out;
20656d88bad4Sdanielk1977 }
20666d88bad4Sdanielk1977 }else{
20676d88bad4Sdanielk1977 goto error_out;
20686cbe1f1bSdrh }
20696cbe1f1bSdrh argc -= 2;
20706cbe1f1bSdrh argv += 2;
20716cbe1f1bSdrh }
20726d88bad4Sdanielk1977 return;
20736d88bad4Sdanielk1977
20746d88bad4Sdanielk1977 error_out:
20756d88bad4Sdanielk1977 sqlite3_result_error(context,"first argument should be one of: "
20766d88bad4Sdanielk1977 "int int64 string double null value", -1);
20776cbe1f1bSdrh }
20786cbe1f1bSdrh
20796cbe1f1bSdrh /*
20806cbe1f1bSdrh ** Usage: sqlite_register_test_function DB NAME
20816cbe1f1bSdrh **
20826cbe1f1bSdrh ** Register the test SQL function on the database DB under the name NAME.
20836cbe1f1bSdrh */
test_register_func(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)20847617e4a8Smistachkin static int SQLITE_TCLAPI test_register_func(
20856cbe1f1bSdrh void *NotUsed,
20866cbe1f1bSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
20876cbe1f1bSdrh int argc, /* Number of arguments */
20886cbe1f1bSdrh char **argv /* Text of each argument */
20896cbe1f1bSdrh ){
20909bb575fdSdrh sqlite3 *db;
20916cbe1f1bSdrh int rc;
20926cbe1f1bSdrh if( argc!=3 ){
20936cbe1f1bSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
20946cbe1f1bSdrh " DB FUNCTION-NAME", 0);
20956cbe1f1bSdrh return TCL_ERROR;
20966cbe1f1bSdrh }
2097b86ccfb2Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2098f9d64d2cSdanielk1977 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
2099d8123366Sdanielk1977 testFunc, 0, 0);
21006cbe1f1bSdrh if( rc!=0 ){
2101f20b21c8Sdanielk1977 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
21026cbe1f1bSdrh return TCL_ERROR;
21036cbe1f1bSdrh }
2104c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
21056cbe1f1bSdrh return TCL_OK;
21066cbe1f1bSdrh }
21076cbe1f1bSdrh
21086cbe1f1bSdrh /*
2109106bb236Sdanielk1977 ** Usage: sqlite3_finalize STMT
2110b86ccfb2Sdrh **
2111106bb236Sdanielk1977 ** Finalize a statement handle.
2112b86ccfb2Sdrh */
test_finalize(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])21137617e4a8Smistachkin static int SQLITE_TCLAPI test_finalize(
2114106bb236Sdanielk1977 void * clientData,
2115106bb236Sdanielk1977 Tcl_Interp *interp,
2116106bb236Sdanielk1977 int objc,
2117106bb236Sdanielk1977 Tcl_Obj *CONST objv[]
2118b86ccfb2Sdrh ){
2119106bb236Sdanielk1977 sqlite3_stmt *pStmt;
2120b86ccfb2Sdrh int rc;
2121dddb2f23Sdrh sqlite3 *db = 0;
2122106bb236Sdanielk1977
2123106bb236Sdanielk1977 if( objc!=2 ){
2124106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
2125106bb236Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
2126b86ccfb2Sdrh return TCL_ERROR;
2127b86ccfb2Sdrh }
2128106bb236Sdanielk1977
2129106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2130106bb236Sdanielk1977
21314397de57Sdanielk1977 if( pStmt ){
2132c60d0446Sdrh db = StmtToDb(pStmt);
21334397de57Sdanielk1977 }
2134fc57d7bfSdanielk1977 rc = sqlite3_finalize(pStmt);
21354f0c5878Sdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
21364397de57Sdanielk1977 if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
2137106bb236Sdanielk1977 return TCL_OK;
2138106bb236Sdanielk1977 }
2139106bb236Sdanielk1977
2140106bb236Sdanielk1977 /*
2141d1d38488Sdrh ** Usage: sqlite3_stmt_status STMT CODE RESETFLAG
2142d1d38488Sdrh **
2143d1d38488Sdrh ** Get the value of a status counter from a statement.
2144d1d38488Sdrh */
test_stmt_status(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])21457617e4a8Smistachkin static int SQLITE_TCLAPI test_stmt_status(
2146d1d38488Sdrh void * clientData,
2147d1d38488Sdrh Tcl_Interp *interp,
2148d1d38488Sdrh int objc,
2149d1d38488Sdrh Tcl_Obj *CONST objv[]
2150d1d38488Sdrh ){
2151d1d38488Sdrh int iValue;
215227b2f053Smistachkin int i, op = 0, resetFlag;
2153d1d38488Sdrh const char *zOpName;
2154d1d38488Sdrh sqlite3_stmt *pStmt;
2155d1d38488Sdrh
2156d1d38488Sdrh static const struct {
2157d1d38488Sdrh const char *zName;
2158d1d38488Sdrh int op;
2159d1d38488Sdrh } aOp[] = {
2160d1d38488Sdrh { "SQLITE_STMTSTATUS_FULLSCAN_STEP", SQLITE_STMTSTATUS_FULLSCAN_STEP },
2161d1d38488Sdrh { "SQLITE_STMTSTATUS_SORT", SQLITE_STMTSTATUS_SORT },
2162a21a64ddSdrh { "SQLITE_STMTSTATUS_AUTOINDEX", SQLITE_STMTSTATUS_AUTOINDEX },
2163bf159fa2Sdrh { "SQLITE_STMTSTATUS_VM_STEP", SQLITE_STMTSTATUS_VM_STEP },
216400d11d40Sdrh { "SQLITE_STMTSTATUS_REPREPARE", SQLITE_STMTSTATUS_REPREPARE },
216500d11d40Sdrh { "SQLITE_STMTSTATUS_RUN", SQLITE_STMTSTATUS_RUN },
216600d11d40Sdrh { "SQLITE_STMTSTATUS_MEMUSED", SQLITE_STMTSTATUS_MEMUSED },
2167d1d38488Sdrh };
2168d1d38488Sdrh if( objc!=4 ){
2169d1d38488Sdrh Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG");
2170d1d38488Sdrh return TCL_ERROR;
2171d1d38488Sdrh }
2172d1d38488Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2173d1d38488Sdrh zOpName = Tcl_GetString(objv[2]);
2174d1d38488Sdrh for(i=0; i<ArraySize(aOp); i++){
2175d1d38488Sdrh if( strcmp(aOp[i].zName, zOpName)==0 ){
2176d1d38488Sdrh op = aOp[i].op;
2177d1d38488Sdrh break;
2178d1d38488Sdrh }
2179d1d38488Sdrh }
2180d1d38488Sdrh if( i>=ArraySize(aOp) ){
2181d1d38488Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR;
2182d1d38488Sdrh }
2183d1d38488Sdrh if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR;
2184d1d38488Sdrh iValue = sqlite3_stmt_status(pStmt, op, resetFlag);
2185d1d38488Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(iValue));
2186d1d38488Sdrh return TCL_OK;
2187d1d38488Sdrh }
2188d1d38488Sdrh
218904489b6dSdan #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
219004489b6dSdan /*
219104489b6dSdan ** Usage: sqlite3_stmt_scanstatus STMT IDX
219204489b6dSdan */
test_stmt_scanstatus(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])21937617e4a8Smistachkin static int SQLITE_TCLAPI test_stmt_scanstatus(
219404489b6dSdan void * clientData,
219504489b6dSdan Tcl_Interp *interp,
219604489b6dSdan int objc,
219704489b6dSdan Tcl_Obj *CONST objv[]
219804489b6dSdan ){
219904489b6dSdan sqlite3_stmt *pStmt; /* First argument */
220004489b6dSdan int idx; /* Second argument */
220104489b6dSdan
220204489b6dSdan const char *zName;
220304489b6dSdan const char *zExplain;
220404489b6dSdan sqlite3_int64 nLoop;
220504489b6dSdan sqlite3_int64 nVisit;
2206518140edSdrh double rEst;
220704489b6dSdan int res;
220804489b6dSdan
220904489b6dSdan if( objc!=3 ){
221004489b6dSdan Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX");
221104489b6dSdan return TCL_ERROR;
221204489b6dSdan }
221304489b6dSdan if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
221404489b6dSdan if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
221504489b6dSdan
2216d1a1c234Sdrh res = sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop);
221704489b6dSdan if( res==0 ){
221804489b6dSdan Tcl_Obj *pRet = Tcl_NewObj();
221904489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nLoop", -1));
222004489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nLoop));
2221d1a1c234Sdrh sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
222204489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nVisit", -1));
222304489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nVisit));
2224518140edSdrh sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EST, (void*)&rEst);
222504489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nEst", -1));
2226518140edSdrh Tcl_ListObjAppendElement(0, pRet, Tcl_NewDoubleObj(rEst));
2227d1a1c234Sdrh sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NAME, (void*)&zName);
222804489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zName", -1));
222904489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zName, -1));
2230d1a1c234Sdrh sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
223104489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zExplain", -1));
223204489b6dSdan Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zExplain, -1));
223304489b6dSdan Tcl_SetObjResult(interp, pRet);
223404489b6dSdan }else{
223504489b6dSdan Tcl_ResetResult(interp);
223604489b6dSdan }
223704489b6dSdan return TCL_OK;
223804489b6dSdan }
223904489b6dSdan
224004489b6dSdan /*
224104489b6dSdan ** Usage: sqlite3_stmt_scanstatus_reset STMT
224204489b6dSdan */
test_stmt_scanstatus_reset(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])22437617e4a8Smistachkin static int SQLITE_TCLAPI test_stmt_scanstatus_reset(
224404489b6dSdan void * clientData,
224504489b6dSdan Tcl_Interp *interp,
224604489b6dSdan int objc,
224704489b6dSdan Tcl_Obj *CONST objv[]
224804489b6dSdan ){
224904489b6dSdan sqlite3_stmt *pStmt; /* First argument */
225004489b6dSdan if( objc!=2 ){
225104489b6dSdan Tcl_WrongNumArgs(interp, 1, objv, "STMT");
225204489b6dSdan return TCL_ERROR;
225304489b6dSdan }
225404489b6dSdan if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
225504489b6dSdan sqlite3_stmt_scanstatus_reset(pStmt);
225604489b6dSdan return TCL_OK;
225704489b6dSdan }
225804489b6dSdan #endif
225904489b6dSdan
2260d83f7ca1Sdan #ifdef SQLITE_ENABLE_SQLLOG
2261d83f7ca1Sdan /*
2262d83f7ca1Sdan ** Usage: sqlite3_config_sqllog
2263d83f7ca1Sdan **
2264d83f7ca1Sdan ** Zero the SQLITE_CONFIG_SQLLOG configuration
2265d83f7ca1Sdan */
test_config_sqllog(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])22667617e4a8Smistachkin static int SQLITE_TCLAPI test_config_sqllog(
2267d83f7ca1Sdan void * clientData,
2268d83f7ca1Sdan Tcl_Interp *interp,
2269d83f7ca1Sdan int objc,
2270d83f7ca1Sdan Tcl_Obj *CONST objv[]
2271d83f7ca1Sdan ){
2272d83f7ca1Sdan if( objc!=1 ){
2273d83f7ca1Sdan Tcl_WrongNumArgs(interp, 1, objv, "");
2274d83f7ca1Sdan return TCL_ERROR;
2275d83f7ca1Sdan }
2276d83f7ca1Sdan sqlite3_config(SQLITE_CONFIG_SQLLOG, 0, 0);
2277d83f7ca1Sdan return TCL_OK;
2278d83f7ca1Sdan }
2279d83f7ca1Sdan #endif
2280d83f7ca1Sdan
2281d1d38488Sdrh /*
22822e3a5a81Sdan ** Usage: sqlite3_config_sorterref
22832e3a5a81Sdan **
22842e3a5a81Sdan ** Set the SQLITE_CONFIG_SORTERREF_SIZE configuration option
22852e3a5a81Sdan */
test_config_sorterref(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])22862e3a5a81Sdan static int SQLITE_TCLAPI test_config_sorterref(
22872e3a5a81Sdan void * clientData,
22882e3a5a81Sdan Tcl_Interp *interp,
22892e3a5a81Sdan int objc,
22902e3a5a81Sdan Tcl_Obj *CONST objv[]
22912e3a5a81Sdan ){
22922e3a5a81Sdan int iVal;
22932e3a5a81Sdan if( objc!=2 ){
22942e3a5a81Sdan Tcl_WrongNumArgs(interp, 1, objv, "NBYTE");
22952e3a5a81Sdan return TCL_ERROR;
22962e3a5a81Sdan }
22972e3a5a81Sdan if( Tcl_GetIntFromObj(interp, objv[1], &iVal) ) return TCL_ERROR;
22982e3a5a81Sdan sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, iVal);
22992e3a5a81Sdan return TCL_OK;
23002e3a5a81Sdan }
23012e3a5a81Sdan
23022e3a5a81Sdan /*
2303e4e416e8Sdan ** Usage: vfs_current_time_int64
2304e4e416e8Sdan **
2305e4e416e8Sdan ** Return the value returned by the default VFS's xCurrentTimeInt64 method.
2306e4e416e8Sdan */
vfsCurrentTimeInt64(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])23077617e4a8Smistachkin static int SQLITE_TCLAPI vfsCurrentTimeInt64(
2308e4e416e8Sdan void * clientData,
2309e4e416e8Sdan Tcl_Interp *interp,
2310e4e416e8Sdan int objc,
2311e4e416e8Sdan Tcl_Obj *CONST objv[]
2312e4e416e8Sdan ){
2313e4e416e8Sdan i64 t;
2314e4e416e8Sdan sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
2315e4e416e8Sdan if( objc!=1 ){
2316e4e416e8Sdan Tcl_WrongNumArgs(interp, 1, objv, "");
2317e4e416e8Sdan return TCL_ERROR;
2318e4e416e8Sdan }
2319e4e416e8Sdan pVfs->xCurrentTimeInt64(pVfs, &t);
2320e4e416e8Sdan Tcl_SetObjResult(interp, Tcl_NewWideIntObj(t));
2321e4e416e8Sdan return TCL_OK;
2322e4e416e8Sdan }
2323e4e416e8Sdan
2324ee3b7a27Sdrh #ifdef SQLITE_ENABLE_SNAPSHOT
2325e4e416e8Sdan /*
2326fc1acf33Sdan ** Usage: sqlite3_snapshot_get DB DBNAME
2327fc1acf33Sdan */
test_snapshot_get(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])23287617e4a8Smistachkin static int SQLITE_TCLAPI test_snapshot_get(
2329fc1acf33Sdan void * clientData,
2330fc1acf33Sdan Tcl_Interp *interp,
2331fc1acf33Sdan int objc,
2332fc1acf33Sdan Tcl_Obj *CONST objv[]
2333fc1acf33Sdan ){
2334fc1acf33Sdan int rc;
2335fc1acf33Sdan sqlite3 *db;
2336fc1acf33Sdan char *zName;
2337fc1acf33Sdan sqlite3_snapshot *pSnapshot = 0;
2338fc1acf33Sdan
2339fc1acf33Sdan if( objc!=3 ){
2340fc1acf33Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
2341fc1acf33Sdan return TCL_ERROR;
2342fc1acf33Sdan }
2343fc1acf33Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2344fc1acf33Sdan zName = Tcl_GetString(objv[2]);
2345fc1acf33Sdan
2346fc1acf33Sdan rc = sqlite3_snapshot_get(db, zName, &pSnapshot);
2347fc1acf33Sdan if( rc!=SQLITE_OK ){
2348fc1acf33Sdan Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
2349fc1acf33Sdan return TCL_ERROR;
2350fc1acf33Sdan }else{
2351fc1acf33Sdan char zBuf[100];
2352fc1acf33Sdan if( sqlite3TestMakePointerStr(interp, zBuf, pSnapshot) ) return TCL_ERROR;
2353fc1acf33Sdan Tcl_SetObjResult(interp, Tcl_NewStringObj(zBuf, -1));
2354fc1acf33Sdan }
2355fc1acf33Sdan return TCL_OK;
2356fc1acf33Sdan }
2357ee3b7a27Sdrh #endif /* SQLITE_ENABLE_SNAPSHOT */
2358fc1acf33Sdan
2359ee3b7a27Sdrh #ifdef SQLITE_ENABLE_SNAPSHOT
2360fc1acf33Sdan /*
23611158498dSdan ** Usage: sqlite3_snapshot_recover DB DBNAME
23621158498dSdan */
test_snapshot_recover(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])23631158498dSdan static int SQLITE_TCLAPI test_snapshot_recover(
23641158498dSdan void * clientData,
23651158498dSdan Tcl_Interp *interp,
23661158498dSdan int objc,
23671158498dSdan Tcl_Obj *CONST objv[]
23681158498dSdan ){
23691158498dSdan int rc;
23701158498dSdan sqlite3 *db;
23711158498dSdan char *zName;
23721158498dSdan
23731158498dSdan if( objc!=3 ){
23741158498dSdan Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
23751158498dSdan return TCL_ERROR;
23761158498dSdan }
23771158498dSdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
23781158498dSdan zName = Tcl_GetString(objv[2]);
23791158498dSdan
23801158498dSdan rc = sqlite3_snapshot_recover(db, zName);
23811158498dSdan if( rc!=SQLITE_OK ){
23821158498dSdan Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
23831158498dSdan return TCL_ERROR;
23841158498dSdan }else{
23851158498dSdan Tcl_ResetResult(interp);
23861158498dSdan }
23871158498dSdan return TCL_OK;
23881158498dSdan }
23891158498dSdan #endif /* SQLITE_ENABLE_SNAPSHOT */
23901158498dSdan
23911158498dSdan #ifdef SQLITE_ENABLE_SNAPSHOT
23921158498dSdan /*
2393fc1acf33Sdan ** Usage: sqlite3_snapshot_open DB DBNAME SNAPSHOT
2394fc1acf33Sdan */
test_snapshot_open(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])23957617e4a8Smistachkin static int SQLITE_TCLAPI test_snapshot_open(
2396fc1acf33Sdan void * clientData,
2397fc1acf33Sdan Tcl_Interp *interp,
2398fc1acf33Sdan int objc,
2399fc1acf33Sdan Tcl_Obj *CONST objv[]
2400fc1acf33Sdan ){
2401fc1acf33Sdan int rc;
2402fc1acf33Sdan sqlite3 *db;
2403fc1acf33Sdan char *zName;
2404fc1acf33Sdan sqlite3_snapshot *pSnapshot;
2405fc1acf33Sdan
2406fc1acf33Sdan if( objc!=4 ){
2407fc1acf33Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SNAPSHOT");
2408fc1acf33Sdan return TCL_ERROR;
2409fc1acf33Sdan }
2410fc1acf33Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2411fc1acf33Sdan zName = Tcl_GetString(objv[2]);
2412fc1acf33Sdan pSnapshot = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[3]));
2413fc1acf33Sdan
2414fc1acf33Sdan rc = sqlite3_snapshot_open(db, zName, pSnapshot);
2415fc1acf33Sdan if( rc!=SQLITE_OK ){
2416fc1acf33Sdan Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
2417fc1acf33Sdan return TCL_ERROR;
2418fa3d4c19Sdan }else{
2419fa3d4c19Sdan Tcl_ResetResult(interp);
2420fc1acf33Sdan }
2421fc1acf33Sdan return TCL_OK;
2422fc1acf33Sdan }
2423ee3b7a27Sdrh #endif /* SQLITE_ENABLE_SNAPSHOT */
2424fc1acf33Sdan
2425ee3b7a27Sdrh #ifdef SQLITE_ENABLE_SNAPSHOT
2426fc1acf33Sdan /*
2427fc1acf33Sdan ** Usage: sqlite3_snapshot_free SNAPSHOT
2428fc1acf33Sdan */
test_snapshot_free(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])24297617e4a8Smistachkin static int SQLITE_TCLAPI test_snapshot_free(
2430fc1acf33Sdan void * clientData,
2431fc1acf33Sdan Tcl_Interp *interp,
2432fc1acf33Sdan int objc,
2433fc1acf33Sdan Tcl_Obj *CONST objv[]
2434fc1acf33Sdan ){
2435fc1acf33Sdan sqlite3_snapshot *pSnapshot;
2436fc1acf33Sdan if( objc!=2 ){
2437fc1acf33Sdan Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT");
2438fc1acf33Sdan return TCL_ERROR;
2439fc1acf33Sdan }
2440fc1acf33Sdan pSnapshot = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
2441fc1acf33Sdan sqlite3_snapshot_free(pSnapshot);
2442fc1acf33Sdan return TCL_OK;
2443fc1acf33Sdan }
2444ee3b7a27Sdrh #endif /* SQLITE_ENABLE_SNAPSHOT */
2445fc1acf33Sdan
2446ad2d5bafSdan #ifdef SQLITE_ENABLE_SNAPSHOT
2447ad2d5bafSdan /*
2448ad2d5bafSdan ** Usage: sqlite3_snapshot_cmp SNAPSHOT1 SNAPSHOT2
2449ad2d5bafSdan */
test_snapshot_cmp(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])24507617e4a8Smistachkin static int SQLITE_TCLAPI test_snapshot_cmp(
2451ad2d5bafSdan void * clientData,
2452ad2d5bafSdan Tcl_Interp *interp,
2453ad2d5bafSdan int objc,
2454ad2d5bafSdan Tcl_Obj *CONST objv[]
2455ad2d5bafSdan ){
2456ad2d5bafSdan int res;
2457ad2d5bafSdan sqlite3_snapshot *p1;
2458ad2d5bafSdan sqlite3_snapshot *p2;
2459ad2d5bafSdan if( objc!=3 ){
2460ad2d5bafSdan Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT1 SNAPSHOT2");
2461ad2d5bafSdan return TCL_ERROR;
2462ad2d5bafSdan }
2463ad2d5bafSdan p1 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
2464ad2d5bafSdan p2 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[2]));
2465ad2d5bafSdan res = sqlite3_snapshot_cmp(p1, p2);
2466ad2d5bafSdan Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
2467ad2d5bafSdan return TCL_OK;
2468ad2d5bafSdan }
2469ad2d5bafSdan #endif /* SQLITE_ENABLE_SNAPSHOT */
2470ad2d5bafSdan
247125accbcaSdan #ifdef SQLITE_ENABLE_SNAPSHOT
247225accbcaSdan /*
247325accbcaSdan ** Usage: sqlite3_snapshot_get_blob DB DBNAME
247425accbcaSdan */
test_snapshot_get_blob(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])247525accbcaSdan static int SQLITE_TCLAPI test_snapshot_get_blob(
247625accbcaSdan void * clientData,
247725accbcaSdan Tcl_Interp *interp,
247825accbcaSdan int objc,
247925accbcaSdan Tcl_Obj *CONST objv[]
248025accbcaSdan ){
248125accbcaSdan int rc;
248225accbcaSdan sqlite3 *db;
248325accbcaSdan char *zName;
248425accbcaSdan sqlite3_snapshot *pSnapshot = 0;
248525accbcaSdan
248625accbcaSdan if( objc!=3 ){
248725accbcaSdan Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
248825accbcaSdan return TCL_ERROR;
248925accbcaSdan }
249025accbcaSdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
249125accbcaSdan zName = Tcl_GetString(objv[2]);
249225accbcaSdan
249325accbcaSdan rc = sqlite3_snapshot_get(db, zName, &pSnapshot);
249425accbcaSdan if( rc!=SQLITE_OK ){
249525accbcaSdan Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
249625accbcaSdan return TCL_ERROR;
249725accbcaSdan }else{
249825accbcaSdan Tcl_SetObjResult(interp,
249925accbcaSdan Tcl_NewByteArrayObj((unsigned char*)pSnapshot, sizeof(sqlite3_snapshot))
250025accbcaSdan );
250125accbcaSdan sqlite3_snapshot_free(pSnapshot);
250225accbcaSdan }
250325accbcaSdan return TCL_OK;
250425accbcaSdan }
250525accbcaSdan #endif /* SQLITE_ENABLE_SNAPSHOT */
250625accbcaSdan
250725accbcaSdan #ifdef SQLITE_ENABLE_SNAPSHOT
250825accbcaSdan /*
250925accbcaSdan ** Usage: sqlite3_snapshot_open_blob DB DBNAME SNAPSHOT
251025accbcaSdan */
test_snapshot_open_blob(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])251125accbcaSdan static int SQLITE_TCLAPI test_snapshot_open_blob(
251225accbcaSdan void * clientData,
251325accbcaSdan Tcl_Interp *interp,
251425accbcaSdan int objc,
251525accbcaSdan Tcl_Obj *CONST objv[]
251625accbcaSdan ){
251725accbcaSdan int rc;
251825accbcaSdan sqlite3 *db;
251925accbcaSdan char *zName;
252025accbcaSdan unsigned char *pBlob;
252125accbcaSdan int nBlob;
252225accbcaSdan
252325accbcaSdan if( objc!=4 ){
252425accbcaSdan Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SNAPSHOT");
252525accbcaSdan return TCL_ERROR;
252625accbcaSdan }
252725accbcaSdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
252825accbcaSdan zName = Tcl_GetString(objv[2]);
252925accbcaSdan pBlob = Tcl_GetByteArrayFromObj(objv[3], &nBlob);
253025accbcaSdan if( nBlob!=sizeof(sqlite3_snapshot) ){
253125accbcaSdan Tcl_AppendResult(interp, "bad SNAPSHOT", 0);
253225accbcaSdan return TCL_ERROR;
253325accbcaSdan }
253425accbcaSdan rc = sqlite3_snapshot_open(db, zName, (sqlite3_snapshot*)pBlob);
253525accbcaSdan if( rc!=SQLITE_OK ){
253625accbcaSdan Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
253725accbcaSdan return TCL_ERROR;
253825accbcaSdan }
253925accbcaSdan return TCL_OK;
254025accbcaSdan }
254125accbcaSdan #endif /* SQLITE_ENABLE_SNAPSHOT */
254225accbcaSdan
254325accbcaSdan #ifdef SQLITE_ENABLE_SNAPSHOT
254425accbcaSdan /*
254525accbcaSdan ** Usage: sqlite3_snapshot_cmp_blob SNAPSHOT1 SNAPSHOT2
254625accbcaSdan */
test_snapshot_cmp_blob(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])254725accbcaSdan static int SQLITE_TCLAPI test_snapshot_cmp_blob(
254825accbcaSdan void * clientData,
254925accbcaSdan Tcl_Interp *interp,
255025accbcaSdan int objc,
255125accbcaSdan Tcl_Obj *CONST objv[]
255225accbcaSdan ){
255325accbcaSdan int res;
255425accbcaSdan unsigned char *p1;
255525accbcaSdan unsigned char *p2;
255625accbcaSdan int n1;
255725accbcaSdan int n2;
255825accbcaSdan
255925accbcaSdan if( objc!=3 ){
256025accbcaSdan Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT1 SNAPSHOT2");
256125accbcaSdan return TCL_ERROR;
256225accbcaSdan }
256325accbcaSdan
256425accbcaSdan p1 = Tcl_GetByteArrayFromObj(objv[1], &n1);
256525accbcaSdan p2 = Tcl_GetByteArrayFromObj(objv[2], &n2);
256625accbcaSdan
256725accbcaSdan if( n1!=sizeof(sqlite3_snapshot) || n1!=n2 ){
256825accbcaSdan Tcl_AppendResult(interp, "bad SNAPSHOT", 0);
256925accbcaSdan return TCL_ERROR;
257025accbcaSdan }
257125accbcaSdan
257225accbcaSdan res = sqlite3_snapshot_cmp((sqlite3_snapshot*)p1, (sqlite3_snapshot*)p2);
257325accbcaSdan Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
257425accbcaSdan return TCL_OK;
257525accbcaSdan }
257625accbcaSdan #endif /* SQLITE_ENABLE_SNAPSHOT */
257725accbcaSdan
2578fc1acf33Sdan /*
2579000f95b1Sdan ** Usage: sqlite3_delete_database FILENAME
2580000f95b1Sdan */
2581000f95b1Sdan int sqlite3_delete_database(const char*); /* in test_delete.c */
test_delete_database(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])2582000f95b1Sdan static int SQLITE_TCLAPI test_delete_database(
2583000f95b1Sdan void * clientData,
2584000f95b1Sdan Tcl_Interp *interp,
2585000f95b1Sdan int objc,
2586000f95b1Sdan Tcl_Obj *CONST objv[]
2587000f95b1Sdan ){
2588000f95b1Sdan int rc;
2589000f95b1Sdan const char *zFile;
2590000f95b1Sdan if( objc!=2 ){
2591000f95b1Sdan Tcl_WrongNumArgs(interp, 1, objv, "FILE");
2592000f95b1Sdan return TCL_ERROR;
2593000f95b1Sdan }
2594000f95b1Sdan zFile = (const char*)Tcl_GetString(objv[1]);
2595000f95b1Sdan rc = sqlite3_delete_database(zFile);
2596000f95b1Sdan
2597000f95b1Sdan Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
2598000f95b1Sdan return TCL_OK;
2599000f95b1Sdan }
2600000f95b1Sdan
2601000f95b1Sdan /*
26024da30f88Sdan ** Usage: atomic_batch_write PATH
26034da30f88Sdan */
test_atomic_batch_write(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])26044da30f88Sdan static int SQLITE_TCLAPI test_atomic_batch_write(
26054da30f88Sdan void * clientData,
26064da30f88Sdan Tcl_Interp *interp,
26074da30f88Sdan int objc,
26084da30f88Sdan Tcl_Obj *CONST objv[]
26094da30f88Sdan ){
26104da30f88Sdan char *zFile = 0; /* Path to file to test */
26114da30f88Sdan sqlite3 *db = 0; /* Database handle */
26124da30f88Sdan sqlite3_file *pFd = 0; /* SQLite fd open on zFile */
26134da30f88Sdan int bRes = 0; /* Integer result of this command */
26144da30f88Sdan int dc = 0; /* Device-characteristics mask */
26154da30f88Sdan int rc; /* sqlite3_open() return code */
26164da30f88Sdan
26174da30f88Sdan if( objc!=2 ){
26184da30f88Sdan Tcl_WrongNumArgs(interp, 1, objv, "PATH");
26194da30f88Sdan return TCL_ERROR;
26204da30f88Sdan }
26214da30f88Sdan zFile = Tcl_GetString(objv[1]);
26224da30f88Sdan
26234da30f88Sdan rc = sqlite3_open(zFile, &db);
26244da30f88Sdan if( rc!=SQLITE_OK ){
26254da30f88Sdan Tcl_AppendResult(interp, sqlite3_errmsg(db), 0);
26264da30f88Sdan sqlite3_close(db);
26274da30f88Sdan return TCL_ERROR;
26284da30f88Sdan }
26294da30f88Sdan
26304da30f88Sdan rc = sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, (void*)&pFd);
26314da30f88Sdan dc = pFd->pMethods->xDeviceCharacteristics(pFd);
26324da30f88Sdan if( dc & SQLITE_IOCAP_BATCH_ATOMIC ){
26334da30f88Sdan bRes = 1;
26344da30f88Sdan }
26354da30f88Sdan
26364da30f88Sdan Tcl_SetObjResult(interp, Tcl_NewIntObj(bRes));
26374da30f88Sdan sqlite3_close(db);
26384da30f88Sdan return TCL_OK;
26394da30f88Sdan }
26404da30f88Sdan
26414da30f88Sdan /*
2642bb5a9c3eSdrh ** Usage: sqlite3_next_stmt DB STMT
2643bb5a9c3eSdrh **
2644bb5a9c3eSdrh ** Return the next statment in sequence after STMT.
2645bb5a9c3eSdrh */
test_next_stmt(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])26467617e4a8Smistachkin static int SQLITE_TCLAPI test_next_stmt(
2647bb5a9c3eSdrh void * clientData,
2648bb5a9c3eSdrh Tcl_Interp *interp,
2649bb5a9c3eSdrh int objc,
2650bb5a9c3eSdrh Tcl_Obj *CONST objv[]
2651bb5a9c3eSdrh ){
2652bb5a9c3eSdrh sqlite3_stmt *pStmt;
2653bb5a9c3eSdrh sqlite3 *db = 0;
2654bb5a9c3eSdrh char zBuf[50];
2655bb5a9c3eSdrh
2656bb5a9c3eSdrh if( objc!=3 ){
2657bb5a9c3eSdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
2658bb5a9c3eSdrh Tcl_GetStringFromObj(objv[0], 0), " DB STMT", 0);
2659bb5a9c3eSdrh return TCL_ERROR;
2660bb5a9c3eSdrh }
2661bb5a9c3eSdrh
2662bb5a9c3eSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2663bb5a9c3eSdrh if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt) ) return TCL_ERROR;
2664bb5a9c3eSdrh pStmt = sqlite3_next_stmt(db, pStmt);
2665bb5a9c3eSdrh if( pStmt ){
2666bb5a9c3eSdrh if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
2667bb5a9c3eSdrh Tcl_AppendResult(interp, zBuf, 0);
2668bb5a9c3eSdrh }
2669bb5a9c3eSdrh return TCL_OK;
2670bb5a9c3eSdrh }
2671bb5a9c3eSdrh
2672f03d9cccSdrh /*
2673f03d9cccSdrh ** Usage: sqlite3_stmt_readonly STMT
2674f03d9cccSdrh **
2675f03d9cccSdrh ** Return true if STMT is a NULL pointer or a pointer to a statement
2676f03d9cccSdrh ** that is guaranteed to leave the database unmodified.
2677f03d9cccSdrh */
test_stmt_readonly(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])26787617e4a8Smistachkin static int SQLITE_TCLAPI test_stmt_readonly(
2679f03d9cccSdrh void * clientData,
2680f03d9cccSdrh Tcl_Interp *interp,
2681f03d9cccSdrh int objc,
2682f03d9cccSdrh Tcl_Obj *CONST objv[]
2683f03d9cccSdrh ){
2684f03d9cccSdrh sqlite3_stmt *pStmt;
2685f03d9cccSdrh int rc;
2686f03d9cccSdrh
2687f03d9cccSdrh if( objc!=2 ){
2688f03d9cccSdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
2689f03d9cccSdrh Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
2690f03d9cccSdrh return TCL_ERROR;
2691f03d9cccSdrh }
2692f03d9cccSdrh
2693f03d9cccSdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2694f03d9cccSdrh rc = sqlite3_stmt_readonly(pStmt);
2695f03d9cccSdrh Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
2696f03d9cccSdrh return TCL_OK;
2697f03d9cccSdrh }
2698f03d9cccSdrh
2699d9495cd0Sdan /*
270039c5c4aeSdrh ** Usage: sqlite3_stmt_isexplain STMT
270139c5c4aeSdrh **
270239c5c4aeSdrh ** Return 1, 2, or 0 respectively if STMT is an EXPLAIN statement, an
270339c5c4aeSdrh ** EXPLAIN QUERY PLAN statement or an ordinary statement or NULL pointer.
270439c5c4aeSdrh */
test_stmt_isexplain(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])270539c5c4aeSdrh static int SQLITE_TCLAPI test_stmt_isexplain(
270639c5c4aeSdrh void * clientData,
270739c5c4aeSdrh Tcl_Interp *interp,
270839c5c4aeSdrh int objc,
270939c5c4aeSdrh Tcl_Obj *CONST objv[]
271039c5c4aeSdrh ){
271139c5c4aeSdrh sqlite3_stmt *pStmt;
271239c5c4aeSdrh int rc;
271339c5c4aeSdrh
271439c5c4aeSdrh if( objc!=2 ){
271539c5c4aeSdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
271639c5c4aeSdrh Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
271739c5c4aeSdrh return TCL_ERROR;
271839c5c4aeSdrh }
271939c5c4aeSdrh
272039c5c4aeSdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
272139c5c4aeSdrh rc = sqlite3_stmt_isexplain(pStmt);
272239c5c4aeSdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
272339c5c4aeSdrh return TCL_OK;
272439c5c4aeSdrh }
272539c5c4aeSdrh
272639c5c4aeSdrh /*
27272fb6693eSdrh ** Usage: sqlite3_stmt_busy STMT
27282fb6693eSdrh **
27292fb6693eSdrh ** Return true if STMT is a non-NULL pointer to a statement
27302fb6693eSdrh ** that has been stepped but not to completion.
27312fb6693eSdrh */
test_stmt_busy(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])27327617e4a8Smistachkin static int SQLITE_TCLAPI test_stmt_busy(
27332fb6693eSdrh void * clientData,
27342fb6693eSdrh Tcl_Interp *interp,
27352fb6693eSdrh int objc,
27362fb6693eSdrh Tcl_Obj *CONST objv[]
27372fb6693eSdrh ){
27382fb6693eSdrh sqlite3_stmt *pStmt;
27392fb6693eSdrh int rc;
27402fb6693eSdrh
27412fb6693eSdrh if( objc!=2 ){
27422fb6693eSdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
27432fb6693eSdrh Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
27442fb6693eSdrh return TCL_ERROR;
27452fb6693eSdrh }
27462fb6693eSdrh
27472fb6693eSdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
27482fb6693eSdrh rc = sqlite3_stmt_busy(pStmt);
27492fb6693eSdrh Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
27502fb6693eSdrh return TCL_OK;
27512fb6693eSdrh }
27522fb6693eSdrh
27532fb6693eSdrh /*
2754d9495cd0Sdan ** Usage: uses_stmt_journal STMT
2755d9495cd0Sdan **
2756d9495cd0Sdan ** Return true if STMT uses a statement journal.
2757d9495cd0Sdan */
uses_stmt_journal(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])27587617e4a8Smistachkin static int SQLITE_TCLAPI uses_stmt_journal(
2759d9495cd0Sdan void * clientData,
2760d9495cd0Sdan Tcl_Interp *interp,
2761d9495cd0Sdan int objc,
2762d9495cd0Sdan Tcl_Obj *CONST objv[]
2763d9495cd0Sdan ){
2764d9495cd0Sdan sqlite3_stmt *pStmt;
2765d9495cd0Sdan
2766d9495cd0Sdan if( objc!=2 ){
2767d9495cd0Sdan Tcl_AppendResult(interp, "wrong # args: should be \"",
2768d9495cd0Sdan Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
2769d9495cd0Sdan return TCL_ERROR;
2770d9495cd0Sdan }
2771d9495cd0Sdan
2772d9495cd0Sdan if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2773caffb1a5Sdrh sqlite3_stmt_readonly(pStmt);
2774d9495cd0Sdan Tcl_SetObjResult(interp, Tcl_NewBooleanObj(((Vdbe *)pStmt)->usesStmtJournal));
2775d9495cd0Sdan return TCL_OK;
2776d9495cd0Sdan }
2777d9495cd0Sdan
2778bb5a9c3eSdrh
2779bb5a9c3eSdrh /*
2780106bb236Sdanielk1977 ** Usage: sqlite3_reset STMT
2781106bb236Sdanielk1977 **
2782261919ccSdanielk1977 ** Reset a statement handle.
2783106bb236Sdanielk1977 */
test_reset(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])27847617e4a8Smistachkin static int SQLITE_TCLAPI test_reset(
2785106bb236Sdanielk1977 void * clientData,
2786106bb236Sdanielk1977 Tcl_Interp *interp,
2787106bb236Sdanielk1977 int objc,
2788106bb236Sdanielk1977 Tcl_Obj *CONST objv[]
2789106bb236Sdanielk1977 ){
2790106bb236Sdanielk1977 sqlite3_stmt *pStmt;
2791106bb236Sdanielk1977 int rc;
2792106bb236Sdanielk1977
2793106bb236Sdanielk1977 if( objc!=2 ){
2794106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
2795106bb236Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
2796106bb236Sdanielk1977 return TCL_ERROR;
2797106bb236Sdanielk1977 }
2798106bb236Sdanielk1977
2799106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2800106bb236Sdanielk1977
2801fc57d7bfSdanielk1977 rc = sqlite3_reset(pStmt);
2802261919ccSdanielk1977 if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){
2803261919ccSdanielk1977 return TCL_ERROR;
2804261919ccSdanielk1977 }
28054f0c5878Sdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
2806261919ccSdanielk1977 /*
2807106bb236Sdanielk1977 if( rc ){
2808b86ccfb2Sdrh return TCL_ERROR;
2809b86ccfb2Sdrh }
2810261919ccSdanielk1977 */
2811b86ccfb2Sdrh return TCL_OK;
2812b86ccfb2Sdrh }
2813b86ccfb2Sdrh
28145a38705eSdrh /*
2815d89bd007Sdrh ** Usage: sqlite3_expired STMT
2816d89bd007Sdrh **
2817d89bd007Sdrh ** Return TRUE if a recompilation of the statement is recommended.
2818d89bd007Sdrh */
test_expired(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])28197617e4a8Smistachkin static int SQLITE_TCLAPI test_expired(
2820d89bd007Sdrh void * clientData,
2821d89bd007Sdrh Tcl_Interp *interp,
2822d89bd007Sdrh int objc,
2823d89bd007Sdrh Tcl_Obj *CONST objv[]
2824d89bd007Sdrh ){
2825eec556d3Sshane #ifndef SQLITE_OMIT_DEPRECATED
2826d89bd007Sdrh sqlite3_stmt *pStmt;
2827d89bd007Sdrh if( objc!=2 ){
2828d89bd007Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
2829d89bd007Sdrh Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
2830d89bd007Sdrh return TCL_ERROR;
2831d89bd007Sdrh }
2832d89bd007Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2833d89bd007Sdrh Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt)));
2834eec556d3Sshane #endif
2835d89bd007Sdrh return TCL_OK;
2836d89bd007Sdrh }
2837d89bd007Sdrh
2838d89bd007Sdrh /*
2839f8db1bc0Sdrh ** Usage: sqlite3_transfer_bindings FROMSTMT TOSTMT
2840f8db1bc0Sdrh **
2841f8db1bc0Sdrh ** Transfer all bindings from FROMSTMT over to TOSTMT
2842f8db1bc0Sdrh */
test_transfer_bind(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])28437617e4a8Smistachkin static int SQLITE_TCLAPI test_transfer_bind(
2844f8db1bc0Sdrh void * clientData,
2845f8db1bc0Sdrh Tcl_Interp *interp,
2846f8db1bc0Sdrh int objc,
2847f8db1bc0Sdrh Tcl_Obj *CONST objv[]
2848f8db1bc0Sdrh ){
2849eec556d3Sshane #ifndef SQLITE_OMIT_DEPRECATED
2850f8db1bc0Sdrh sqlite3_stmt *pStmt1, *pStmt2;
2851f8db1bc0Sdrh if( objc!=3 ){
2852f8db1bc0Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
2853f8db1bc0Sdrh Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0);
2854f8db1bc0Sdrh return TCL_ERROR;
2855f8db1bc0Sdrh }
2856f8db1bc0Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR;
2857f8db1bc0Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR;
2858f8db1bc0Sdrh Tcl_SetObjResult(interp,
2859f8db1bc0Sdrh Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2)));
2860eec556d3Sshane #endif
2861f8db1bc0Sdrh return TCL_OK;
2862f8db1bc0Sdrh }
2863f8db1bc0Sdrh
2864f8db1bc0Sdrh /*
2865fbcd585fSdanielk1977 ** Usage: sqlite3_changes DB
286650457896Sdrh **
2867fbcd585fSdanielk1977 ** Return the number of changes made to the database by the last SQL
2868fbcd585fSdanielk1977 ** execution.
286950457896Sdrh */
test_changes(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])28707617e4a8Smistachkin static int SQLITE_TCLAPI test_changes(
2871fbcd585fSdanielk1977 void * clientData,
2872fbcd585fSdanielk1977 Tcl_Interp *interp,
2873fbcd585fSdanielk1977 int objc,
2874fbcd585fSdanielk1977 Tcl_Obj *CONST objv[]
2875fbcd585fSdanielk1977 ){
2876fbcd585fSdanielk1977 sqlite3 *db;
2877fbcd585fSdanielk1977 if( objc!=2 ){
2878fbcd585fSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
2879fbcd585fSdanielk1977 Tcl_GetString(objv[0]), " DB", 0);
2880fbcd585fSdanielk1977 return TCL_ERROR;
2881fbcd585fSdanielk1977 }
2882fbcd585fSdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2883fbcd585fSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
2884fbcd585fSdanielk1977 return TCL_OK;
2885fbcd585fSdanielk1977 }
288650457896Sdrh
288750457896Sdrh /*
28887c972decSdrh ** This is the "static_bind_value" that variables are bound to when
28896f8a503dSdanielk1977 ** the FLAG option of sqlite3_bind is "static"
289050457896Sdrh */
28917c972decSdrh static char *sqlite_static_bind_value = 0;
2892f0313813Sdrh static int sqlite_static_bind_nbyte = 0;
28937c972decSdrh
28947c972decSdrh /*
28956f8a503dSdanielk1977 ** Usage: sqlite3_bind VM IDX VALUE FLAGS
28967c972decSdrh **
2897f7b5496eSdrh ** Sets the value of the IDX-th occurrence of "?" in the original SQL
28987c972decSdrh ** string. VALUE is the new value. If FLAGS=="null" then VALUE is
28997c972decSdrh ** ignored and the value is set to NULL. If FLAGS=="static" then
29007c972decSdrh ** the value is set to the value of a static variable named
29017c972decSdrh ** "sqlite_static_bind_value". If FLAGS=="normal" then a copy
2902bf8aa2a6Sdrh ** of the VALUE is made. If FLAGS=="blob10" then a VALUE is ignored
2903bf8aa2a6Sdrh ** an a 10-byte blob "abc\000xyz\000pq" is inserted.
29047c972decSdrh */
test_bind(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)29057617e4a8Smistachkin static int SQLITE_TCLAPI test_bind(
290650457896Sdrh void *NotUsed,
290750457896Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
290850457896Sdrh int argc, /* Number of arguments */
290950457896Sdrh char **argv /* Text of each argument */
291050457896Sdrh ){
2911fc57d7bfSdanielk1977 sqlite3_stmt *pStmt;
291250457896Sdrh int rc;
29137c972decSdrh int idx;
29147c972decSdrh if( argc!=5 ){
291550457896Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
29167c972decSdrh " VM IDX VALUE (null|static|normal)\"", 0);
291750457896Sdrh return TCL_ERROR;
291850457896Sdrh }
2919fc57d7bfSdanielk1977 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
29207c972decSdrh if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
29217c972decSdrh if( strcmp(argv[4],"null")==0 ){
2922fc57d7bfSdanielk1977 rc = sqlite3_bind_null(pStmt, idx);
29237c972decSdrh }else if( strcmp(argv[4],"static")==0 ){
2924fc57d7bfSdanielk1977 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
2925f0313813Sdrh }else if( strcmp(argv[4],"static-nbytes")==0 ){
2926f0313813Sdrh rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value,
2927f0313813Sdrh sqlite_static_bind_nbyte, 0);
29287c972decSdrh }else if( strcmp(argv[4],"normal")==0 ){
2929d8123366Sdanielk1977 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
2930bf8aa2a6Sdrh }else if( strcmp(argv[4],"blob10")==0 ){
2931bf8aa2a6Sdrh rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC);
29327c972decSdrh }else{
29337c972decSdrh Tcl_AppendResult(interp, "4th argument should be "
29347c972decSdrh "\"null\" or \"static\" or \"normal\"", 0);
29357c972decSdrh return TCL_ERROR;
29367c972decSdrh }
2937c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
293850457896Sdrh if( rc ){
293950457896Sdrh char zBuf[50];
294065545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
2941f20b21c8Sdanielk1977 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
294250457896Sdrh return TCL_ERROR;
294350457896Sdrh }
294450457896Sdrh return TCL_OK;
294550457896Sdrh }
294650457896Sdrh
29475436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
29484e6af134Sdanielk1977 /*
29494e6af134Sdanielk1977 ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
29504e6af134Sdanielk1977 **
29514e6af134Sdanielk1977 ** This function is used to test that SQLite selects the correct collation
29524e6af134Sdanielk1977 ** sequence callback when multiple versions (for different text encodings)
29534e6af134Sdanielk1977 ** are available.
29544e6af134Sdanielk1977 **
29554e6af134Sdanielk1977 ** Calling this routine registers the collation sequence "test_collate"
29564e6af134Sdanielk1977 ** with database handle <db>. The second argument must be a list of three
29574e6af134Sdanielk1977 ** boolean values. If the first is true, then a version of test_collate is
29584e6af134Sdanielk1977 ** registered for UTF-8, if the second is true, a version is registered for
29594e6af134Sdanielk1977 ** UTF-16le, if the third is true, a UTF-16be version is available.
29604e6af134Sdanielk1977 ** Previous versions of test_collate are deleted.
29614e6af134Sdanielk1977 **
29624e6af134Sdanielk1977 ** The collation sequence test_collate is implemented by calling the
29634e6af134Sdanielk1977 ** following TCL script:
29644e6af134Sdanielk1977 **
29654e6af134Sdanielk1977 ** "test_collate <enc> <lhs> <rhs>"
29664e6af134Sdanielk1977 **
29674e6af134Sdanielk1977 ** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
29684e6af134Sdanielk1977 ** The <enc> parameter is the encoding of the collation function that
29694e6af134Sdanielk1977 ** SQLite selected to call. The TCL test script implements the
29704e6af134Sdanielk1977 ** "test_collate" proc.
29714e6af134Sdanielk1977 **
297260ec914cSpeter.d.reid ** Note that this will only work with one interpreter at a time, as the
29734e6af134Sdanielk1977 ** interp pointer to use when evaluating the TCL script is stored in
29744e6af134Sdanielk1977 ** pTestCollateInterp.
29754e6af134Sdanielk1977 */
29764e6af134Sdanielk1977 static Tcl_Interp* pTestCollateInterp;
test_collate_func(void * pCtx,int nA,const void * zA,int nB,const void * zB)29774e6af134Sdanielk1977 static int test_collate_func(
29784e6af134Sdanielk1977 void *pCtx,
29794e6af134Sdanielk1977 int nA, const void *zA,
29804e6af134Sdanielk1977 int nB, const void *zB
29814e6af134Sdanielk1977 ){
29824e6af134Sdanielk1977 Tcl_Interp *i = pTestCollateInterp;
2983d2199f0fSdan int encin = SQLITE_PTR_TO_INT(pCtx);
29844e6af134Sdanielk1977 int res;
29854db38a70Sdrh int n;
29864e6af134Sdanielk1977
29874e6af134Sdanielk1977 sqlite3_value *pVal;
29884e6af134Sdanielk1977 Tcl_Obj *pX;
29894e6af134Sdanielk1977
29904e6af134Sdanielk1977 pX = Tcl_NewStringObj("test_collate", -1);
29914e6af134Sdanielk1977 Tcl_IncrRefCount(pX);
29924e6af134Sdanielk1977
29934e6af134Sdanielk1977 switch( encin ){
29944e6af134Sdanielk1977 case SQLITE_UTF8:
29954e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
29964e6af134Sdanielk1977 break;
29974e6af134Sdanielk1977 case SQLITE_UTF16LE:
29984e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
29994e6af134Sdanielk1977 break;
30004e6af134Sdanielk1977 case SQLITE_UTF16BE:
30014e6af134Sdanielk1977 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
30024e6af134Sdanielk1977 break;
30034e6af134Sdanielk1977 default:
30044e6af134Sdanielk1977 assert(0);
30054e6af134Sdanielk1977 }
30064e6af134Sdanielk1977
300702fa4696Sdan sqlite3BeginBenignMalloc();
30081e536953Sdanielk1977 pVal = sqlite3ValueNew(0);
300902fa4696Sdan if( pVal ){
3010b21c8cd4Sdrh sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
30114db38a70Sdrh n = sqlite3_value_bytes(pVal);
301203d847eaSdrh Tcl_ListObjAppendElement(i,pX,
301303d847eaSdrh Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
3014b21c8cd4Sdrh sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
30154db38a70Sdrh n = sqlite3_value_bytes(pVal);
301603d847eaSdrh Tcl_ListObjAppendElement(i,pX,
301703d847eaSdrh Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
30184e6af134Sdanielk1977 sqlite3ValueFree(pVal);
301902fa4696Sdan }
302002fa4696Sdan sqlite3EndBenignMalloc();
30214e6af134Sdanielk1977
30224e6af134Sdanielk1977 Tcl_EvalObjEx(i, pX, 0);
30234e6af134Sdanielk1977 Tcl_DecrRefCount(pX);
30244e6af134Sdanielk1977 Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
30254e6af134Sdanielk1977 return res;
30264e6af134Sdanielk1977 }
test_collate(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])30277617e4a8Smistachkin static int SQLITE_TCLAPI test_collate(
30284e6af134Sdanielk1977 void * clientData,
30294e6af134Sdanielk1977 Tcl_Interp *interp,
30304e6af134Sdanielk1977 int objc,
30314e6af134Sdanielk1977 Tcl_Obj *CONST objv[]
30324e6af134Sdanielk1977 ){
30334e6af134Sdanielk1977 sqlite3 *db;
30344e6af134Sdanielk1977 int val;
3035312d6b36Sdanielk1977 sqlite3_value *pVal;
3036c60d0446Sdrh int rc;
30374e6af134Sdanielk1977
30384e6af134Sdanielk1977 if( objc!=5 ) goto bad_args;
30394e6af134Sdanielk1977 pTestCollateInterp = interp;
30404e6af134Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
30414e6af134Sdanielk1977
30424e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
3043c60d0446Sdrh rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
30444e6af134Sdanielk1977 (void *)SQLITE_UTF8, val?test_collate_func:0);
3045c60d0446Sdrh if( rc==SQLITE_OK ){
3046eee4c8caSdrh const void *zUtf16;
30474e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
3048c60d0446Sdrh rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
30494e6af134Sdanielk1977 (void *)SQLITE_UTF16LE, val?test_collate_func:0);
30504e6af134Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
3051312d6b36Sdanielk1977
305286f8c197Sdrh #if 0
30539a30cf65Sdanielk1977 if( sqlite3_iMallocFail>0 ){
30549a30cf65Sdanielk1977 sqlite3_iMallocFail++;
30559a30cf65Sdanielk1977 }
30569a30cf65Sdanielk1977 #endif
3057f3a65f7eSdrh sqlite3_mutex_enter(db->mutex);
3058f3a65f7eSdrh pVal = sqlite3ValueNew(db);
3059b21c8cd4Sdrh sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
3060a7a8e14bSdanielk1977 zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
3061f3a65f7eSdrh if( db->mallocFailed ){
3062f3a65f7eSdrh rc = SQLITE_NOMEM;
3063f3a65f7eSdrh }else{
3064a7a8e14bSdanielk1977 rc = sqlite3_create_collation16(db, zUtf16, SQLITE_UTF16BE,
30659a30cf65Sdanielk1977 (void *)SQLITE_UTF16BE, val?test_collate_func:0);
3066f3a65f7eSdrh }
3067312d6b36Sdanielk1977 sqlite3ValueFree(pVal);
3068f3a65f7eSdrh sqlite3_mutex_leave(db->mutex);
3069c60d0446Sdrh }
3070c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
30719a30cf65Sdanielk1977
30729a30cf65Sdanielk1977 if( rc!=SQLITE_OK ){
3073e84d8d32Smistachkin Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
30749a30cf65Sdanielk1977 return TCL_ERROR;
30759a30cf65Sdanielk1977 }
30764e6af134Sdanielk1977 return TCL_OK;
30774e6af134Sdanielk1977
30784e6af134Sdanielk1977 bad_args:
30794e6af134Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
30804e6af134Sdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
30814e6af134Sdanielk1977 return TCL_ERROR;
30824e6af134Sdanielk1977 }
30834e6af134Sdanielk1977
3084268803a9Sdrh /*
308538fdead8Sdan ** Usage: add_test_utf16bin_collate <db ptr>
308638fdead8Sdan **
308738fdead8Sdan ** Add a utf-16 collation sequence named "utf16bin" to the database
308838fdead8Sdan ** handle. This collation sequence compares arguments in the same way as the
308938fdead8Sdan ** built-in collation "binary".
309038fdead8Sdan */
test_utf16bin_collate_func(void * pCtx,int nA,const void * zA,int nB,const void * zB)309138fdead8Sdan static int test_utf16bin_collate_func(
309238fdead8Sdan void *pCtx,
309338fdead8Sdan int nA, const void *zA,
309438fdead8Sdan int nB, const void *zB
309538fdead8Sdan ){
309638fdead8Sdan int nCmp = (nA>nB ? nB : nA);
309738fdead8Sdan int res = memcmp(zA, zB, nCmp);
309838fdead8Sdan if( res==0 ) res = nA - nB;
309938fdead8Sdan return res;
310038fdead8Sdan }
test_utf16bin_collate(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])31017617e4a8Smistachkin static int SQLITE_TCLAPI test_utf16bin_collate(
310238fdead8Sdan void * clientData,
310338fdead8Sdan Tcl_Interp *interp,
310438fdead8Sdan int objc,
310538fdead8Sdan Tcl_Obj *CONST objv[]
310638fdead8Sdan ){
310738fdead8Sdan sqlite3 *db;
310838fdead8Sdan int rc;
310938fdead8Sdan
311038fdead8Sdan if( objc!=2 ) goto bad_args;
311138fdead8Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
311238fdead8Sdan
311338fdead8Sdan rc = sqlite3_create_collation(db, "utf16bin", SQLITE_UTF16, 0,
311438fdead8Sdan test_utf16bin_collate_func
311538fdead8Sdan );
311638fdead8Sdan if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
311738fdead8Sdan return TCL_OK;
311838fdead8Sdan
311938fdead8Sdan bad_args:
312038fdead8Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB");
312138fdead8Sdan return TCL_ERROR;
312238fdead8Sdan }
312338fdead8Sdan
312438fdead8Sdan /*
3125268803a9Sdrh ** When the collation needed callback is invoked, record the name of
3126268803a9Sdrh ** the requested collating function here. The recorded name is linked
3127268803a9Sdrh ** to a TCL variable and used to make sure that the requested collation
3128268803a9Sdrh ** name is correct.
3129268803a9Sdrh */
3130268803a9Sdrh static char zNeededCollation[200];
3131268803a9Sdrh static char *pzNeededCollation = zNeededCollation;
3132268803a9Sdrh
3133268803a9Sdrh
3134268803a9Sdrh /*
3135268803a9Sdrh ** Called when a collating sequence is needed. Registered using
3136268803a9Sdrh ** sqlite3_collation_needed16().
3137268803a9Sdrh */
test_collate_needed_cb(void * pCtx,sqlite3 * db,int eTextRep,const void * pName)3138312d6b36Sdanielk1977 static void test_collate_needed_cb(
3139312d6b36Sdanielk1977 void *pCtx,
3140312d6b36Sdanielk1977 sqlite3 *db,
3141312d6b36Sdanielk1977 int eTextRep,
3142268803a9Sdrh const void *pName
3143312d6b36Sdanielk1977 ){
314414db2665Sdanielk1977 int enc = ENC(db);
3145268803a9Sdrh int i;
3146268803a9Sdrh char *z;
3147268803a9Sdrh for(z = (char*)pName, i=0; *z || z[1]; z++){
3148268803a9Sdrh if( *z ) zNeededCollation[i++] = *z;
3149268803a9Sdrh }
3150268803a9Sdrh zNeededCollation[i] = 0;
3151312d6b36Sdanielk1977 sqlite3_create_collation(
3152d2199f0fSdan db, "test_collate", ENC(db), SQLITE_INT_TO_PTR(enc), test_collate_func);
3153312d6b36Sdanielk1977 }
3154312d6b36Sdanielk1977
3155312d6b36Sdanielk1977 /*
3156312d6b36Sdanielk1977 ** Usage: add_test_collate_needed DB
3157312d6b36Sdanielk1977 */
test_collate_needed(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])31587617e4a8Smistachkin static int SQLITE_TCLAPI test_collate_needed(
3159312d6b36Sdanielk1977 void * clientData,
3160312d6b36Sdanielk1977 Tcl_Interp *interp,
3161312d6b36Sdanielk1977 int objc,
3162312d6b36Sdanielk1977 Tcl_Obj *CONST objv[]
3163312d6b36Sdanielk1977 ){
3164312d6b36Sdanielk1977 sqlite3 *db;
3165c60d0446Sdrh int rc;
3166312d6b36Sdanielk1977
3167312d6b36Sdanielk1977 if( objc!=2 ) goto bad_args;
3168312d6b36Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3169c60d0446Sdrh rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
3170268803a9Sdrh zNeededCollation[0] = 0;
3171c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
3172312d6b36Sdanielk1977 return TCL_OK;
3173312d6b36Sdanielk1977
3174312d6b36Sdanielk1977 bad_args:
3175312d6b36Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "DB");
3176312d6b36Sdanielk1977 return TCL_ERROR;
3177312d6b36Sdanielk1977 }
31787d9bd4e1Sdrh
31797d9bd4e1Sdrh /*
31807d9bd4e1Sdrh ** tclcmd: add_alignment_test_collations DB
31817d9bd4e1Sdrh **
31827d9bd4e1Sdrh ** Add two new collating sequences to the database DB
31837d9bd4e1Sdrh **
31847d9bd4e1Sdrh ** utf16_aligned
31857d9bd4e1Sdrh ** utf16_unaligned
31867d9bd4e1Sdrh **
31877d9bd4e1Sdrh ** Both collating sequences use the same sort order as BINARY.
31887d9bd4e1Sdrh ** The only difference is that the utf16_aligned collating
31897d9bd4e1Sdrh ** sequence is declared with the SQLITE_UTF16_ALIGNED flag.
31907d9bd4e1Sdrh ** Both collating functions increment the unaligned utf16 counter
31917d9bd4e1Sdrh ** whenever they see a string that begins on an odd byte boundary.
31927d9bd4e1Sdrh */
31937d9bd4e1Sdrh static int unaligned_string_counter = 0;
alignmentCollFunc(void * NotUsed,int nKey1,const void * pKey1,int nKey2,const void * pKey2)31947d9bd4e1Sdrh static int alignmentCollFunc(
31957d9bd4e1Sdrh void *NotUsed,
31967d9bd4e1Sdrh int nKey1, const void *pKey1,
31977d9bd4e1Sdrh int nKey2, const void *pKey2
31987d9bd4e1Sdrh ){
31997d9bd4e1Sdrh int rc, n;
32007d9bd4e1Sdrh n = nKey1<nKey2 ? nKey1 : nKey2;
3201d2199f0fSdan if( nKey1>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey1))) ) unaligned_string_counter++;
3202d2199f0fSdan if( nKey2>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey2))) ) unaligned_string_counter++;
32037d9bd4e1Sdrh rc = memcmp(pKey1, pKey2, n);
32047d9bd4e1Sdrh if( rc==0 ){
32057d9bd4e1Sdrh rc = nKey1 - nKey2;
32067d9bd4e1Sdrh }
32077d9bd4e1Sdrh return rc;
32087d9bd4e1Sdrh }
add_alignment_test_collations(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])32097617e4a8Smistachkin static int SQLITE_TCLAPI add_alignment_test_collations(
32107d9bd4e1Sdrh void * clientData,
32117d9bd4e1Sdrh Tcl_Interp *interp,
32127d9bd4e1Sdrh int objc,
32137d9bd4e1Sdrh Tcl_Obj *CONST objv[]
32147d9bd4e1Sdrh ){
32157d9bd4e1Sdrh sqlite3 *db;
32167d9bd4e1Sdrh if( objc>=2 ){
32177d9bd4e1Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3218ebb32939Sdanielk1977 sqlite3_create_collation(db, "utf16_unaligned", SQLITE_UTF16,
32197d9bd4e1Sdrh 0, alignmentCollFunc);
3220ebb32939Sdanielk1977 sqlite3_create_collation(db, "utf16_aligned", SQLITE_UTF16_ALIGNED,
32217d9bd4e1Sdrh 0, alignmentCollFunc);
32227d9bd4e1Sdrh }
32237d9bd4e1Sdrh return SQLITE_OK;
32247d9bd4e1Sdrh }
32257d9bd4e1Sdrh #endif /* !defined(SQLITE_OMIT_UTF16) */
3226312d6b36Sdanielk1977
3227c8e9a2dfSdanielk1977 /*
3228c8e9a2dfSdanielk1977 ** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
3229c8e9a2dfSdanielk1977 **
3230c8e9a2dfSdanielk1977 ** This function is used to test that SQLite selects the correct user
3231c8e9a2dfSdanielk1977 ** function callback when multiple versions (for different text encodings)
3232c8e9a2dfSdanielk1977 ** are available.
3233c8e9a2dfSdanielk1977 **
3234c8e9a2dfSdanielk1977 ** Calling this routine registers up to three versions of the user function
3235c8e9a2dfSdanielk1977 ** "test_function" with database handle <db>. If the second argument is
3236c8e9a2dfSdanielk1977 ** true, then a version of test_function is registered for UTF-8, if the
3237c8e9a2dfSdanielk1977 ** third is true, a version is registered for UTF-16le, if the fourth is
3238c8e9a2dfSdanielk1977 ** true, a UTF-16be version is available. Previous versions of
3239c8e9a2dfSdanielk1977 ** test_function are deleted.
3240c8e9a2dfSdanielk1977 **
3241c8e9a2dfSdanielk1977 ** The user function is implemented by calling the following TCL script:
3242c8e9a2dfSdanielk1977 **
3243c8e9a2dfSdanielk1977 ** "test_function <enc> <arg>"
3244c8e9a2dfSdanielk1977 **
3245c8e9a2dfSdanielk1977 ** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
3246c8e9a2dfSdanielk1977 ** single argument passed to the SQL function. The value returned by
3247c8e9a2dfSdanielk1977 ** the TCL script is used as the return value of the SQL function. It
3248c8e9a2dfSdanielk1977 ** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
3249c8e9a2dfSdanielk1977 ** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
3250c8e9a2dfSdanielk1977 ** prefers UTF-16BE.
3251c8e9a2dfSdanielk1977 */
32525436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
test_function_utf8(sqlite3_context * pCtx,int nArg,sqlite3_value ** argv)3253c8e9a2dfSdanielk1977 static void test_function_utf8(
3254c8e9a2dfSdanielk1977 sqlite3_context *pCtx,
3255c8e9a2dfSdanielk1977 int nArg,
3256c8e9a2dfSdanielk1977 sqlite3_value **argv
3257c8e9a2dfSdanielk1977 ){
3258c8e9a2dfSdanielk1977 Tcl_Interp *interp;
3259c8e9a2dfSdanielk1977 Tcl_Obj *pX;
3260c8e9a2dfSdanielk1977 sqlite3_value *pVal;
3261c8e9a2dfSdanielk1977 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
3262c8e9a2dfSdanielk1977 pX = Tcl_NewStringObj("test_function", -1);
3263c8e9a2dfSdanielk1977 Tcl_IncrRefCount(pX);
3264c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
3265c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX,
326603d847eaSdrh Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
3267c8e9a2dfSdanielk1977 Tcl_EvalObjEx(interp, pX, 0);
3268c8e9a2dfSdanielk1977 Tcl_DecrRefCount(pX);
3269c8e9a2dfSdanielk1977 sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
32701e536953Sdanielk1977 pVal = sqlite3ValueNew(0);
3271b21c8cd4Sdrh sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
3272c8e9a2dfSdanielk1977 SQLITE_UTF8, SQLITE_STATIC);
3273c8e9a2dfSdanielk1977 sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
3274c8e9a2dfSdanielk1977 -1, SQLITE_TRANSIENT);
3275c8e9a2dfSdanielk1977 sqlite3ValueFree(pVal);
3276c8e9a2dfSdanielk1977 }
test_function_utf16le(sqlite3_context * pCtx,int nArg,sqlite3_value ** argv)3277c8e9a2dfSdanielk1977 static void test_function_utf16le(
3278c8e9a2dfSdanielk1977 sqlite3_context *pCtx,
3279c8e9a2dfSdanielk1977 int nArg,
3280c8e9a2dfSdanielk1977 sqlite3_value **argv
3281c8e9a2dfSdanielk1977 ){
3282c8e9a2dfSdanielk1977 Tcl_Interp *interp;
3283c8e9a2dfSdanielk1977 Tcl_Obj *pX;
3284c8e9a2dfSdanielk1977 sqlite3_value *pVal;
3285c8e9a2dfSdanielk1977 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
3286c8e9a2dfSdanielk1977 pX = Tcl_NewStringObj("test_function", -1);
3287c8e9a2dfSdanielk1977 Tcl_IncrRefCount(pX);
3288c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
3289c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX,
329003d847eaSdrh Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
3291c8e9a2dfSdanielk1977 Tcl_EvalObjEx(interp, pX, 0);
3292c8e9a2dfSdanielk1977 Tcl_DecrRefCount(pX);
32931e536953Sdanielk1977 pVal = sqlite3ValueNew(0);
3294b21c8cd4Sdrh sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
3295c8e9a2dfSdanielk1977 SQLITE_UTF8, SQLITE_STATIC);
329603d847eaSdrh sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
3297c8e9a2dfSdanielk1977 sqlite3ValueFree(pVal);
3298c8e9a2dfSdanielk1977 }
test_function_utf16be(sqlite3_context * pCtx,int nArg,sqlite3_value ** argv)3299c8e9a2dfSdanielk1977 static void test_function_utf16be(
3300c8e9a2dfSdanielk1977 sqlite3_context *pCtx,
3301c8e9a2dfSdanielk1977 int nArg,
3302c8e9a2dfSdanielk1977 sqlite3_value **argv
3303c8e9a2dfSdanielk1977 ){
3304c8e9a2dfSdanielk1977 Tcl_Interp *interp;
3305c8e9a2dfSdanielk1977 Tcl_Obj *pX;
3306c8e9a2dfSdanielk1977 sqlite3_value *pVal;
3307c8e9a2dfSdanielk1977 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
3308c8e9a2dfSdanielk1977 pX = Tcl_NewStringObj("test_function", -1);
3309c8e9a2dfSdanielk1977 Tcl_IncrRefCount(pX);
3310c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
3311c8e9a2dfSdanielk1977 Tcl_ListObjAppendElement(interp, pX,
331203d847eaSdrh Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
3313c8e9a2dfSdanielk1977 Tcl_EvalObjEx(interp, pX, 0);
3314c8e9a2dfSdanielk1977 Tcl_DecrRefCount(pX);
33151e536953Sdanielk1977 pVal = sqlite3ValueNew(0);
3316b21c8cd4Sdrh sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
3317c8e9a2dfSdanielk1977 SQLITE_UTF8, SQLITE_STATIC);
3318de4fcfddSdrh sqlite3_result_text16(pCtx, sqlite3_value_text16le(pVal),
3319de4fcfddSdrh -1, SQLITE_TRANSIENT);
3320de4fcfddSdrh sqlite3_result_text16be(pCtx, sqlite3_value_text16le(pVal),
3321de4fcfddSdrh -1, SQLITE_TRANSIENT);
3322c8e9a2dfSdanielk1977 sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
3323c8e9a2dfSdanielk1977 -1, SQLITE_TRANSIENT);
3324c8e9a2dfSdanielk1977 sqlite3ValueFree(pVal);
3325c8e9a2dfSdanielk1977 }
33265436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
test_function(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])33277617e4a8Smistachkin static int SQLITE_TCLAPI test_function(
3328c8e9a2dfSdanielk1977 void * clientData,
3329c8e9a2dfSdanielk1977 Tcl_Interp *interp,
3330c8e9a2dfSdanielk1977 int objc,
3331c8e9a2dfSdanielk1977 Tcl_Obj *CONST objv[]
3332c8e9a2dfSdanielk1977 ){
33335436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
3334c8e9a2dfSdanielk1977 sqlite3 *db;
3335c8e9a2dfSdanielk1977 int val;
3336c8e9a2dfSdanielk1977
3337c8e9a2dfSdanielk1977 if( objc!=5 ) goto bad_args;
3338c8e9a2dfSdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3339c8e9a2dfSdanielk1977
3340c8e9a2dfSdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
3341c8e9a2dfSdanielk1977 if( val ){
3342c8e9a2dfSdanielk1977 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
3343c8e9a2dfSdanielk1977 interp, test_function_utf8, 0, 0);
3344c8e9a2dfSdanielk1977 }
3345c8e9a2dfSdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
3346c8e9a2dfSdanielk1977 if( val ){
3347c8e9a2dfSdanielk1977 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
3348c8e9a2dfSdanielk1977 interp, test_function_utf16le, 0, 0);
3349c8e9a2dfSdanielk1977 }
3350c8e9a2dfSdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
3351c8e9a2dfSdanielk1977 if( val ){
3352c8e9a2dfSdanielk1977 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
3353c8e9a2dfSdanielk1977 interp, test_function_utf16be, 0, 0);
3354c8e9a2dfSdanielk1977 }
3355c8e9a2dfSdanielk1977
3356c8e9a2dfSdanielk1977 return TCL_OK;
3357c8e9a2dfSdanielk1977 bad_args:
3358c8e9a2dfSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
3359c8e9a2dfSdanielk1977 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
33605436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
3361c8e9a2dfSdanielk1977 return TCL_ERROR;
3362c8e9a2dfSdanielk1977 }
3363c8e9a2dfSdanielk1977
3364312d6b36Sdanielk1977 /*
3365ba3cbf3dSdan ** Usage: sqlite3_test_errstr <err code>
3366312d6b36Sdanielk1977 **
3367312d6b36Sdanielk1977 ** Test that the english language string equivalents for sqlite error codes
3368312d6b36Sdanielk1977 ** are sane. The parameter is an integer representing an sqlite error code.
3369312d6b36Sdanielk1977 ** The result is a list of two elements, the string representation of the
3370312d6b36Sdanielk1977 ** error code and the english language explanation.
3371312d6b36Sdanielk1977 */
test_errstr(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])33727617e4a8Smistachkin static int SQLITE_TCLAPI test_errstr(
3373312d6b36Sdanielk1977 void * clientData,
3374312d6b36Sdanielk1977 Tcl_Interp *interp,
3375312d6b36Sdanielk1977 int objc,
3376312d6b36Sdanielk1977 Tcl_Obj *CONST objv[]
3377312d6b36Sdanielk1977 ){
3378312d6b36Sdanielk1977 char *zCode;
3379312d6b36Sdanielk1977 int i;
3380312d6b36Sdanielk1977 if( objc!=1 ){
3381312d6b36Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
3382312d6b36Sdanielk1977 }
3383312d6b36Sdanielk1977
3384312d6b36Sdanielk1977 zCode = Tcl_GetString(objv[1]);
3385312d6b36Sdanielk1977 for(i=0; i<200; i++){
33864f0c5878Sdrh if( 0==strcmp(t1ErrorName(i), zCode) ) break;
3387312d6b36Sdanielk1977 }
3388312d6b36Sdanielk1977 Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
3389312d6b36Sdanielk1977 return TCL_OK;
3390312d6b36Sdanielk1977 }
3391312d6b36Sdanielk1977
339250457896Sdrh /*
339399ee3600Sdrh ** Usage: breakpoint
339499ee3600Sdrh **
339599ee3600Sdrh ** This routine exists for one purpose - to provide a place to put a
339699ee3600Sdrh ** breakpoint with GDB that can be triggered using TCL code. The use
339799ee3600Sdrh ** for this is when a particular test fails on (say) the 1485th iteration.
339899ee3600Sdrh ** In the TCL test script, we can add code like this:
339999ee3600Sdrh **
340099ee3600Sdrh ** if {$i==1485} breakpoint
340199ee3600Sdrh **
340299ee3600Sdrh ** Then run testfixture in the debugger and wait for the breakpoint to
340399ee3600Sdrh ** fire. Then additional breakpoints can be set to trace down the bug.
340499ee3600Sdrh */
test_breakpoint(void * NotUsed,Tcl_Interp * interp,int argc,char ** argv)34057617e4a8Smistachkin static int SQLITE_TCLAPI test_breakpoint(
340699ee3600Sdrh void *NotUsed,
340799ee3600Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
340899ee3600Sdrh int argc, /* Number of arguments */
340999ee3600Sdrh char **argv /* Text of each argument */
341099ee3600Sdrh ){
341199ee3600Sdrh return TCL_OK; /* Do nothing */
341299ee3600Sdrh }
341399ee3600Sdrh
3414241db313Sdrh /*
3415b026e05eSdrh ** Usage: sqlite3_bind_zeroblob STMT IDX N
3416b026e05eSdrh **
3417b026e05eSdrh ** Test the sqlite3_bind_zeroblob interface. STMT is a prepared statement.
3418b026e05eSdrh ** IDX is the index of a wildcard in the prepared statement. This command
3419b026e05eSdrh ** binds a N-byte zero-filled BLOB to the wildcard.
3420b026e05eSdrh */
test_bind_zeroblob(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])34217617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_zeroblob(
3422b026e05eSdrh void * clientData,
3423b026e05eSdrh Tcl_Interp *interp,
3424b026e05eSdrh int objc,
3425b026e05eSdrh Tcl_Obj *CONST objv[]
3426b026e05eSdrh ){
3427b026e05eSdrh sqlite3_stmt *pStmt;
3428b026e05eSdrh int idx;
3429b026e05eSdrh int n;
3430b026e05eSdrh int rc;
3431b026e05eSdrh
3432b026e05eSdrh if( objc!=4 ){
343328c66307Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N");
3434b026e05eSdrh return TCL_ERROR;
3435b026e05eSdrh }
3436b026e05eSdrh
3437b026e05eSdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3438b026e05eSdrh if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3439b026e05eSdrh if( Tcl_GetIntFromObj(interp, objv[3], &n) ) return TCL_ERROR;
3440b026e05eSdrh
3441b026e05eSdrh rc = sqlite3_bind_zeroblob(pStmt, idx, n);
3442b026e05eSdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3443b026e05eSdrh if( rc!=SQLITE_OK ){
3444b026e05eSdrh return TCL_ERROR;
3445b026e05eSdrh }
3446b026e05eSdrh
3447b026e05eSdrh return TCL_OK;
3448b026e05eSdrh }
3449b026e05eSdrh
3450b026e05eSdrh /*
345180c03022Sdan ** Usage: sqlite3_bind_zeroblob64 STMT IDX N
345280c03022Sdan **
345380c03022Sdan ** Test the sqlite3_bind_zeroblob64 interface. STMT is a prepared statement.
345480c03022Sdan ** IDX is the index of a wildcard in the prepared statement. This command
345580c03022Sdan ** binds a N-byte zero-filled BLOB to the wildcard.
345680c03022Sdan */
test_bind_zeroblob64(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])34577617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_zeroblob64(
345880c03022Sdan void * clientData,
345980c03022Sdan Tcl_Interp *interp,
346080c03022Sdan int objc,
346180c03022Sdan Tcl_Obj *CONST objv[]
346280c03022Sdan ){
346380c03022Sdan sqlite3_stmt *pStmt;
346480c03022Sdan int idx;
34659a1e85eeSdrh Tcl_WideInt n;
346680c03022Sdan int rc;
346780c03022Sdan
346880c03022Sdan if( objc!=4 ){
346980c03022Sdan Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N");
347080c03022Sdan return TCL_ERROR;
347180c03022Sdan }
347280c03022Sdan
347380c03022Sdan if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
347480c03022Sdan if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
347580c03022Sdan if( Tcl_GetWideIntFromObj(interp, objv[3], &n) ) return TCL_ERROR;
347680c03022Sdan
347780c03022Sdan rc = sqlite3_bind_zeroblob64(pStmt, idx, n);
347880c03022Sdan if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
347980c03022Sdan if( rc!=SQLITE_OK ){
348080c03022Sdan Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
348180c03022Sdan return TCL_ERROR;
348280c03022Sdan }
348380c03022Sdan
348480c03022Sdan return TCL_OK;
348580c03022Sdan }
348680c03022Sdan
348780c03022Sdan /*
3488241db313Sdrh ** Usage: sqlite3_bind_int STMT N VALUE
3489241db313Sdrh **
3490241db313Sdrh ** Test the sqlite3_bind_int interface. STMT is a prepared statement.
3491241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command
3492241db313Sdrh ** binds a 32-bit integer VALUE to that wildcard.
3493241db313Sdrh */
test_bind_int(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])34947617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_int(
349551e3d8e2Sdanielk1977 void * clientData,
349651e3d8e2Sdanielk1977 Tcl_Interp *interp,
349751e3d8e2Sdanielk1977 int objc,
349851e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[]
349951e3d8e2Sdanielk1977 ){
350051e3d8e2Sdanielk1977 sqlite3_stmt *pStmt;
350151e3d8e2Sdanielk1977 int idx;
350251e3d8e2Sdanielk1977 int value;
350351e3d8e2Sdanielk1977 int rc;
350451e3d8e2Sdanielk1977
350551e3d8e2Sdanielk1977 if( objc!=4 ){
350651e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
3507241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
350851e3d8e2Sdanielk1977 return TCL_ERROR;
350951e3d8e2Sdanielk1977 }
351051e3d8e2Sdanielk1977
351151e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
351251e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
351351e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
351451e3d8e2Sdanielk1977
3515c572ef7fSdanielk1977 rc = sqlite3_bind_int(pStmt, idx, value);
3516c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
351751e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){
351851e3d8e2Sdanielk1977 return TCL_ERROR;
351951e3d8e2Sdanielk1977 }
352051e3d8e2Sdanielk1977
352151e3d8e2Sdanielk1977 return TCL_OK;
352251e3d8e2Sdanielk1977 }
352351e3d8e2Sdanielk1977
3524241db313Sdrh
3525241db313Sdrh /*
35262e3f87aeSdrh ** Usage: intarray_addr INT ...
35274841624aSdrh **
35282e3f87aeSdrh ** Return the address of a C-language array of 32-bit integers.
35292e3f87aeSdrh **
35302e3f87aeSdrh ** Space to hold the array is obtained from malloc(). Call this procedure once
35312e3f87aeSdrh ** with no arguments in order to release memory. Each call to this procedure
35322e3f87aeSdrh ** overwrites the previous array.
35334841624aSdrh */
test_intarray_addr(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])35347617e4a8Smistachkin static int SQLITE_TCLAPI test_intarray_addr(
35354841624aSdrh void * clientData,
35364841624aSdrh Tcl_Interp *interp,
35374841624aSdrh int objc,
35384841624aSdrh Tcl_Obj *CONST objv[]
35394841624aSdrh ){
35404841624aSdrh int i;
35414841624aSdrh static int *p = 0;
35424841624aSdrh
35434841624aSdrh sqlite3_free(p);
35444841624aSdrh p = 0;
35452e3f87aeSdrh if( objc>1 ){
35462e3f87aeSdrh p = sqlite3_malloc( sizeof(p[0])*(objc-1) );
35474841624aSdrh if( p==0 ) return TCL_ERROR;
35482e3f87aeSdrh for(i=0; i<objc-1; i++){
35492e3f87aeSdrh if( Tcl_GetIntFromObj(interp, objv[1+i], &p[i]) ){
35504841624aSdrh sqlite3_free(p);
35512e3f87aeSdrh p = 0;
35524841624aSdrh return TCL_ERROR;
35534841624aSdrh }
35544841624aSdrh }
35552e3f87aeSdrh }
35562e3f87aeSdrh Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p));
35572e3f87aeSdrh return TCL_OK;
35582e3f87aeSdrh }
35592e3f87aeSdrh /*
35602e3f87aeSdrh ** Usage: intarray_addr INT ...
35612e3f87aeSdrh **
35622e3f87aeSdrh ** Return the address of a C-language array of 32-bit integers.
35632e3f87aeSdrh **
35642e3f87aeSdrh ** Space to hold the array is obtained from malloc(). Call this procedure once
35652e3f87aeSdrh ** with no arguments in order to release memory. Each call to this procedure
35662e3f87aeSdrh ** overwrites the previous array.
35672e3f87aeSdrh */
test_int64array_addr(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])35687617e4a8Smistachkin static int SQLITE_TCLAPI test_int64array_addr(
35692e3f87aeSdrh void * clientData,
35702e3f87aeSdrh Tcl_Interp *interp,
35712e3f87aeSdrh int objc,
35722e3f87aeSdrh Tcl_Obj *CONST objv[]
35732e3f87aeSdrh ){
35742e3f87aeSdrh int i;
35752e3f87aeSdrh static sqlite3_int64 *p = 0;
35762e3f87aeSdrh
35772e3f87aeSdrh sqlite3_free(p);
35782e3f87aeSdrh p = 0;
35792e3f87aeSdrh if( objc>1 ){
35802e3f87aeSdrh p = sqlite3_malloc( sizeof(p[0])*(objc-1) );
35812e3f87aeSdrh if( p==0 ) return TCL_ERROR;
35822e3f87aeSdrh for(i=0; i<objc-1; i++){
3583a912348aSdrh Tcl_WideInt v;
3584a912348aSdrh if( Tcl_GetWideIntFromObj(interp, objv[1+i], &v) ){
35852e3f87aeSdrh sqlite3_free(p);
35862e3f87aeSdrh p = 0;
35872e3f87aeSdrh return TCL_ERROR;
35882e3f87aeSdrh }
3589a912348aSdrh p[i] = v;
35902e3f87aeSdrh }
35912e3f87aeSdrh }
35922e3f87aeSdrh Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p));
35932e3f87aeSdrh return TCL_OK;
35942e3f87aeSdrh }
35952e3f87aeSdrh /*
35962e3f87aeSdrh ** Usage: doublearray_addr INT ...
35972e3f87aeSdrh **
35982e3f87aeSdrh ** Return the address of a C-language array of doubles.
35992e3f87aeSdrh **
36002e3f87aeSdrh ** Space to hold the array is obtained from malloc(). Call this procedure once
36012e3f87aeSdrh ** with no arguments in order to release memory. Each call to this procedure
36022e3f87aeSdrh ** overwrites the previous array.
36032e3f87aeSdrh */
test_doublearray_addr(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])36047617e4a8Smistachkin static int SQLITE_TCLAPI test_doublearray_addr(
36052e3f87aeSdrh void * clientData,
36062e3f87aeSdrh Tcl_Interp *interp,
36072e3f87aeSdrh int objc,
36082e3f87aeSdrh Tcl_Obj *CONST objv[]
36092e3f87aeSdrh ){
36102e3f87aeSdrh int i;
36112e3f87aeSdrh static double *p = 0;
36122e3f87aeSdrh
36132e3f87aeSdrh sqlite3_free(p);
36142e3f87aeSdrh p = 0;
36152e3f87aeSdrh if( objc>1 ){
36162e3f87aeSdrh p = sqlite3_malloc( sizeof(p[0])*(objc-1) );
36172e3f87aeSdrh if( p==0 ) return TCL_ERROR;
36182e3f87aeSdrh for(i=0; i<objc-1; i++){
36192e3f87aeSdrh if( Tcl_GetDoubleFromObj(interp, objv[1+i], &p[i]) ){
36202e3f87aeSdrh sqlite3_free(p);
36212e3f87aeSdrh p = 0;
36222e3f87aeSdrh return TCL_ERROR;
36232e3f87aeSdrh }
36242e3f87aeSdrh }
36252e3f87aeSdrh }
36262e3f87aeSdrh Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p));
36272e3f87aeSdrh return TCL_OK;
36282e3f87aeSdrh }
36292e3f87aeSdrh /*
36302e3f87aeSdrh ** Usage: textarray_addr TEXT ...
36312e3f87aeSdrh **
36322e3f87aeSdrh ** Return the address of a C-language array of strings.
36332e3f87aeSdrh **
36342e3f87aeSdrh ** Space to hold the array is obtained from malloc(). Call this procedure once
36352e3f87aeSdrh ** with no arguments in order to release memory. Each call to this procedure
36362e3f87aeSdrh ** overwrites the previous array.
36372e3f87aeSdrh */
test_textarray_addr(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])36387617e4a8Smistachkin static int SQLITE_TCLAPI test_textarray_addr(
36392e3f87aeSdrh void * clientData,
36402e3f87aeSdrh Tcl_Interp *interp,
36412e3f87aeSdrh int objc,
36422e3f87aeSdrh Tcl_Obj *CONST objv[]
36432e3f87aeSdrh ){
36442e3f87aeSdrh int i;
36452e3f87aeSdrh static int n = 0;
36462e3f87aeSdrh static char **p = 0;
36472e3f87aeSdrh
36482e3f87aeSdrh for(i=0; i<n; i++) sqlite3_free(p[i]);
36492e3f87aeSdrh sqlite3_free(p);
36502e3f87aeSdrh p = 0;
36512e3f87aeSdrh if( objc>1 ){
36522e3f87aeSdrh p = sqlite3_malloc( sizeof(p[0])*(objc-1) );
36532e3f87aeSdrh if( p==0 ) return TCL_ERROR;
36542e3f87aeSdrh for(i=0; i<objc-1; i++){
36552e3f87aeSdrh p[i] = sqlite3_mprintf("%s", Tcl_GetString(objv[1+i]));
36562e3f87aeSdrh }
36572e3f87aeSdrh }
365850687436Sdan n = objc-1;
36592e3f87aeSdrh Tcl_SetObjResult(interp, Tcl_NewWideIntObj((sqlite3_int64)p));
36604841624aSdrh return TCL_OK;
36614841624aSdrh }
36624841624aSdrh
36634841624aSdrh
36644841624aSdrh /*
3665241db313Sdrh ** Usage: sqlite3_bind_int64 STMT N VALUE
3666241db313Sdrh **
3667241db313Sdrh ** Test the sqlite3_bind_int64 interface. STMT is a prepared statement.
3668241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command
3669241db313Sdrh ** binds a 64-bit integer VALUE to that wildcard.
3670241db313Sdrh */
test_bind_int64(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])36717617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_int64(
367251e3d8e2Sdanielk1977 void * clientData,
367351e3d8e2Sdanielk1977 Tcl_Interp *interp,
367451e3d8e2Sdanielk1977 int objc,
367551e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[]
367651e3d8e2Sdanielk1977 ){
367751e3d8e2Sdanielk1977 sqlite3_stmt *pStmt;
367851e3d8e2Sdanielk1977 int idx;
3679b3f787f4Sdrh Tcl_WideInt value;
368051e3d8e2Sdanielk1977 int rc;
368151e3d8e2Sdanielk1977
368251e3d8e2Sdanielk1977 if( objc!=4 ){
368351e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
3684241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
368551e3d8e2Sdanielk1977 return TCL_ERROR;
368651e3d8e2Sdanielk1977 }
368751e3d8e2Sdanielk1977
368851e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
368951e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
369051e3d8e2Sdanielk1977 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
369151e3d8e2Sdanielk1977
369251e3d8e2Sdanielk1977 rc = sqlite3_bind_int64(pStmt, idx, value);
3693c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
369451e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){
369551e3d8e2Sdanielk1977 return TCL_ERROR;
369651e3d8e2Sdanielk1977 }
369751e3d8e2Sdanielk1977
369851e3d8e2Sdanielk1977 return TCL_OK;
369951e3d8e2Sdanielk1977 }
370051e3d8e2Sdanielk1977
3701241db313Sdrh
3702241db313Sdrh /*
3703241db313Sdrh ** Usage: sqlite3_bind_double STMT N VALUE
3704241db313Sdrh **
3705241db313Sdrh ** Test the sqlite3_bind_double interface. STMT is a prepared statement.
3706241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command
3707241db313Sdrh ** binds a 64-bit integer VALUE to that wildcard.
3708241db313Sdrh */
test_bind_double(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])37097617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_double(
371051e3d8e2Sdanielk1977 void * clientData,
371151e3d8e2Sdanielk1977 Tcl_Interp *interp,
371251e3d8e2Sdanielk1977 int objc,
371351e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[]
371451e3d8e2Sdanielk1977 ){
371551e3d8e2Sdanielk1977 sqlite3_stmt *pStmt;
371651e3d8e2Sdanielk1977 int idx;
371727b2f053Smistachkin double value = 0;
371851e3d8e2Sdanielk1977 int rc;
3719a06f17feSdrh const char *zVal;
3720a06f17feSdrh int i;
3721a06f17feSdrh static const struct {
3722a06f17feSdrh const char *zName; /* Name of the special floating point value */
3723a06f17feSdrh unsigned int iUpper; /* Upper 32 bits */
3724a06f17feSdrh unsigned int iLower; /* Lower 32 bits */
3725a06f17feSdrh } aSpecialFp[] = {
3726a06f17feSdrh { "NaN", 0x7fffffff, 0xffffffff },
3727a06f17feSdrh { "SNaN", 0x7ff7ffff, 0xffffffff },
3728a06f17feSdrh { "-NaN", 0xffffffff, 0xffffffff },
3729a06f17feSdrh { "-SNaN", 0xfff7ffff, 0xffffffff },
3730a06f17feSdrh { "+Inf", 0x7ff00000, 0x00000000 },
3731a06f17feSdrh { "-Inf", 0xfff00000, 0x00000000 },
3732a06f17feSdrh { "Epsilon", 0x00000000, 0x00000001 },
3733a06f17feSdrh { "-Epsilon", 0x80000000, 0x00000001 },
3734a06f17feSdrh { "NaN0", 0x7ff80000, 0x00000000 },
3735a06f17feSdrh { "-NaN0", 0xfff80000, 0x00000000 },
3736a06f17feSdrh };
373751e3d8e2Sdanielk1977
373851e3d8e2Sdanielk1977 if( objc!=4 ){
373951e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
3740241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
374151e3d8e2Sdanielk1977 return TCL_ERROR;
374251e3d8e2Sdanielk1977 }
374351e3d8e2Sdanielk1977
374451e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
374551e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
374651e3d8e2Sdanielk1977
3747394f07efSdrh /* Intercept the string "NaN" and generate a NaN value for it.
3748394f07efSdrh ** All other strings are passed through to Tcl_GetDoubleFromObj().
3749394f07efSdrh ** Tcl_GetDoubleFromObj() should understand "NaN" but some versions
3750394f07efSdrh ** contain a bug.
3751394f07efSdrh */
3752a06f17feSdrh zVal = Tcl_GetString(objv[3]);
3753a06f17feSdrh for(i=0; i<sizeof(aSpecialFp)/sizeof(aSpecialFp[0]); i++){
3754a06f17feSdrh if( strcmp(aSpecialFp[i].zName, zVal)==0 ){
3755a06f17feSdrh sqlite3_uint64 x;
3756a06f17feSdrh x = aSpecialFp[i].iUpper;
3757a06f17feSdrh x <<= 32;
3758a06f17feSdrh x |= aSpecialFp[i].iLower;
37590a66733aSdrh assert( sizeof(value)==8 );
37600a66733aSdrh assert( sizeof(x)==8 );
37610a66733aSdrh memcpy(&value, &x, 8);
3762a06f17feSdrh break;
3763a06f17feSdrh }
3764a06f17feSdrh }
3765a06f17feSdrh if( i>=sizeof(aSpecialFp)/sizeof(aSpecialFp[0]) &&
3766a06f17feSdrh Tcl_GetDoubleFromObj(interp, objv[3], &value) ){
3767394f07efSdrh return TCL_ERROR;
3768394f07efSdrh }
376951e3d8e2Sdanielk1977 rc = sqlite3_bind_double(pStmt, idx, value);
3770c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
377151e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){
377251e3d8e2Sdanielk1977 return TCL_ERROR;
377351e3d8e2Sdanielk1977 }
377451e3d8e2Sdanielk1977
377551e3d8e2Sdanielk1977 return TCL_OK;
377651e3d8e2Sdanielk1977 }
377751e3d8e2Sdanielk1977
3778241db313Sdrh /*
3779241db313Sdrh ** Usage: sqlite3_bind_null STMT N
3780241db313Sdrh **
3781241db313Sdrh ** Test the sqlite3_bind_null interface. STMT is a prepared statement.
3782241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command
3783241db313Sdrh ** binds a NULL to the wildcard.
3784241db313Sdrh */
test_bind_null(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])37857617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_null(
378651e3d8e2Sdanielk1977 void * clientData,
378751e3d8e2Sdanielk1977 Tcl_Interp *interp,
378851e3d8e2Sdanielk1977 int objc,
378951e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[]
379051e3d8e2Sdanielk1977 ){
379151e3d8e2Sdanielk1977 sqlite3_stmt *pStmt;
379251e3d8e2Sdanielk1977 int idx;
379351e3d8e2Sdanielk1977 int rc;
379451e3d8e2Sdanielk1977
379551e3d8e2Sdanielk1977 if( objc!=3 ){
379651e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
3797241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
379851e3d8e2Sdanielk1977 return TCL_ERROR;
379951e3d8e2Sdanielk1977 }
380051e3d8e2Sdanielk1977
380151e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
380251e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
380351e3d8e2Sdanielk1977
380451e3d8e2Sdanielk1977 rc = sqlite3_bind_null(pStmt, idx);
3805c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
380651e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){
380751e3d8e2Sdanielk1977 return TCL_ERROR;
380851e3d8e2Sdanielk1977 }
380951e3d8e2Sdanielk1977
381051e3d8e2Sdanielk1977 return TCL_OK;
381151e3d8e2Sdanielk1977 }
381251e3d8e2Sdanielk1977
3813241db313Sdrh /*
3814241db313Sdrh ** Usage: sqlite3_bind_text STMT N STRING BYTES
3815241db313Sdrh **
3816241db313Sdrh ** Test the sqlite3_bind_text interface. STMT is a prepared statement.
3817241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command
3818241db313Sdrh ** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes
3819241db313Sdrh ** long.
3820241db313Sdrh */
test_bind_text(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])38217617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_text(
382251e3d8e2Sdanielk1977 void * clientData,
382351e3d8e2Sdanielk1977 Tcl_Interp *interp,
382451e3d8e2Sdanielk1977 int objc,
382551e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[]
382651e3d8e2Sdanielk1977 ){
382751e3d8e2Sdanielk1977 sqlite3_stmt *pStmt;
382851e3d8e2Sdanielk1977 int idx;
3829639ae98cSdrh int trueLength = 0;
383051e3d8e2Sdanielk1977 int bytes;
383151e3d8e2Sdanielk1977 char *value;
383251e3d8e2Sdanielk1977 int rc;
3833639ae98cSdrh char *toFree = 0;
383451e3d8e2Sdanielk1977
383551e3d8e2Sdanielk1977 if( objc!=5 ){
383651e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
3837241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
383851e3d8e2Sdanielk1977 return TCL_ERROR;
383951e3d8e2Sdanielk1977 }
384051e3d8e2Sdanielk1977
384151e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
384251e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3843639ae98cSdrh value = (char*)Tcl_GetByteArrayFromObj(objv[3], &trueLength);
384451e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
3845639ae98cSdrh if( bytes<0 ){
3846639ae98cSdrh toFree = malloc( trueLength + 1 );
3847639ae98cSdrh if( toFree==0 ){
3848639ae98cSdrh Tcl_AppendResult(interp, "out of memory", (void*)0);
3849639ae98cSdrh return TCL_ERROR;
3850639ae98cSdrh }
3851639ae98cSdrh memcpy(toFree, value, trueLength);
3852639ae98cSdrh toFree[trueLength] = 0;
3853639ae98cSdrh value = toFree;
3854639ae98cSdrh }
3855d8123366Sdanielk1977 rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
3856639ae98cSdrh free(toFree);
3857c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
385851e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){
3859639ae98cSdrh Tcl_AppendResult(interp, sqlite3ErrName(rc), (void*)0);
386051e3d8e2Sdanielk1977 return TCL_ERROR;
386151e3d8e2Sdanielk1977 }
386251e3d8e2Sdanielk1977
386351e3d8e2Sdanielk1977 return TCL_OK;
386451e3d8e2Sdanielk1977 }
386551e3d8e2Sdanielk1977
3866241db313Sdrh /*
3867161fb796Sdanielk1977 ** Usage: sqlite3_bind_text16 ?-static? STMT N STRING BYTES
3868241db313Sdrh **
3869241db313Sdrh ** Test the sqlite3_bind_text16 interface. STMT is a prepared statement.
3870241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command
3871241db313Sdrh ** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes
3872241db313Sdrh ** long.
3873241db313Sdrh */
test_bind_text16(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])38747617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_text16(
387551e3d8e2Sdanielk1977 void * clientData,
387651e3d8e2Sdanielk1977 Tcl_Interp *interp,
387751e3d8e2Sdanielk1977 int objc,
387851e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[]
387951e3d8e2Sdanielk1977 ){
38805436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
388151e3d8e2Sdanielk1977 sqlite3_stmt *pStmt;
388251e3d8e2Sdanielk1977 int idx;
388351e3d8e2Sdanielk1977 int bytes;
388451e3d8e2Sdanielk1977 char *value;
3885639ae98cSdrh char *toFree = 0;
388651e3d8e2Sdanielk1977 int rc;
3887639ae98cSdrh int trueLength = 0;
388851e3d8e2Sdanielk1977
38897da5fcb0Sdrh void (*xDel)(void*) = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
3890161fb796Sdanielk1977 Tcl_Obj *oStmt = objv[objc-4];
3891161fb796Sdanielk1977 Tcl_Obj *oN = objv[objc-3];
3892161fb796Sdanielk1977 Tcl_Obj *oString = objv[objc-2];
3893161fb796Sdanielk1977 Tcl_Obj *oBytes = objv[objc-1];
3894161fb796Sdanielk1977
3895161fb796Sdanielk1977 if( objc!=5 && objc!=6){
389651e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
3897241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
389851e3d8e2Sdanielk1977 return TCL_ERROR;
389951e3d8e2Sdanielk1977 }
390051e3d8e2Sdanielk1977
3901161fb796Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR;
3902161fb796Sdanielk1977 if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR;
3903639ae98cSdrh value = (char*)Tcl_GetByteArrayFromObj(oString, &trueLength);
3904161fb796Sdanielk1977 if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR;
3905639ae98cSdrh if( bytes<0 && xDel==SQLITE_TRANSIENT ){
39065e23ae50Sdrh toFree = malloc( trueLength + 3 );
3907639ae98cSdrh if( toFree==0 ){
3908639ae98cSdrh Tcl_AppendResult(interp, "out of memory", (void*)0);
3909639ae98cSdrh return TCL_ERROR;
3910639ae98cSdrh }
3911639ae98cSdrh memcpy(toFree, value, trueLength);
39125e23ae50Sdrh memset(toFree+trueLength, 0, 3);
3913639ae98cSdrh value = toFree;
3914639ae98cSdrh }
3915161fb796Sdanielk1977 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel);
3916639ae98cSdrh free(toFree);
3917c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
391851e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){
3919e84d8d32Smistachkin Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
392051e3d8e2Sdanielk1977 return TCL_ERROR;
392151e3d8e2Sdanielk1977 }
392251e3d8e2Sdanielk1977
39235436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
392451e3d8e2Sdanielk1977 return TCL_OK;
392551e3d8e2Sdanielk1977 }
392651e3d8e2Sdanielk1977
3927241db313Sdrh /*
39285b159dc3Sdanielk1977 ** Usage: sqlite3_bind_blob ?-static? STMT N DATA BYTES
3929241db313Sdrh **
3930241db313Sdrh ** Test the sqlite3_bind_blob interface. STMT is a prepared statement.
3931241db313Sdrh ** N is the index of a wildcard in the prepared statement. This command
3932241db313Sdrh ** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size.
3933241db313Sdrh */
test_bind_blob(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])39347617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_blob(
393551e3d8e2Sdanielk1977 void * clientData,
393651e3d8e2Sdanielk1977 Tcl_Interp *interp,
393751e3d8e2Sdanielk1977 int objc,
393851e3d8e2Sdanielk1977 Tcl_Obj *CONST objv[]
393951e3d8e2Sdanielk1977 ){
394051e3d8e2Sdanielk1977 sqlite3_stmt *pStmt;
3941de6fde6aSmistachkin int len, idx;
394251e3d8e2Sdanielk1977 int bytes;
394351e3d8e2Sdanielk1977 char *value;
394451e3d8e2Sdanielk1977 int rc;
39455b159dc3Sdanielk1977 sqlite3_destructor_type xDestructor = SQLITE_TRANSIENT;
394651e3d8e2Sdanielk1977
39475b159dc3Sdanielk1977 if( objc!=5 && objc!=6 ){
394851e3d8e2Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
3949241db313Sdrh Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
395051e3d8e2Sdanielk1977 return TCL_ERROR;
395151e3d8e2Sdanielk1977 }
395251e3d8e2Sdanielk1977
39535b159dc3Sdanielk1977 if( objc==6 ){
39545b159dc3Sdanielk1977 xDestructor = SQLITE_STATIC;
39555b159dc3Sdanielk1977 objv++;
39565b159dc3Sdanielk1977 }
39575b159dc3Sdanielk1977
395851e3d8e2Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
395951e3d8e2Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3960de6fde6aSmistachkin
39618d853642Sdrh value = (char*)Tcl_GetByteArrayFromObj(objv[3], &len);
396249e4643eSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
396351e3d8e2Sdanielk1977
3964de6fde6aSmistachkin if( bytes>len ){
3965de6fde6aSmistachkin char zBuf[200];
3966de6fde6aSmistachkin sqlite3_snprintf(sizeof(zBuf), zBuf,
3967de6fde6aSmistachkin "cannot use %d blob bytes, have %d", bytes, len);
3968ea847f1bSdrh Tcl_AppendResult(interp, zBuf, (char*)0);
3969de6fde6aSmistachkin return TCL_ERROR;
3970de6fde6aSmistachkin }
3971de6fde6aSmistachkin
39725b159dc3Sdanielk1977 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, xDestructor);
3973c60d0446Sdrh if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
397451e3d8e2Sdanielk1977 if( rc!=SQLITE_OK ){
397551e3d8e2Sdanielk1977 return TCL_ERROR;
397651e3d8e2Sdanielk1977 }
397751e3d8e2Sdanielk1977
397851e3d8e2Sdanielk1977 return TCL_OK;
397951e3d8e2Sdanielk1977 }
398051e3d8e2Sdanielk1977
3981252fe67bSdan /*
3982252fe67bSdan ** Usage: sqlite3_bind_value_from_preupdate STMT N NEW|OLD IDX
3983252fe67bSdan **
3984252fe67bSdan ** Test the sqlite3_bind_value interface using sqlite3_value objects
3985252fe67bSdan ** obtained from either sqlite3_preupdate_new() (if arg[3]=="new") or
3986252fe67bSdan ** sqlite3_preupdate_old() if (arg[3]=="old"). IDX is the index to
3987252fe67bSdan ** pass to the sqlite3_preupdate_xxx() function.
3988252fe67bSdan */
test_bind_value_from_preupdate(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])3989252fe67bSdan static int SQLITE_TCLAPI test_bind_value_from_preupdate(
3990252fe67bSdan void * clientData,
3991252fe67bSdan Tcl_Interp *interp,
3992252fe67bSdan int objc,
3993252fe67bSdan Tcl_Obj *CONST objv[]
3994252fe67bSdan ){
3995252fe67bSdan sqlite3_stmt *pStmt;
3996252fe67bSdan int idx;
3997252fe67bSdan int bidx;
3998252fe67bSdan const char *z3 = 0;
3999252fe67bSdan sqlite3 *db = 0;
4000252fe67bSdan sqlite3_value *pVal = 0;
4001252fe67bSdan
4002252fe67bSdan if( objc!=5 ){
4003252fe67bSdan Tcl_WrongNumArgs(interp, 1, objv, "STMT N NEW|OLD IDX");
4004252fe67bSdan return TCL_ERROR;
4005252fe67bSdan }
4006252fe67bSdan
4007252fe67bSdan if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4008252fe67bSdan if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
4009252fe67bSdan z3 = Tcl_GetString(objv[3]);
4010252fe67bSdan if( Tcl_GetIntFromObj(interp, objv[4], &bidx) ) return TCL_ERROR;
4011252fe67bSdan db = sqlite3_db_handle(pStmt);
4012252fe67bSdan
4013ddd3fe6fSdrh #ifdef SQLITE_ENABLE_PREUPDATE_HOOK
4014252fe67bSdan if( z3[0]=='n' ){
4015252fe67bSdan sqlite3_preupdate_new(db, bidx, &pVal);
4016252fe67bSdan }else if( z3[0]=='o' ){
4017252fe67bSdan sqlite3_preupdate_old(db, bidx, &pVal);
4018252fe67bSdan }else{
4019252fe67bSdan Tcl_AppendResult(interp, "expected new or old, got: ", z3, (char*)0);
4020252fe67bSdan return TCL_ERROR;
4021252fe67bSdan }
4022252fe67bSdan sqlite3_bind_value(pStmt, idx, pVal);
4023ddd3fe6fSdrh #endif
4024252fe67bSdan
4025252fe67bSdan return TCL_OK;
4026252fe67bSdan }
4027252fe67bSdan
4028252fe67bSdan /*
4029252fe67bSdan ** Usage: sqlite3_bind_value_from_select STMT N SELECT
4030252fe67bSdan **
4031252fe67bSdan ** Test the sqlite3_bind_value interface. STMT is a prepared statement.
4032252fe67bSdan ** N is the index of a wildcard in the prepared statement.
4033252fe67bSdan */
test_bind_value_from_select(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])4034252fe67bSdan static int SQLITE_TCLAPI test_bind_value_from_select(
4035252fe67bSdan void * clientData,
4036252fe67bSdan Tcl_Interp *interp,
4037252fe67bSdan int objc,
4038252fe67bSdan Tcl_Obj *CONST objv[]
4039252fe67bSdan ){
4040252fe67bSdan sqlite3_stmt *pStmt;
4041252fe67bSdan sqlite3_stmt *pStmt2;
4042252fe67bSdan int idx;
4043252fe67bSdan const char *zSql = 0;
4044252fe67bSdan sqlite3 *db = 0;
4045252fe67bSdan int rc = SQLITE_OK;
4046252fe67bSdan
4047252fe67bSdan if( objc!=4 ){
4048252fe67bSdan Tcl_WrongNumArgs(interp, 1, objv, "STMT N SELECT");
4049252fe67bSdan return TCL_ERROR;
4050252fe67bSdan }
4051252fe67bSdan
4052252fe67bSdan if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4053252fe67bSdan if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
4054252fe67bSdan zSql = Tcl_GetString(objv[3]);
4055252fe67bSdan db = sqlite3_db_handle(pStmt);
4056252fe67bSdan
4057252fe67bSdan rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt2, 0);
4058252fe67bSdan if( rc!=SQLITE_OK ){
4059252fe67bSdan Tcl_AppendResult(interp, "error in SQL: ", sqlite3_errmsg(db), (char*)0);
4060252fe67bSdan return TCL_ERROR;
4061252fe67bSdan }
4062252fe67bSdan if( sqlite3_step(pStmt2)==SQLITE_ROW ){
4063252fe67bSdan sqlite3_value *pVal = sqlite3_column_value(pStmt2, 0);
4064252fe67bSdan sqlite3_bind_value(pStmt, idx, pVal);
4065252fe67bSdan }
4066252fe67bSdan rc = sqlite3_finalize(pStmt2);
4067252fe67bSdan if( rc!=SQLITE_OK ){
4068252fe67bSdan Tcl_AppendResult(interp,
4069252fe67bSdan "error runnning SQL: ", sqlite3_errmsg(db), (char*)0
4070252fe67bSdan );
4071252fe67bSdan return TCL_ERROR;
4072252fe67bSdan }
4073252fe67bSdan
4074252fe67bSdan return TCL_OK;
4075252fe67bSdan }
4076252fe67bSdan
4077ea847f1bSdrh
40785011bb8dSdan #ifndef SQLITE_OMIT_VIRTUALTABLE
4079ea847f1bSdrh /*
4080ea847f1bSdrh ** sqlite3_carray_bind [options...] STMT NAME VALUE ...
4081ea847f1bSdrh **
4082ea847f1bSdrh ** Options:
4083ea847f1bSdrh ** -transient
4084ea847f1bSdrh ** -static
4085ea847f1bSdrh ** -int32
4086ea847f1bSdrh ** -int64
4087ea847f1bSdrh ** -double
4088ea847f1bSdrh ** -text
4089ea847f1bSdrh **
4090ea847f1bSdrh ** Each call clears static data. Called with no options does nothing
4091ea847f1bSdrh ** but clear static data.
4092ea847f1bSdrh */
test_carray_bind(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])4093ea847f1bSdrh static int SQLITE_TCLAPI test_carray_bind(
4094ea847f1bSdrh void * clientData,
4095ea847f1bSdrh Tcl_Interp *interp,
4096ea847f1bSdrh int objc,
4097ea847f1bSdrh Tcl_Obj *CONST objv[]
4098ea847f1bSdrh ){
4099ea847f1bSdrh sqlite3_stmt *pStmt;
4100ea847f1bSdrh int eType = 0; /* CARRAY_INT32 */
4101ea847f1bSdrh int nData = 0;
4102ea847f1bSdrh void *aData = 0;
4103ea847f1bSdrh int isTransient = 0;
4104ea847f1bSdrh int isStatic = 0;
4105ea847f1bSdrh int idx;
4106ea847f1bSdrh int i, j;
4107ea847f1bSdrh int rc;
4108ea847f1bSdrh void (*xDel)(void*) = sqlite3_free;
4109ea847f1bSdrh static void *aStaticData = 0;
4110ea847f1bSdrh static int nStaticData = 0;
4111ea847f1bSdrh static int eStaticType = 0;
4112ea847f1bSdrh extern int sqlite3_carray_bind(
4113ea847f1bSdrh sqlite3_stmt *pStmt,
4114ea847f1bSdrh int i,
4115ea847f1bSdrh void *aData,
4116ea847f1bSdrh int nData,
4117ea847f1bSdrh int mFlags,
4118ea847f1bSdrh void (*xDestroy)(void*)
4119ea847f1bSdrh );
4120ea847f1bSdrh
4121ea847f1bSdrh if( aStaticData ){
4122ea847f1bSdrh /* Always clear preexisting static data on every call */
4123ea847f1bSdrh if( eStaticType==3 ){
4124ea847f1bSdrh for(i=0; i<nStaticData; i++){
4125ea847f1bSdrh sqlite3_free(((char**)aStaticData)[i]);
4126ea847f1bSdrh }
4127ea847f1bSdrh }
4128ea847f1bSdrh sqlite3_free(aStaticData);
4129ea847f1bSdrh aStaticData = 0;
4130ea847f1bSdrh nStaticData = 0;
4131ea847f1bSdrh eStaticType = 0;
4132ea847f1bSdrh }
4133ea847f1bSdrh if( objc==1 ) return TCL_OK;
4134ea847f1bSdrh
4135ea847f1bSdrh for(i=1; i<objc && Tcl_GetString(objv[i])[0]=='-'; i++){
4136ea847f1bSdrh const char *z = Tcl_GetString(objv[i]);
4137ea847f1bSdrh if( strcmp(z, "-transient")==0 ){
4138ea847f1bSdrh isTransient = 1;
4139ea847f1bSdrh xDel = SQLITE_TRANSIENT;
4140ea847f1bSdrh }else
4141ea847f1bSdrh if( strcmp(z, "-static")==0 ){
4142ea847f1bSdrh isStatic = 1;
4143ea847f1bSdrh xDel = SQLITE_STATIC;
4144ea847f1bSdrh }else
4145ea847f1bSdrh if( strcmp(z, "-int32")==0 ){
4146ea847f1bSdrh eType = 0; /* CARRAY_INT32 */
4147ea847f1bSdrh }else
4148ea847f1bSdrh if( strcmp(z, "-int64")==0 ){
4149ea847f1bSdrh eType = 1; /* CARRAY_INT64 */
4150ea847f1bSdrh }else
4151ea847f1bSdrh if( strcmp(z, "-double")==0 ){
4152ea847f1bSdrh eType = 2; /* CARRAY_DOUBLE */
4153ea847f1bSdrh }else
4154ea847f1bSdrh if( strcmp(z, "-text")==0 ){
4155ea847f1bSdrh eType = 3; /* CARRAY_TEXT */
4156ea847f1bSdrh }else
4157ea847f1bSdrh if( strcmp(z, "--")==0 ){
4158ea847f1bSdrh break;
4159ea847f1bSdrh }else
4160ea847f1bSdrh {
4161ea847f1bSdrh Tcl_AppendResult(interp, "unknown option: ", z, (char*)0);
4162ea847f1bSdrh return TCL_ERROR;
4163ea847f1bSdrh }
4164ea847f1bSdrh }
4165ea847f1bSdrh if( eType==3 && !isStatic && !isTransient ){
4166ea847f1bSdrh Tcl_AppendResult(interp, "text data must be either -static or -transient",
4167ea847f1bSdrh (char*)0);
4168ea847f1bSdrh return TCL_ERROR;
4169ea847f1bSdrh }
4170ea847f1bSdrh if( isStatic && isTransient ){
4171ea847f1bSdrh Tcl_AppendResult(interp, "cannot be both -static and -transient",
4172ea847f1bSdrh (char*)0);
4173ea847f1bSdrh return TCL_ERROR;
4174ea847f1bSdrh }
4175ea847f1bSdrh if( objc-i < 2 ){
4176ea847f1bSdrh Tcl_WrongNumArgs(interp, 1, objv, "[OPTIONS] STMT IDX VALUE ...");
4177ea847f1bSdrh return TCL_ERROR;
4178ea847f1bSdrh }
4179ea847f1bSdrh if( getStmtPointer(interp, Tcl_GetString(objv[i]), &pStmt) ) return TCL_ERROR;
4180ea847f1bSdrh i++;
4181ea847f1bSdrh if( Tcl_GetIntFromObj(interp, objv[i], &idx) ) return TCL_ERROR;
4182ea847f1bSdrh i++;
4183ea847f1bSdrh nData = objc - i;
4184ea847f1bSdrh switch( eType + 4*(nData<=0) ){
4185ea847f1bSdrh case 0: { /* INT32 */
4186ea847f1bSdrh int *a = sqlite3_malloc( sizeof(int)*nData );
4187ea847f1bSdrh if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; }
4188ea847f1bSdrh for(j=0; j<nData; j++){
4189ea847f1bSdrh int v;
4190ea847f1bSdrh if( Tcl_GetIntFromObj(interp, objv[i+j], &v) ){
4191ea847f1bSdrh sqlite3_free(a);
4192ea847f1bSdrh return TCL_ERROR;
4193ea847f1bSdrh }
4194ea847f1bSdrh a[j] = v;
4195ea847f1bSdrh }
4196ea847f1bSdrh aData = a;
4197ea847f1bSdrh break;
4198ea847f1bSdrh }
4199ea847f1bSdrh case 1: { /* INT64 */
4200ea847f1bSdrh sqlite3_int64 *a = sqlite3_malloc( sizeof(sqlite3_int64)*nData );
4201ea847f1bSdrh if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; }
4202ea847f1bSdrh for(j=0; j<nData; j++){
4203ea847f1bSdrh Tcl_WideInt v;
4204ea847f1bSdrh if( Tcl_GetWideIntFromObj(interp, objv[i+j], &v) ){
4205ea847f1bSdrh sqlite3_free(a);
4206ea847f1bSdrh return TCL_ERROR;
4207ea847f1bSdrh }
4208ea847f1bSdrh a[j] = v;
4209ea847f1bSdrh }
4210ea847f1bSdrh aData = a;
4211ea847f1bSdrh break;
4212ea847f1bSdrh }
4213ea847f1bSdrh case 2: { /* DOUBLE */
4214ea847f1bSdrh double *a = sqlite3_malloc( sizeof(double)*nData );
4215ea847f1bSdrh if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; }
4216ea847f1bSdrh for(j=0; j<nData; j++){
4217ea847f1bSdrh double v;
4218ea847f1bSdrh if( Tcl_GetDoubleFromObj(interp, objv[i+j], &v) ){
4219ea847f1bSdrh sqlite3_free(a);
4220ea847f1bSdrh return TCL_ERROR;
4221ea847f1bSdrh }
4222ea847f1bSdrh a[j] = v;
4223ea847f1bSdrh }
4224ea847f1bSdrh aData = a;
4225ea847f1bSdrh break;
4226ea847f1bSdrh }
4227ea847f1bSdrh case 3: { /* TEXT */
4228ea847f1bSdrh char **a = sqlite3_malloc( sizeof(char*)*nData );
4229ea847f1bSdrh if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; }
4230ea847f1bSdrh for(j=0; j<nData; j++){
4231ea847f1bSdrh const char *v = Tcl_GetString(objv[i+j]);
4232ea847f1bSdrh a[j] = sqlite3_mprintf("%s", v);
4233ea847f1bSdrh }
4234ea847f1bSdrh aData = a;
4235ea847f1bSdrh break;
4236ea847f1bSdrh }
4237ea847f1bSdrh case 4: { /* nData==0 */
4238ea847f1bSdrh aData = "";
4239ea847f1bSdrh xDel = SQLITE_STATIC;
4240ea847f1bSdrh isTransient = 0;
4241ea847f1bSdrh isStatic = 0;
4242ea847f1bSdrh break;
4243ea847f1bSdrh }
4244ea847f1bSdrh }
4245ea847f1bSdrh if( isStatic ){
4246ea847f1bSdrh aStaticData = aData;
4247ea847f1bSdrh nStaticData = nData;
4248ea847f1bSdrh eStaticType = eType;
4249ea847f1bSdrh }
4250ea847f1bSdrh rc = sqlite3_carray_bind(pStmt, idx, aData, nData, eType, xDel);
4251ea847f1bSdrh if( isTransient ){
4252ea847f1bSdrh if( eType==3 ){
4253ea847f1bSdrh for(i=0; i<nData; i++) sqlite3_free(((char**)aData)[i]);
4254ea847f1bSdrh }
4255ea847f1bSdrh sqlite3_free(aData);
4256ea847f1bSdrh }
4257ea847f1bSdrh carray_bind_done:
4258ea847f1bSdrh if( rc ){
4259ea847f1bSdrh Tcl_AppendResult(interp, sqlite3_errstr(rc), (char*)0);
4260ea847f1bSdrh return TCL_ERROR;
4261ea847f1bSdrh }
4262ea847f1bSdrh return TCL_OK;
4263ea847f1bSdrh }
42645011bb8dSdan #endif /* SQLITE_OMIT_VIRTUALTABLE */
4265ea847f1bSdrh
426699ee3600Sdrh /*
426775f6a032Sdrh ** Usage: sqlite3_bind_parameter_count STMT
426875f6a032Sdrh **
426975f6a032Sdrh ** Return the number of wildcards in the given statement.
427075f6a032Sdrh */
test_bind_parameter_count(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])42717617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_parameter_count(
427275f6a032Sdrh void * clientData,
427375f6a032Sdrh Tcl_Interp *interp,
427475f6a032Sdrh int objc,
427575f6a032Sdrh Tcl_Obj *CONST objv[]
427675f6a032Sdrh ){
427775f6a032Sdrh sqlite3_stmt *pStmt;
427875f6a032Sdrh
427975f6a032Sdrh if( objc!=2 ){
428075f6a032Sdrh Tcl_WrongNumArgs(interp, 1, objv, "STMT");
428175f6a032Sdrh return TCL_ERROR;
428275f6a032Sdrh }
428375f6a032Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
428475f6a032Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
428575f6a032Sdrh return TCL_OK;
428675f6a032Sdrh }
428775f6a032Sdrh
428875f6a032Sdrh /*
4289895d7472Sdrh ** Usage: sqlite3_bind_parameter_name STMT N
4290895d7472Sdrh **
4291895d7472Sdrh ** Return the name of the Nth wildcard. The first wildcard is 1.
4292895d7472Sdrh ** An empty string is returned if N is out of range or if the wildcard
4293895d7472Sdrh ** is nameless.
4294895d7472Sdrh */
test_bind_parameter_name(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])42957617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_parameter_name(
4296895d7472Sdrh void * clientData,
4297895d7472Sdrh Tcl_Interp *interp,
4298895d7472Sdrh int objc,
4299895d7472Sdrh Tcl_Obj *CONST objv[]
4300895d7472Sdrh ){
4301895d7472Sdrh sqlite3_stmt *pStmt;
4302895d7472Sdrh int i;
4303895d7472Sdrh
4304895d7472Sdrh if( objc!=3 ){
4305895d7472Sdrh Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
4306895d7472Sdrh return TCL_ERROR;
4307895d7472Sdrh }
4308895d7472Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4309895d7472Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
4310895d7472Sdrh Tcl_SetObjResult(interp,
4311895d7472Sdrh Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
4312895d7472Sdrh );
4313895d7472Sdrh return TCL_OK;
4314895d7472Sdrh }
4315895d7472Sdrh
4316895d7472Sdrh /*
4317fa6bc000Sdrh ** Usage: sqlite3_bind_parameter_index STMT NAME
4318fa6bc000Sdrh **
4319fa6bc000Sdrh ** Return the index of the wildcard called NAME. Return 0 if there is
4320fa6bc000Sdrh ** no such wildcard.
4321fa6bc000Sdrh */
test_bind_parameter_index(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])43227617e4a8Smistachkin static int SQLITE_TCLAPI test_bind_parameter_index(
4323fa6bc000Sdrh void * clientData,
4324fa6bc000Sdrh Tcl_Interp *interp,
4325fa6bc000Sdrh int objc,
4326fa6bc000Sdrh Tcl_Obj *CONST objv[]
4327fa6bc000Sdrh ){
4328fa6bc000Sdrh sqlite3_stmt *pStmt;
4329fa6bc000Sdrh
4330fa6bc000Sdrh if( objc!=3 ){
4331fa6bc000Sdrh Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
4332fa6bc000Sdrh return TCL_ERROR;
4333fa6bc000Sdrh }
4334fa6bc000Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4335fa6bc000Sdrh Tcl_SetObjResult(interp,
4336fa6bc000Sdrh Tcl_NewIntObj(
4337fa6bc000Sdrh sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
4338fa6bc000Sdrh )
4339fa6bc000Sdrh );
4340fa6bc000Sdrh return TCL_OK;
4341fa6bc000Sdrh }
4342fa6bc000Sdrh
4343fa6bc000Sdrh /*
4344600dd0baSdanielk1977 ** Usage: sqlite3_clear_bindings STMT
4345600dd0baSdanielk1977 **
4346600dd0baSdanielk1977 */
test_clear_bindings(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])43477617e4a8Smistachkin static int SQLITE_TCLAPI test_clear_bindings(
4348600dd0baSdanielk1977 void * clientData,
4349600dd0baSdanielk1977 Tcl_Interp *interp,
4350600dd0baSdanielk1977 int objc,
4351600dd0baSdanielk1977 Tcl_Obj *CONST objv[]
4352600dd0baSdanielk1977 ){
4353600dd0baSdanielk1977 sqlite3_stmt *pStmt;
4354600dd0baSdanielk1977
4355600dd0baSdanielk1977 if( objc!=2 ){
4356600dd0baSdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
4357600dd0baSdanielk1977 return TCL_ERROR;
4358600dd0baSdanielk1977 }
4359600dd0baSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4360600dd0baSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
4361600dd0baSdanielk1977 return TCL_OK;
4362600dd0baSdanielk1977 }
4363f9cb7f58Sdrh
4364f9cb7f58Sdrh /*
4365f9cb7f58Sdrh ** Usage: sqlite3_sleep MILLISECONDS
4366f9cb7f58Sdrh */
test_sleep(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])43677617e4a8Smistachkin static int SQLITE_TCLAPI test_sleep(
4368f9cb7f58Sdrh void * clientData,
4369f9cb7f58Sdrh Tcl_Interp *interp,
4370f9cb7f58Sdrh int objc,
4371f9cb7f58Sdrh Tcl_Obj *CONST objv[]
4372f9cb7f58Sdrh ){
4373f9cb7f58Sdrh int ms;
4374f9cb7f58Sdrh
4375f9cb7f58Sdrh if( objc!=2 ){
4376f9cb7f58Sdrh Tcl_WrongNumArgs(interp, 1, objv, "MILLISECONDS");
4377f9cb7f58Sdrh return TCL_ERROR;
4378f9cb7f58Sdrh }
4379f9cb7f58Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &ms) ){
4380f9cb7f58Sdrh return TCL_ERROR;
4381f9cb7f58Sdrh }
4382f9cb7f58Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(ms)));
4383f9cb7f58Sdrh return TCL_OK;
4384f9cb7f58Sdrh }
4385600dd0baSdanielk1977
4386600dd0baSdanielk1977 /*
438799dfe5ebSdrh ** Usage: sqlite3_extended_errcode DB
438899dfe5ebSdrh **
438999dfe5ebSdrh ** Return the string representation of the most recent sqlite3_* API
439099dfe5ebSdrh ** error code. e.g. "SQLITE_ERROR".
439199dfe5ebSdrh */
test_ex_errcode(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])43927617e4a8Smistachkin static int SQLITE_TCLAPI test_ex_errcode(
439399dfe5ebSdrh void * clientData,
439499dfe5ebSdrh Tcl_Interp *interp,
439599dfe5ebSdrh int objc,
439699dfe5ebSdrh Tcl_Obj *CONST objv[]
439799dfe5ebSdrh ){
439899dfe5ebSdrh sqlite3 *db;
439999dfe5ebSdrh int rc;
440099dfe5ebSdrh
440199dfe5ebSdrh if( objc!=2 ){
440299dfe5ebSdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
440399dfe5ebSdrh Tcl_GetString(objv[0]), " DB", 0);
440499dfe5ebSdrh return TCL_ERROR;
440599dfe5ebSdrh }
440699dfe5ebSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
440799dfe5ebSdrh rc = sqlite3_extended_errcode(db);
440899dfe5ebSdrh Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0);
440999dfe5ebSdrh return TCL_OK;
441099dfe5ebSdrh }
441199dfe5ebSdrh
441299dfe5ebSdrh
441399dfe5ebSdrh /*
44146622cce3Sdanielk1977 ** Usage: sqlite3_errcode DB
44156622cce3Sdanielk1977 **
44166622cce3Sdanielk1977 ** Return the string representation of the most recent sqlite3_* API
44176622cce3Sdanielk1977 ** error code. e.g. "SQLITE_ERROR".
44186622cce3Sdanielk1977 */
test_errcode(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])44197617e4a8Smistachkin static int SQLITE_TCLAPI test_errcode(
44206622cce3Sdanielk1977 void * clientData,
44216622cce3Sdanielk1977 Tcl_Interp *interp,
44226622cce3Sdanielk1977 int objc,
44236622cce3Sdanielk1977 Tcl_Obj *CONST objv[]
44246622cce3Sdanielk1977 ){
44256622cce3Sdanielk1977 sqlite3 *db;
44264ac285a1Sdrh int rc;
44276622cce3Sdanielk1977
44286622cce3Sdanielk1977 if( objc!=2 ){
44296622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
44306622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0);
44316622cce3Sdanielk1977 return TCL_ERROR;
44326622cce3Sdanielk1977 }
44336622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
44344ac285a1Sdrh rc = sqlite3_errcode(db);
443599dfe5ebSdrh Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0);
44366622cce3Sdanielk1977 return TCL_OK;
44376622cce3Sdanielk1977 }
44386622cce3Sdanielk1977
44396622cce3Sdanielk1977 /*
44400410302eSdanielk1977 ** Usage: sqlite3_errmsg DB
44416622cce3Sdanielk1977 **
44426622cce3Sdanielk1977 ** Returns the UTF-8 representation of the error message string for the
44436622cce3Sdanielk1977 ** most recent sqlite3_* API call.
44446622cce3Sdanielk1977 */
test_errmsg(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])44457617e4a8Smistachkin static int SQLITE_TCLAPI test_errmsg(
44466622cce3Sdanielk1977 void * clientData,
44476622cce3Sdanielk1977 Tcl_Interp *interp,
44486622cce3Sdanielk1977 int objc,
44496622cce3Sdanielk1977 Tcl_Obj *CONST objv[]
44506622cce3Sdanielk1977 ){
44519bb575fdSdrh sqlite3 *db;
44526622cce3Sdanielk1977 const char *zErr;
44536622cce3Sdanielk1977
44546622cce3Sdanielk1977 if( objc!=2 ){
44556622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
44566622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0);
44576622cce3Sdanielk1977 return TCL_ERROR;
44586622cce3Sdanielk1977 }
44596622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
44606622cce3Sdanielk1977
44616622cce3Sdanielk1977 zErr = sqlite3_errmsg(db);
44626622cce3Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
44636622cce3Sdanielk1977 return TCL_OK;
44646622cce3Sdanielk1977 }
44656622cce3Sdanielk1977
4466f62641e9Sdrh
4467f62641e9Sdrh /*
4468f62641e9Sdrh ** Usage: sqlite3_error_offset DB
4469f62641e9Sdrh **
4470f62641e9Sdrh ** Return the byte offset into the input UTF8 SQL for the most recent
4471f62641e9Sdrh ** error, or -1 of the error does not refer to a specific token.
4472f62641e9Sdrh */
test_error_offset(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])4473f62641e9Sdrh static int SQLITE_TCLAPI test_error_offset(
4474f62641e9Sdrh void * clientData,
4475f62641e9Sdrh Tcl_Interp *interp,
4476f62641e9Sdrh int objc,
4477f62641e9Sdrh Tcl_Obj *CONST objv[]
4478f62641e9Sdrh ){
4479f62641e9Sdrh sqlite3 *db;
4480f62641e9Sdrh int iByteOffset;
4481f62641e9Sdrh
4482f62641e9Sdrh if( objc!=2 ){
4483f62641e9Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
4484f62641e9Sdrh Tcl_GetString(objv[0]), " DB", 0);
4485f62641e9Sdrh return TCL_ERROR;
4486f62641e9Sdrh }
4487f62641e9Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4488f62641e9Sdrh
4489f62641e9Sdrh iByteOffset = sqlite3_error_offset(db);
44909169d0cbSdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(iByteOffset));
4491f62641e9Sdrh return TCL_OK;
4492f62641e9Sdrh }
4493f62641e9Sdrh
44946622cce3Sdanielk1977 /*
44956622cce3Sdanielk1977 ** Usage: test_errmsg16 DB
44966622cce3Sdanielk1977 **
44976622cce3Sdanielk1977 ** Returns the UTF-16 representation of the error message string for the
44986622cce3Sdanielk1977 ** most recent sqlite3_* API call. This is a byte array object at the TCL
44996622cce3Sdanielk1977 ** level, and it includes the 0x00 0x00 terminator bytes at the end of the
45006622cce3Sdanielk1977 ** UTF-16 string.
45016622cce3Sdanielk1977 */
test_errmsg16(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])45027617e4a8Smistachkin static int SQLITE_TCLAPI test_errmsg16(
45036622cce3Sdanielk1977 void * clientData,
45046622cce3Sdanielk1977 Tcl_Interp *interp,
45056622cce3Sdanielk1977 int objc,
45066622cce3Sdanielk1977 Tcl_Obj *CONST objv[]
45076622cce3Sdanielk1977 ){
45085436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
45099bb575fdSdrh sqlite3 *db;
45106622cce3Sdanielk1977 const void *zErr;
4511aed382f9Sdrh const char *z;
4512950f054cSdanielk1977 int bytes = 0;
45136622cce3Sdanielk1977
45146622cce3Sdanielk1977 if( objc!=2 ){
45156622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
45166622cce3Sdanielk1977 Tcl_GetString(objv[0]), " DB", 0);
45176622cce3Sdanielk1977 return TCL_ERROR;
45186622cce3Sdanielk1977 }
45196622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
45206622cce3Sdanielk1977
45216622cce3Sdanielk1977 zErr = sqlite3_errmsg16(db);
4522950f054cSdanielk1977 if( zErr ){
4523aed382f9Sdrh z = zErr;
4524aed382f9Sdrh for(bytes=0; z[bytes] || z[bytes+1]; bytes+=2){}
4525950f054cSdanielk1977 }
45266622cce3Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
45275436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
45286622cce3Sdanielk1977 return TCL_OK;
45296622cce3Sdanielk1977 }
45306622cce3Sdanielk1977
45316622cce3Sdanielk1977 /*
45321c767f0dSdrh ** Usage: sqlite3_prepare DB sql bytes ?tailvar?
45336622cce3Sdanielk1977 **
45346622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
45356622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global
45366622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A
45376622cce3Sdanielk1977 ** STMT handle is returned.
45386622cce3Sdanielk1977 */
test_prepare(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])45397617e4a8Smistachkin static int SQLITE_TCLAPI test_prepare(
45406622cce3Sdanielk1977 void * clientData,
45416622cce3Sdanielk1977 Tcl_Interp *interp,
45426622cce3Sdanielk1977 int objc,
45436622cce3Sdanielk1977 Tcl_Obj *CONST objv[]
45446622cce3Sdanielk1977 ){
45456622cce3Sdanielk1977 sqlite3 *db;
45466622cce3Sdanielk1977 const char *zSql;
45476622cce3Sdanielk1977 int bytes;
45486622cce3Sdanielk1977 const char *zTail = 0;
45496622cce3Sdanielk1977 sqlite3_stmt *pStmt = 0;
45506622cce3Sdanielk1977 char zBuf[50];
45514ad1713cSdanielk1977 int rc;
45526622cce3Sdanielk1977
45531c767f0dSdrh if( objc!=5 && objc!=4 ){
45546622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
45551c767f0dSdrh Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
45566622cce3Sdanielk1977 return TCL_ERROR;
45576622cce3Sdanielk1977 }
45586622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
45596622cce3Sdanielk1977 zSql = Tcl_GetString(objv[2]);
45606622cce3Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
45616622cce3Sdanielk1977
45621c767f0dSdrh rc = sqlite3_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
4563937d0deaSdan Tcl_ResetResult(interp);
4564c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
45651c767f0dSdrh if( zTail && objc>=5 ){
45666622cce3Sdanielk1977 if( bytes>=0 ){
456783cc1392Sdrh bytes = bytes - (int)(zTail-zSql);
45686622cce3Sdanielk1977 }
45697da5fcb0Sdrh if( (int)strlen(zTail)<bytes ){
457083cc1392Sdrh bytes = (int)strlen(zTail);
45713a2c8c8bSdanielk1977 }
45726622cce3Sdanielk1977 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
45736622cce3Sdanielk1977 }
45744ad1713cSdanielk1977 if( rc!=SQLITE_OK ){
45754ad1713cSdanielk1977 assert( pStmt==0 );
457665545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
45774ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
45784ad1713cSdanielk1977 return TCL_ERROR;
45794ad1713cSdanielk1977 }
45806622cce3Sdanielk1977
45814ad1713cSdanielk1977 if( pStmt ){
458264b1bea3Sdrh if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
45836622cce3Sdanielk1977 Tcl_AppendResult(interp, zBuf, 0);
45844ad1713cSdanielk1977 }
45856622cce3Sdanielk1977 return TCL_OK;
45866622cce3Sdanielk1977 }
45876622cce3Sdanielk1977
45886622cce3Sdanielk1977 /*
45891c767f0dSdrh ** Usage: sqlite3_prepare_v2 DB sql bytes ?tailvar?
4590b900aaf3Sdrh **
4591b900aaf3Sdrh ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
4592b900aaf3Sdrh ** database handle <DB>. The parameter <tailval> is the name of a global
4593b900aaf3Sdrh ** variable that is set to the unused portion of <sql> (if any). A
4594b900aaf3Sdrh ** STMT handle is returned.
4595b900aaf3Sdrh */
test_prepare_v2(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])45967617e4a8Smistachkin static int SQLITE_TCLAPI test_prepare_v2(
4597b900aaf3Sdrh void * clientData,
4598b900aaf3Sdrh Tcl_Interp *interp,
4599b900aaf3Sdrh int objc,
4600b900aaf3Sdrh Tcl_Obj *CONST objv[]
4601b900aaf3Sdrh ){
4602b900aaf3Sdrh sqlite3 *db;
4603b900aaf3Sdrh const char *zSql;
4604d89b834fSdan char *zCopy = 0; /* malloc() copy of zSql */
4605b900aaf3Sdrh int bytes;
4606b900aaf3Sdrh const char *zTail = 0;
46078bee11a4Smistachkin const char **pzTail;
4608b900aaf3Sdrh sqlite3_stmt *pStmt = 0;
4609b900aaf3Sdrh char zBuf[50];
4610b900aaf3Sdrh int rc;
4611b900aaf3Sdrh
46121c767f0dSdrh if( objc!=5 && objc!=4 ){
4613b900aaf3Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
4614b900aaf3Sdrh Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
4615b900aaf3Sdrh return TCL_ERROR;
4616b900aaf3Sdrh }
4617b900aaf3Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4618b900aaf3Sdrh zSql = Tcl_GetString(objv[2]);
4619b900aaf3Sdrh if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
4620b900aaf3Sdrh
4621d89b834fSdan /* Instead of using zSql directly, make a copy into a buffer obtained
4622d89b834fSdan ** directly from malloc(). The idea is to make it easier for valgrind
4623d89b834fSdan ** to spot buffer overreads. */
4624d89b834fSdan if( bytes>=0 ){
4625d89b834fSdan zCopy = malloc(bytes);
4626d89b834fSdan memcpy(zCopy, zSql, bytes);
4627d89b834fSdan }else{
46282c3abeb8Sdrh int n = (int)strlen(zSql) + 1;
4629d89b834fSdan zCopy = malloc(n);
4630d89b834fSdan memcpy(zCopy, zSql, n);
4631d89b834fSdan }
46328bee11a4Smistachkin pzTail = objc>=5 ? &zTail : 0;
46338bee11a4Smistachkin rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, pzTail);
4634112e1740Sdan if( objc>=5 ){
4635d89b834fSdan zTail = &zSql[(zTail - zCopy)];
4636112e1740Sdan }
4637112e1740Sdan free(zCopy);
4638d89b834fSdan
46397e29e956Sdanielk1977 assert(rc==SQLITE_OK || pStmt==0);
4640937d0deaSdan Tcl_ResetResult(interp);
4641b900aaf3Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
4642112e1740Sdan if( rc==SQLITE_OK && objc>=5 && zTail ){
4643b900aaf3Sdrh if( bytes>=0 ){
464483cc1392Sdrh bytes = bytes - (int)(zTail-zSql);
4645b900aaf3Sdrh }
4646b900aaf3Sdrh Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
4647b900aaf3Sdrh }
4648b900aaf3Sdrh if( rc!=SQLITE_OK ){
4649b900aaf3Sdrh assert( pStmt==0 );
465065545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
4651b900aaf3Sdrh Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
4652b900aaf3Sdrh return TCL_ERROR;
4653b900aaf3Sdrh }
4654b900aaf3Sdrh
4655b900aaf3Sdrh if( pStmt ){
4656b900aaf3Sdrh if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
4657b900aaf3Sdrh Tcl_AppendResult(interp, zBuf, 0);
4658b900aaf3Sdrh }
4659b900aaf3Sdrh return TCL_OK;
4660b900aaf3Sdrh }
4661b900aaf3Sdrh
4662b900aaf3Sdrh /*
46638bee11a4Smistachkin ** Usage: sqlite3_prepare_v3 DB sql bytes flags ?tailvar?
46648bee11a4Smistachkin **
46658bee11a4Smistachkin ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
46668bee11a4Smistachkin ** database handle <DB> and flags <flags>. The parameter <tailval> is
46678bee11a4Smistachkin ** the name of a global variable that is set to the unused portion of
46688bee11a4Smistachkin ** <sql> (if any). A STMT handle is returned.
46698bee11a4Smistachkin */
test_prepare_v3(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])46708bee11a4Smistachkin static int SQLITE_TCLAPI test_prepare_v3(
46718bee11a4Smistachkin void * clientData,
46728bee11a4Smistachkin Tcl_Interp *interp,
46738bee11a4Smistachkin int objc,
46748bee11a4Smistachkin Tcl_Obj *CONST objv[]
46758bee11a4Smistachkin ){
46768bee11a4Smistachkin sqlite3 *db;
46778bee11a4Smistachkin const char *zSql;
46788bee11a4Smistachkin char *zCopy = 0; /* malloc() copy of zSql */
46798bee11a4Smistachkin int bytes, flags;
46808bee11a4Smistachkin const char *zTail = 0;
46818bee11a4Smistachkin const char **pzTail;
46828bee11a4Smistachkin sqlite3_stmt *pStmt = 0;
46838bee11a4Smistachkin char zBuf[50];
46848bee11a4Smistachkin int rc;
46858bee11a4Smistachkin
46868bee11a4Smistachkin if( objc!=6 && objc!=5 ){
46878bee11a4Smistachkin Tcl_AppendResult(interp, "wrong # args: should be \"",
46888bee11a4Smistachkin Tcl_GetString(objv[0]), " DB sql bytes flags tailvar", 0);
46898bee11a4Smistachkin return TCL_ERROR;
46908bee11a4Smistachkin }
46918bee11a4Smistachkin if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
46928bee11a4Smistachkin zSql = Tcl_GetString(objv[2]);
46938bee11a4Smistachkin if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
46948bee11a4Smistachkin if( Tcl_GetIntFromObj(interp, objv[4], &flags) ) return TCL_ERROR;
46958bee11a4Smistachkin
46968bee11a4Smistachkin /* Instead of using zSql directly, make a copy into a buffer obtained
46978bee11a4Smistachkin ** directly from malloc(). The idea is to make it easier for valgrind
46988bee11a4Smistachkin ** to spot buffer overreads. */
46998bee11a4Smistachkin if( bytes>=0 ){
47008bee11a4Smistachkin zCopy = malloc(bytes);
47018bee11a4Smistachkin memcpy(zCopy, zSql, bytes);
47028bee11a4Smistachkin }else{
47038bee11a4Smistachkin int n = (int)strlen(zSql) + 1;
47048bee11a4Smistachkin zCopy = malloc(n);
47058bee11a4Smistachkin memcpy(zCopy, zSql, n);
47068bee11a4Smistachkin }
47078bee11a4Smistachkin pzTail = objc>=6 ? &zTail : 0;
47088bee11a4Smistachkin rc = sqlite3_prepare_v3(db, zCopy, bytes, (unsigned int)flags,&pStmt,pzTail);
47098bee11a4Smistachkin free(zCopy);
47108bee11a4Smistachkin zTail = &zSql[(zTail - zCopy)];
47118bee11a4Smistachkin
47128bee11a4Smistachkin assert(rc==SQLITE_OK || pStmt==0);
47138bee11a4Smistachkin Tcl_ResetResult(interp);
47148bee11a4Smistachkin if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
47158bee11a4Smistachkin if( rc==SQLITE_OK && zTail && objc>=6 ){
47168bee11a4Smistachkin if( bytes>=0 ){
47178bee11a4Smistachkin bytes = bytes - (int)(zTail-zSql);
47188bee11a4Smistachkin }
47198bee11a4Smistachkin Tcl_ObjSetVar2(interp, objv[5], 0, Tcl_NewStringObj(zTail, bytes), 0);
47208bee11a4Smistachkin }
47218bee11a4Smistachkin if( rc!=SQLITE_OK ){
47228bee11a4Smistachkin assert( pStmt==0 );
47238bee11a4Smistachkin sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
47248bee11a4Smistachkin Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
47258bee11a4Smistachkin return TCL_ERROR;
47268bee11a4Smistachkin }
47278bee11a4Smistachkin
47288bee11a4Smistachkin if( pStmt ){
47298bee11a4Smistachkin if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
47308bee11a4Smistachkin Tcl_AppendResult(interp, zBuf, 0);
47318bee11a4Smistachkin }
47328bee11a4Smistachkin return TCL_OK;
47338bee11a4Smistachkin }
47348bee11a4Smistachkin
47358bee11a4Smistachkin /*
47364837f531Sdrh ** Usage: sqlite3_prepare_tkt3134 DB
47374837f531Sdrh **
47384837f531Sdrh ** Generate a prepared statement for a zero-byte string as a test
473960ec914cSpeter.d.reid ** for ticket #3134. The string should be preceded by a zero byte.
47404837f531Sdrh */
test_prepare_tkt3134(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])47417617e4a8Smistachkin static int SQLITE_TCLAPI test_prepare_tkt3134(
47424837f531Sdrh void * clientData,
47434837f531Sdrh Tcl_Interp *interp,
47444837f531Sdrh int objc,
47454837f531Sdrh Tcl_Obj *CONST objv[]
47464837f531Sdrh ){
47474837f531Sdrh sqlite3 *db;
47484837f531Sdrh static const char zSql[] = "\000SELECT 1";
47494837f531Sdrh sqlite3_stmt *pStmt = 0;
47504837f531Sdrh char zBuf[50];
47514837f531Sdrh int rc;
47524837f531Sdrh
47534837f531Sdrh if( objc!=2 ){
47544837f531Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
47554837f531Sdrh Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
47564837f531Sdrh return TCL_ERROR;
47574837f531Sdrh }
47584837f531Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
47594837f531Sdrh rc = sqlite3_prepare_v2(db, &zSql[1], 0, &pStmt, 0);
47604837f531Sdrh assert(rc==SQLITE_OK || pStmt==0);
47614837f531Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
47624837f531Sdrh if( rc!=SQLITE_OK ){
47634837f531Sdrh assert( pStmt==0 );
476465545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
47654837f531Sdrh Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
47664837f531Sdrh return TCL_ERROR;
47674837f531Sdrh }
47684837f531Sdrh
47694837f531Sdrh if( pStmt ){
47704837f531Sdrh if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
47714837f531Sdrh Tcl_AppendResult(interp, zBuf, 0);
47724837f531Sdrh }
47734837f531Sdrh return TCL_OK;
47744837f531Sdrh }
47754837f531Sdrh
47764837f531Sdrh /*
4777b900aaf3Sdrh ** Usage: sqlite3_prepare16 DB sql bytes tailvar
47786622cce3Sdanielk1977 **
47796622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
47806622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global
47816622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A
47826622cce3Sdanielk1977 ** STMT handle is returned.
47836622cce3Sdanielk1977 */
test_prepare16(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])47847617e4a8Smistachkin static int SQLITE_TCLAPI test_prepare16(
47856622cce3Sdanielk1977 void * clientData,
47866622cce3Sdanielk1977 Tcl_Interp *interp,
47876622cce3Sdanielk1977 int objc,
47886622cce3Sdanielk1977 Tcl_Obj *CONST objv[]
47896622cce3Sdanielk1977 ){
47905436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
47916622cce3Sdanielk1977 sqlite3 *db;
47926622cce3Sdanielk1977 const void *zSql;
47936622cce3Sdanielk1977 const void *zTail = 0;
47946622cce3Sdanielk1977 Tcl_Obj *pTail = 0;
47956622cce3Sdanielk1977 sqlite3_stmt *pStmt = 0;
47966622cce3Sdanielk1977 char zBuf[50];
4797c60d0446Sdrh int rc;
47986622cce3Sdanielk1977 int bytes; /* The integer specified as arg 3 */
47996622cce3Sdanielk1977 int objlen; /* The byte-array length of arg 2 */
48006622cce3Sdanielk1977
48011c767f0dSdrh if( objc!=5 && objc!=4 ){
48026622cce3Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
48031c767f0dSdrh Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
48046622cce3Sdanielk1977 return TCL_ERROR;
48056622cce3Sdanielk1977 }
48066622cce3Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
48076622cce3Sdanielk1977 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
48086622cce3Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
48096622cce3Sdanielk1977
48101c767f0dSdrh rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
4811c60d0446Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
4812c60d0446Sdrh if( rc ){
48136622cce3Sdanielk1977 return TCL_ERROR;
48146622cce3Sdanielk1977 }
48156622cce3Sdanielk1977
48161c767f0dSdrh if( objc>=5 ){
48176622cce3Sdanielk1977 if( zTail ){
481883cc1392Sdrh objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql);
48196622cce3Sdanielk1977 }else{
48206622cce3Sdanielk1977 objlen = 0;
48216622cce3Sdanielk1977 }
48226622cce3Sdanielk1977 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
48236622cce3Sdanielk1977 Tcl_IncrRefCount(pTail);
48246622cce3Sdanielk1977 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
48254ad1713cSdanielk1977 Tcl_DecrRefCount(pTail);
48261c767f0dSdrh }
48276622cce3Sdanielk1977
48284ad1713cSdanielk1977 if( pStmt ){
482964b1bea3Sdrh if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
48304ad1713cSdanielk1977 }
48316622cce3Sdanielk1977 Tcl_AppendResult(interp, zBuf, 0);
48325436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
48336622cce3Sdanielk1977 return TCL_OK;
48346622cce3Sdanielk1977 }
48356622cce3Sdanielk1977
48364ad1713cSdanielk1977 /*
48371c767f0dSdrh ** Usage: sqlite3_prepare16_v2 DB sql bytes ?tailvar?
4838b900aaf3Sdrh **
4839b900aaf3Sdrh ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
4840b900aaf3Sdrh ** database handle <DB>. The parameter <tailval> is the name of a global
4841b900aaf3Sdrh ** variable that is set to the unused portion of <sql> (if any). A
4842b900aaf3Sdrh ** STMT handle is returned.
4843b900aaf3Sdrh */
test_prepare16_v2(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])48447617e4a8Smistachkin static int SQLITE_TCLAPI test_prepare16_v2(
4845b900aaf3Sdrh void * clientData,
4846b900aaf3Sdrh Tcl_Interp *interp,
4847b900aaf3Sdrh int objc,
4848b900aaf3Sdrh Tcl_Obj *CONST objv[]
4849b900aaf3Sdrh ){
4850b900aaf3Sdrh #ifndef SQLITE_OMIT_UTF16
4851b900aaf3Sdrh sqlite3 *db;
4852b900aaf3Sdrh const void *zSql;
4853b900aaf3Sdrh const void *zTail = 0;
4854b900aaf3Sdrh Tcl_Obj *pTail = 0;
4855b900aaf3Sdrh sqlite3_stmt *pStmt = 0;
4856b900aaf3Sdrh char zBuf[50];
4857b900aaf3Sdrh int rc;
4858b900aaf3Sdrh int bytes; /* The integer specified as arg 3 */
4859b900aaf3Sdrh int objlen; /* The byte-array length of arg 2 */
4860b900aaf3Sdrh
48611c767f0dSdrh if( objc!=5 && objc!=4 ){
4862b900aaf3Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
48631c767f0dSdrh Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
4864b900aaf3Sdrh return TCL_ERROR;
4865b900aaf3Sdrh }
4866b900aaf3Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4867b900aaf3Sdrh zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
4868b900aaf3Sdrh if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
4869b900aaf3Sdrh
48701c767f0dSdrh rc = sqlite3_prepare16_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
4871b900aaf3Sdrh if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
4872b900aaf3Sdrh if( rc ){
4873b900aaf3Sdrh return TCL_ERROR;
4874b900aaf3Sdrh }
4875b900aaf3Sdrh
48761c767f0dSdrh if( objc>=5 ){
4877b900aaf3Sdrh if( zTail ){
487883cc1392Sdrh objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql);
4879b900aaf3Sdrh }else{
4880b900aaf3Sdrh objlen = 0;
4881b900aaf3Sdrh }
4882b900aaf3Sdrh pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
4883b900aaf3Sdrh Tcl_IncrRefCount(pTail);
4884b900aaf3Sdrh Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
4885b900aaf3Sdrh Tcl_DecrRefCount(pTail);
48861c767f0dSdrh }
4887b900aaf3Sdrh
4888b900aaf3Sdrh if( pStmt ){
4889b900aaf3Sdrh if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
4890b900aaf3Sdrh }
4891b900aaf3Sdrh Tcl_AppendResult(interp, zBuf, 0);
4892b900aaf3Sdrh #endif /* SQLITE_OMIT_UTF16 */
4893b900aaf3Sdrh return TCL_OK;
4894b900aaf3Sdrh }
4895b900aaf3Sdrh
4896b900aaf3Sdrh /*
48974ad1713cSdanielk1977 ** Usage: sqlite3_open filename ?options-list?
48984ad1713cSdanielk1977 */
test_open(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])48997617e4a8Smistachkin static int SQLITE_TCLAPI test_open(
49004ad1713cSdanielk1977 void * clientData,
49014ad1713cSdanielk1977 Tcl_Interp *interp,
49024ad1713cSdanielk1977 int objc,
49034ad1713cSdanielk1977 Tcl_Obj *CONST objv[]
49044ad1713cSdanielk1977 ){
49054ad1713cSdanielk1977 const char *zFilename;
49064ad1713cSdanielk1977 sqlite3 *db;
49074ad1713cSdanielk1977 char zBuf[100];
49084ad1713cSdanielk1977
4909afc91047Sdrh if( objc!=3 && objc!=2 && objc!=1 ){
49104ad1713cSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
49114ad1713cSdanielk1977 Tcl_GetString(objv[0]), " filename options-list", 0);
49124ad1713cSdanielk1977 return TCL_ERROR;
49134ad1713cSdanielk1977 }
49144ad1713cSdanielk1977
4915afc91047Sdrh zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0;
4916caffb1a5Sdrh sqlite3_open(zFilename, &db);
49174ad1713cSdanielk1977
491864b1bea3Sdrh if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
49194ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, 0);
49204ad1713cSdanielk1977 return TCL_OK;
49214ad1713cSdanielk1977 }
49224ad1713cSdanielk1977
49234ad1713cSdanielk1977 /*
4924286ab7c2Sdan ** Usage: sqlite3_open_v2 FILENAME FLAGS VFS
4925286ab7c2Sdan */
test_open_v2(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])49267617e4a8Smistachkin static int SQLITE_TCLAPI test_open_v2(
4927286ab7c2Sdan void * clientData,
4928286ab7c2Sdan Tcl_Interp *interp,
4929286ab7c2Sdan int objc,
4930286ab7c2Sdan Tcl_Obj *CONST objv[]
4931286ab7c2Sdan ){
4932286ab7c2Sdan const char *zFilename;
4933286ab7c2Sdan const char *zVfs;
4934286ab7c2Sdan int flags = 0;
4935286ab7c2Sdan sqlite3 *db;
4936286ab7c2Sdan int rc;
4937286ab7c2Sdan char zBuf[100];
4938286ab7c2Sdan
4939286ab7c2Sdan int nFlag;
4940286ab7c2Sdan Tcl_Obj **apFlag;
4941286ab7c2Sdan int i;
4942286ab7c2Sdan
4943286ab7c2Sdan if( objc!=4 ){
4944286ab7c2Sdan Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS");
4945286ab7c2Sdan return TCL_ERROR;
4946286ab7c2Sdan }
4947286ab7c2Sdan zFilename = Tcl_GetString(objv[1]);
4948286ab7c2Sdan zVfs = Tcl_GetString(objv[3]);
4949286ab7c2Sdan if( zVfs[0]==0x00 ) zVfs = 0;
4950286ab7c2Sdan
4951286ab7c2Sdan rc = Tcl_ListObjGetElements(interp, objv[2], &nFlag, &apFlag);
4952286ab7c2Sdan if( rc!=TCL_OK ) return rc;
4953286ab7c2Sdan for(i=0; i<nFlag; i++){
4954286ab7c2Sdan int iFlag;
4955286ab7c2Sdan struct OpenFlag {
4956286ab7c2Sdan const char *zFlag;
4957286ab7c2Sdan int flag;
4958286ab7c2Sdan } aFlag[] = {
4959286ab7c2Sdan { "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY },
4960286ab7c2Sdan { "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE },
4961286ab7c2Sdan { "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE },
4962286ab7c2Sdan { "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE },
4963286ab7c2Sdan { "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE },
4964286ab7c2Sdan { "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY },
4965286ab7c2Sdan { "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB },
4966286ab7c2Sdan { "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB },
4967286ab7c2Sdan { "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB },
4968286ab7c2Sdan { "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL },
4969286ab7c2Sdan { "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL },
4970286ab7c2Sdan { "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL },
4971ccb2113aSdrh { "SQLITE_OPEN_SUPER_JOURNAL", SQLITE_OPEN_SUPER_JOURNAL },
4972286ab7c2Sdan { "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX },
4973286ab7c2Sdan { "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX },
4974286ab7c2Sdan { "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE },
4975286ab7c2Sdan { "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE },
4976286ab7c2Sdan { "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL },
4977286ab7c2Sdan { "SQLITE_OPEN_URI", SQLITE_OPEN_URI },
497891acf7d3Sdrh { "SQLITE_OPEN_EXRESCODE", SQLITE_OPEN_EXRESCODE },
4979286ab7c2Sdan { 0, 0 }
4980286ab7c2Sdan };
4981286ab7c2Sdan rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]),
4982286ab7c2Sdan "flag", 0, &iFlag
4983286ab7c2Sdan );
4984286ab7c2Sdan if( rc!=TCL_OK ) return rc;
4985286ab7c2Sdan flags |= aFlag[iFlag].flag;
4986286ab7c2Sdan }
4987286ab7c2Sdan
4988286ab7c2Sdan rc = sqlite3_open_v2(zFilename, &db, flags, zVfs);
4989286ab7c2Sdan if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
4990286ab7c2Sdan Tcl_AppendResult(interp, zBuf, 0);
4991286ab7c2Sdan return TCL_OK;
4992286ab7c2Sdan }
4993286ab7c2Sdan
4994286ab7c2Sdan /*
49954ad1713cSdanielk1977 ** Usage: sqlite3_open16 filename options
49964ad1713cSdanielk1977 */
test_open16(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])49977617e4a8Smistachkin static int SQLITE_TCLAPI test_open16(
49984ad1713cSdanielk1977 void * clientData,
49994ad1713cSdanielk1977 Tcl_Interp *interp,
50004ad1713cSdanielk1977 int objc,
50014ad1713cSdanielk1977 Tcl_Obj *CONST objv[]
50024ad1713cSdanielk1977 ){
50035436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
50044ad1713cSdanielk1977 const void *zFilename;
50054ad1713cSdanielk1977 sqlite3 *db;
50064ad1713cSdanielk1977 char zBuf[100];
50074ad1713cSdanielk1977
50084ad1713cSdanielk1977 if( objc!=3 ){
50094ad1713cSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
50104ad1713cSdanielk1977 Tcl_GetString(objv[0]), " filename options-list", 0);
50114ad1713cSdanielk1977 return TCL_ERROR;
50124ad1713cSdanielk1977 }
50134ad1713cSdanielk1977
50144ad1713cSdanielk1977 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
5015caffb1a5Sdrh sqlite3_open16(zFilename, &db);
50164ad1713cSdanielk1977
501764b1bea3Sdrh if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
50184ad1713cSdanielk1977 Tcl_AppendResult(interp, zBuf, 0);
50195436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
50204ad1713cSdanielk1977 return TCL_OK;
50214ad1713cSdanielk1977 }
5022d3d39e93Sdrh
5023d3d39e93Sdrh /*
5024bc6ada41Sdanielk1977 ** Usage: sqlite3_complete16 <UTF-16 string>
5025bc6ada41Sdanielk1977 **
5026bc6ada41Sdanielk1977 ** Return 1 if the supplied argument is a complete SQL statement, or zero
5027bc6ada41Sdanielk1977 ** otherwise.
5028bc6ada41Sdanielk1977 */
test_complete16(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])50297617e4a8Smistachkin static int SQLITE_TCLAPI test_complete16(
5030bc6ada41Sdanielk1977 void * clientData,
5031bc6ada41Sdanielk1977 Tcl_Interp *interp,
5032bc6ada41Sdanielk1977 int objc,
5033bc6ada41Sdanielk1977 Tcl_Obj *CONST objv[]
5034bc6ada41Sdanielk1977 ){
5035ccae6026Sdrh #if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16)
5036bc6ada41Sdanielk1977 char *zBuf;
5037bc6ada41Sdanielk1977
5038bc6ada41Sdanielk1977 if( objc!=2 ){
5039bc6ada41Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
5040bc6ada41Sdanielk1977 return TCL_ERROR;
5041bc6ada41Sdanielk1977 }
5042bc6ada41Sdanielk1977
504303d847eaSdrh zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0);
5044bc6ada41Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
5045ccae6026Sdrh #endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */
5046bc6ada41Sdanielk1977 return TCL_OK;
5047bc6ada41Sdanielk1977 }
5048bc6ada41Sdanielk1977
5049bc6ada41Sdanielk1977 /*
505091694dbdSdrh ** Usage: sqlite3_normalize SQL
505191694dbdSdrh **
505291694dbdSdrh ** Return the normalized value for an SQL statement.
505391694dbdSdrh */
test_normalize(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])505491694dbdSdrh static int SQLITE_TCLAPI test_normalize(
505591694dbdSdrh void * clientData,
505691694dbdSdrh Tcl_Interp *interp,
505791694dbdSdrh int objc,
505891694dbdSdrh Tcl_Obj *CONST objv[]
505991694dbdSdrh ){
506091694dbdSdrh char *zSql;
506191694dbdSdrh char *zNorm;
506291694dbdSdrh extern char *sqlite3_normalize(const char*);
506391694dbdSdrh
506491694dbdSdrh if( objc!=2 ){
506591694dbdSdrh Tcl_WrongNumArgs(interp, 1, objv, "SQL");
506691694dbdSdrh return TCL_ERROR;
506791694dbdSdrh }
506891694dbdSdrh
506991694dbdSdrh zSql = (char*)Tcl_GetString(objv[1]);
507091694dbdSdrh zNorm = sqlite3_normalize(zSql);
507191694dbdSdrh if( zNorm ){
507291694dbdSdrh Tcl_SetObjResult(interp, Tcl_NewStringObj(zNorm, -1));
507391694dbdSdrh sqlite3_free(zNorm);
507491694dbdSdrh }
507591694dbdSdrh return TCL_OK;
507691694dbdSdrh }
507791694dbdSdrh
507891694dbdSdrh /*
5079106bb236Sdanielk1977 ** Usage: sqlite3_step STMT
5080106bb236Sdanielk1977 **
5081106bb236Sdanielk1977 ** Advance the statement to the next row.
5082106bb236Sdanielk1977 */
test_step(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])50837617e4a8Smistachkin static int SQLITE_TCLAPI test_step(
5084106bb236Sdanielk1977 void * clientData,
5085106bb236Sdanielk1977 Tcl_Interp *interp,
5086106bb236Sdanielk1977 int objc,
5087106bb236Sdanielk1977 Tcl_Obj *CONST objv[]
5088106bb236Sdanielk1977 ){
5089106bb236Sdanielk1977 sqlite3_stmt *pStmt;
5090106bb236Sdanielk1977 int rc;
5091106bb236Sdanielk1977
5092e1cd9874Sdanielk1977 if( objc!=2 ){
5093106bb236Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
5094106bb236Sdanielk1977 Tcl_GetString(objv[0]), " STMT", 0);
5095106bb236Sdanielk1977 return TCL_ERROR;
5096106bb236Sdanielk1977 }
5097106bb236Sdanielk1977
5098106bb236Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
509917240fd9Sdanielk1977 rc = sqlite3_step(pStmt);
5100106bb236Sdanielk1977
5101fbcd585fSdanielk1977 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
51024f0c5878Sdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
5103e1cd9874Sdanielk1977 return TCL_OK;
5104e1cd9874Sdanielk1977 }
5105e1cd9874Sdanielk1977
test_sql(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])51067617e4a8Smistachkin static int SQLITE_TCLAPI test_sql(
5107404ca075Sdanielk1977 void * clientData,
5108404ca075Sdanielk1977 Tcl_Interp *interp,
5109404ca075Sdanielk1977 int objc,
5110404ca075Sdanielk1977 Tcl_Obj *CONST objv[]
5111404ca075Sdanielk1977 ){
5112404ca075Sdanielk1977 sqlite3_stmt *pStmt;
5113404ca075Sdanielk1977
5114404ca075Sdanielk1977 if( objc!=2 ){
5115404ca075Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
5116404ca075Sdanielk1977 return TCL_ERROR;
5117404ca075Sdanielk1977 }
5118404ca075Sdanielk1977
5119404ca075Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
5120404ca075Sdanielk1977 Tcl_SetResult(interp, (char *)sqlite3_sql(pStmt), TCL_VOLATILE);
5121404ca075Sdanielk1977 return TCL_OK;
5122404ca075Sdanielk1977 }
test_ex_sql(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])51237617e4a8Smistachkin static int SQLITE_TCLAPI test_ex_sql(
5124fca760c8Sdrh void * clientData,
5125fca760c8Sdrh Tcl_Interp *interp,
5126fca760c8Sdrh int objc,
5127fca760c8Sdrh Tcl_Obj *CONST objv[]
5128fca760c8Sdrh ){
5129fca760c8Sdrh sqlite3_stmt *pStmt;
5130fca760c8Sdrh char *z;
5131fca760c8Sdrh
5132fca760c8Sdrh if( objc!=2 ){
5133fca760c8Sdrh Tcl_WrongNumArgs(interp, 1, objv, "STMT");
5134fca760c8Sdrh return TCL_ERROR;
5135fca760c8Sdrh }
5136fca760c8Sdrh
5137fca760c8Sdrh if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
5138fca760c8Sdrh z = sqlite3_expanded_sql(pStmt);
5139fca760c8Sdrh Tcl_SetResult(interp, z, TCL_VOLATILE);
5140fca760c8Sdrh sqlite3_free(z);
5141fca760c8Sdrh return TCL_OK;
5142fca760c8Sdrh }
51438bee11a4Smistachkin #ifdef SQLITE_ENABLE_NORMALIZE
test_norm_sql(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])51448bee11a4Smistachkin static int SQLITE_TCLAPI test_norm_sql(
51458bee11a4Smistachkin void * clientData,
51468bee11a4Smistachkin Tcl_Interp *interp,
51478bee11a4Smistachkin int objc,
51488bee11a4Smistachkin Tcl_Obj *CONST objv[]
51498bee11a4Smistachkin ){
51508bee11a4Smistachkin sqlite3_stmt *pStmt;
51518bee11a4Smistachkin
51528bee11a4Smistachkin if( objc!=2 ){
51538bee11a4Smistachkin Tcl_WrongNumArgs(interp, 1, objv, "STMT");
51548bee11a4Smistachkin return TCL_ERROR;
51558bee11a4Smistachkin }
51568bee11a4Smistachkin
51578bee11a4Smistachkin if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
51588bee11a4Smistachkin Tcl_SetResult(interp, (char *)sqlite3_normalized_sql(pStmt), TCL_VOLATILE);
51598bee11a4Smistachkin return TCL_OK;
51608bee11a4Smistachkin }
51618bee11a4Smistachkin #endif /* SQLITE_ENABLE_NORMALIZE */
5162404ca075Sdanielk1977
5163e1cd9874Sdanielk1977 /*
516417240fd9Sdanielk1977 ** Usage: sqlite3_column_count STMT
516517240fd9Sdanielk1977 **
516617240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT.
516717240fd9Sdanielk1977 */
test_column_count(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])51687617e4a8Smistachkin static int SQLITE_TCLAPI test_column_count(
516917240fd9Sdanielk1977 void * clientData,
517017240fd9Sdanielk1977 Tcl_Interp *interp,
517117240fd9Sdanielk1977 int objc,
517217240fd9Sdanielk1977 Tcl_Obj *CONST objv[]
517317240fd9Sdanielk1977 ){
517417240fd9Sdanielk1977 sqlite3_stmt *pStmt;
517517240fd9Sdanielk1977
517617240fd9Sdanielk1977 if( objc!=2 ){
517717240fd9Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
517817240fd9Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0);
517917240fd9Sdanielk1977 return TCL_ERROR;
518017240fd9Sdanielk1977 }
518117240fd9Sdanielk1977
518217240fd9Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
518317240fd9Sdanielk1977
518417240fd9Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
518517240fd9Sdanielk1977 return TCL_OK;
518617240fd9Sdanielk1977 }
518717240fd9Sdanielk1977
518817240fd9Sdanielk1977 /*
51893cf86063Sdanielk1977 ** Usage: sqlite3_column_type STMT column
51903cf86063Sdanielk1977 **
51913cf86063Sdanielk1977 ** Return the type of the data in column 'column' of the current row.
51923cf86063Sdanielk1977 */
test_column_type(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])51937617e4a8Smistachkin static int SQLITE_TCLAPI test_column_type(
51943cf86063Sdanielk1977 void * clientData,
51953cf86063Sdanielk1977 Tcl_Interp *interp,
51963cf86063Sdanielk1977 int objc,
51973cf86063Sdanielk1977 Tcl_Obj *CONST objv[]
51983cf86063Sdanielk1977 ){
51993cf86063Sdanielk1977 sqlite3_stmt *pStmt;
52003cf86063Sdanielk1977 int col;
52013cf86063Sdanielk1977 int tp;
52023cf86063Sdanielk1977
52033cf86063Sdanielk1977 if( objc!=3 ){
52043cf86063Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
52053cf86063Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0);
52063cf86063Sdanielk1977 return TCL_ERROR;
52073cf86063Sdanielk1977 }
52083cf86063Sdanielk1977
52093cf86063Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
52103cf86063Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
52113cf86063Sdanielk1977
52123cf86063Sdanielk1977 tp = sqlite3_column_type(pStmt, col);
52133cf86063Sdanielk1977 switch( tp ){
52149c054830Sdrh case SQLITE_INTEGER:
52153cf86063Sdanielk1977 Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
52163cf86063Sdanielk1977 break;
52179c054830Sdrh case SQLITE_NULL:
52183cf86063Sdanielk1977 Tcl_SetResult(interp, "NULL", TCL_STATIC);
52193cf86063Sdanielk1977 break;
52209c054830Sdrh case SQLITE_FLOAT:
52213cf86063Sdanielk1977 Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
52223cf86063Sdanielk1977 break;
52239c054830Sdrh case SQLITE_TEXT:
52243cf86063Sdanielk1977 Tcl_SetResult(interp, "TEXT", TCL_STATIC);
52253cf86063Sdanielk1977 break;
52269c054830Sdrh case SQLITE_BLOB:
52273cf86063Sdanielk1977 Tcl_SetResult(interp, "BLOB", TCL_STATIC);
52283cf86063Sdanielk1977 break;
52293cf86063Sdanielk1977 default:
52303cf86063Sdanielk1977 assert(0);
52313cf86063Sdanielk1977 }
52323cf86063Sdanielk1977
52333cf86063Sdanielk1977 return TCL_OK;
52343cf86063Sdanielk1977 }
52353cf86063Sdanielk1977
52363cf86063Sdanielk1977 /*
523704f2e68dSdanielk1977 ** Usage: sqlite3_column_int64 STMT column
52383cf86063Sdanielk1977 **
52393cf86063Sdanielk1977 ** Return the data in column 'column' of the current row cast as an
524004f2e68dSdanielk1977 ** wide (64-bit) integer.
52413cf86063Sdanielk1977 */
test_column_int64(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])52427617e4a8Smistachkin static int SQLITE_TCLAPI test_column_int64(
52433cf86063Sdanielk1977 void * clientData,
52443cf86063Sdanielk1977 Tcl_Interp *interp,
52453cf86063Sdanielk1977 int objc,
52463cf86063Sdanielk1977 Tcl_Obj *CONST objv[]
52473cf86063Sdanielk1977 ){
52483cf86063Sdanielk1977 sqlite3_stmt *pStmt;
52493cf86063Sdanielk1977 int col;
525004f2e68dSdanielk1977 i64 iVal;
52513cf86063Sdanielk1977
52523cf86063Sdanielk1977 if( objc!=3 ){
52533cf86063Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
52543cf86063Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0);
52553cf86063Sdanielk1977 return TCL_ERROR;
52563cf86063Sdanielk1977 }
52573cf86063Sdanielk1977
52583cf86063Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
52593cf86063Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
52603cf86063Sdanielk1977
526104f2e68dSdanielk1977 iVal = sqlite3_column_int64(pStmt, col);
526204f2e68dSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
526304f2e68dSdanielk1977 return TCL_OK;
526404f2e68dSdanielk1977 }
526504f2e68dSdanielk1977
526604f2e68dSdanielk1977 /*
5267ea61b2c4Sdanielk1977 ** Usage: sqlite3_column_blob STMT column
5268ea61b2c4Sdanielk1977 */
test_column_blob(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])52697617e4a8Smistachkin static int SQLITE_TCLAPI test_column_blob(
5270ea61b2c4Sdanielk1977 void * clientData,
5271ea61b2c4Sdanielk1977 Tcl_Interp *interp,
5272ea61b2c4Sdanielk1977 int objc,
5273ea61b2c4Sdanielk1977 Tcl_Obj *CONST objv[]
5274ea61b2c4Sdanielk1977 ){
5275ea61b2c4Sdanielk1977 sqlite3_stmt *pStmt;
5276ea61b2c4Sdanielk1977 int col;
5277ea61b2c4Sdanielk1977
5278ea61b2c4Sdanielk1977 int len;
5279c572ef7fSdanielk1977 const void *pBlob;
5280ea61b2c4Sdanielk1977
5281ea61b2c4Sdanielk1977 if( objc!=3 ){
5282ea61b2c4Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
5283ea61b2c4Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0);
5284ea61b2c4Sdanielk1977 return TCL_ERROR;
5285ea61b2c4Sdanielk1977 }
5286ea61b2c4Sdanielk1977
5287ea61b2c4Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
5288ea61b2c4Sdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
5289ea61b2c4Sdanielk1977
5290ea61b2c4Sdanielk1977 len = sqlite3_column_bytes(pStmt, col);
52919310ef23Sdrh pBlob = sqlite3_column_blob(pStmt, col);
5292ea61b2c4Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
5293ea61b2c4Sdanielk1977 return TCL_OK;
5294ea61b2c4Sdanielk1977 }
5295ea61b2c4Sdanielk1977
5296ea61b2c4Sdanielk1977 /*
529704f2e68dSdanielk1977 ** Usage: sqlite3_column_double STMT column
529804f2e68dSdanielk1977 **
529904f2e68dSdanielk1977 ** Return the data in column 'column' of the current row cast as a double.
530004f2e68dSdanielk1977 */
test_column_double(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])53017617e4a8Smistachkin static int SQLITE_TCLAPI test_column_double(
530204f2e68dSdanielk1977 void * clientData,
530304f2e68dSdanielk1977 Tcl_Interp *interp,
530404f2e68dSdanielk1977 int objc,
530504f2e68dSdanielk1977 Tcl_Obj *CONST objv[]
530604f2e68dSdanielk1977 ){
530704f2e68dSdanielk1977 sqlite3_stmt *pStmt;
530804f2e68dSdanielk1977 int col;
530904f2e68dSdanielk1977 double rVal;
531004f2e68dSdanielk1977
531104f2e68dSdanielk1977 if( objc!=3 ){
531204f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
531304f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0);
531404f2e68dSdanielk1977 return TCL_ERROR;
531504f2e68dSdanielk1977 }
531604f2e68dSdanielk1977
531704f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
531804f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
531904f2e68dSdanielk1977
532004f2e68dSdanielk1977 rVal = sqlite3_column_double(pStmt, col);
5321c572ef7fSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
53223cf86063Sdanielk1977 return TCL_OK;
53233cf86063Sdanielk1977 }
53243cf86063Sdanielk1977
53253cf86063Sdanielk1977 /*
532617240fd9Sdanielk1977 ** Usage: sqlite3_data_count STMT
532717240fd9Sdanielk1977 **
532817240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT.
532917240fd9Sdanielk1977 */
test_data_count(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])53307617e4a8Smistachkin static int SQLITE_TCLAPI test_data_count(
533117240fd9Sdanielk1977 void * clientData,
533217240fd9Sdanielk1977 Tcl_Interp *interp,
533317240fd9Sdanielk1977 int objc,
533417240fd9Sdanielk1977 Tcl_Obj *CONST objv[]
533517240fd9Sdanielk1977 ){
533617240fd9Sdanielk1977 sqlite3_stmt *pStmt;
533717240fd9Sdanielk1977
533817240fd9Sdanielk1977 if( objc!=2 ){
533917240fd9Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
534017240fd9Sdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0);
534117240fd9Sdanielk1977 return TCL_ERROR;
534217240fd9Sdanielk1977 }
534317240fd9Sdanielk1977
534417240fd9Sdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
534517240fd9Sdanielk1977
534617240fd9Sdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
534717240fd9Sdanielk1977 return TCL_OK;
534817240fd9Sdanielk1977 }
534917240fd9Sdanielk1977
535017240fd9Sdanielk1977 /*
535104f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column
535204f2e68dSdanielk1977 **
535304f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column
535404f2e68dSdanielk1977 **
535504f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column
535604f2e68dSdanielk1977 */
test_stmt_utf8(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])53577617e4a8Smistachkin static int SQLITE_TCLAPI test_stmt_utf8(
5358241db313Sdrh void * clientData, /* Pointer to SQLite API function to be invoke */
535904f2e68dSdanielk1977 Tcl_Interp *interp,
536004f2e68dSdanielk1977 int objc,
536104f2e68dSdanielk1977 Tcl_Obj *CONST objv[]
536204f2e68dSdanielk1977 ){
536304f2e68dSdanielk1977 sqlite3_stmt *pStmt;
536404f2e68dSdanielk1977 int col;
536544a376f6Sdanielk1977 const char *(*xFunc)(sqlite3_stmt*, int);
5366f93bbbeaSdanielk1977 const char *zRet;
536704f2e68dSdanielk1977
536844a376f6Sdanielk1977 xFunc = (const char *(*)(sqlite3_stmt*, int))clientData;
536904f2e68dSdanielk1977 if( objc!=3 ){
537004f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
537104f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0);
537204f2e68dSdanielk1977 return TCL_ERROR;
537304f2e68dSdanielk1977 }
537404f2e68dSdanielk1977
537504f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
537604f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
5377f93bbbeaSdanielk1977 zRet = xFunc(pStmt, col);
5378f93bbbeaSdanielk1977 if( zRet ){
5379f93bbbeaSdanielk1977 Tcl_SetResult(interp, (char *)zRet, 0);
5380f93bbbeaSdanielk1977 }
538104f2e68dSdanielk1977 return TCL_OK;
538204f2e68dSdanielk1977 }
538304f2e68dSdanielk1977
test_global_recover(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])53847617e4a8Smistachkin static int SQLITE_TCLAPI test_global_recover(
53856b456a2bSdanielk1977 void * clientData,
53866b456a2bSdanielk1977 Tcl_Interp *interp,
53876b456a2bSdanielk1977 int objc,
53886b456a2bSdanielk1977 Tcl_Obj *CONST objv[]
53896b456a2bSdanielk1977 ){
5390eec556d3Sshane #ifndef SQLITE_OMIT_DEPRECATED
53916b456a2bSdanielk1977 int rc;
53926b456a2bSdanielk1977 if( objc!=1 ){
53936b456a2bSdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "");
53946b456a2bSdanielk1977 return TCL_ERROR;
53956b456a2bSdanielk1977 }
53966b456a2bSdanielk1977 rc = sqlite3_global_recover();
53974f0c5878Sdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
53986b456a2bSdanielk1977 #endif
53996b456a2bSdanielk1977 return TCL_OK;
54006b456a2bSdanielk1977 }
54016b456a2bSdanielk1977
540204f2e68dSdanielk1977 /*
540304f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column
540404f2e68dSdanielk1977 **
540504f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column
540604f2e68dSdanielk1977 **
540704f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column
540804f2e68dSdanielk1977 */
test_stmt_utf16(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])54097617e4a8Smistachkin static int SQLITE_TCLAPI test_stmt_utf16(
5410241db313Sdrh void * clientData, /* Pointer to SQLite API function to be invoked */
541104f2e68dSdanielk1977 Tcl_Interp *interp,
541204f2e68dSdanielk1977 int objc,
541304f2e68dSdanielk1977 Tcl_Obj *CONST objv[]
541404f2e68dSdanielk1977 ){
54155436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
541604f2e68dSdanielk1977 sqlite3_stmt *pStmt;
541704f2e68dSdanielk1977 int col;
541804f2e68dSdanielk1977 Tcl_Obj *pRet;
541904f2e68dSdanielk1977 const void *zName16;
542044a376f6Sdanielk1977 const void *(*xFunc)(sqlite3_stmt*, int);
542104f2e68dSdanielk1977
542244a376f6Sdanielk1977 xFunc = (const void *(*)(sqlite3_stmt*, int))clientData;
542304f2e68dSdanielk1977 if( objc!=3 ){
542404f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
542504f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0);
542604f2e68dSdanielk1977 return TCL_ERROR;
542704f2e68dSdanielk1977 }
542804f2e68dSdanielk1977
542904f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
543004f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
543104f2e68dSdanielk1977
543204f2e68dSdanielk1977 zName16 = xFunc(pStmt, col);
5433f93bbbeaSdanielk1977 if( zName16 ){
5434aed382f9Sdrh int n;
5435aed382f9Sdrh const char *z = zName16;
5436aed382f9Sdrh for(n=0; z[n] || z[n+1]; n+=2){}
5437aed382f9Sdrh pRet = Tcl_NewByteArrayObj(zName16, n+2);
543804f2e68dSdanielk1977 Tcl_SetObjResult(interp, pRet);
5439f93bbbeaSdanielk1977 }
54405436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
544104f2e68dSdanielk1977
544204f2e68dSdanielk1977 return TCL_OK;
544304f2e68dSdanielk1977 }
544404f2e68dSdanielk1977
544504f2e68dSdanielk1977 /*
544604f2e68dSdanielk1977 ** Usage: sqlite3_column_int STMT column
544704f2e68dSdanielk1977 **
544804f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes STMT column
544904f2e68dSdanielk1977 **
545004f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes16 STMT column
545104f2e68dSdanielk1977 **
545204f2e68dSdanielk1977 */
test_stmt_int(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])54537617e4a8Smistachkin static int SQLITE_TCLAPI test_stmt_int(
5454241db313Sdrh void * clientData, /* Pointer to SQLite API function to be invoked */
545504f2e68dSdanielk1977 Tcl_Interp *interp,
545604f2e68dSdanielk1977 int objc,
545704f2e68dSdanielk1977 Tcl_Obj *CONST objv[]
545804f2e68dSdanielk1977 ){
545904f2e68dSdanielk1977 sqlite3_stmt *pStmt;
546004f2e68dSdanielk1977 int col;
546144a376f6Sdanielk1977 int (*xFunc)(sqlite3_stmt*, int);
546204f2e68dSdanielk1977
546355a25a12Sdanielk1977 xFunc = (int (*)(sqlite3_stmt*, int))clientData;
546404f2e68dSdanielk1977 if( objc!=3 ){
546504f2e68dSdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"",
546604f2e68dSdanielk1977 Tcl_GetString(objv[0]), " STMT column", 0);
546704f2e68dSdanielk1977 return TCL_ERROR;
546804f2e68dSdanielk1977 }
546904f2e68dSdanielk1977
547004f2e68dSdanielk1977 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
547104f2e68dSdanielk1977 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
547204f2e68dSdanielk1977
547304f2e68dSdanielk1977 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
547404f2e68dSdanielk1977 return TCL_OK;
547504f2e68dSdanielk1977 }
547604f2e68dSdanielk1977
5477cacb208eSdrh
5478cacb208eSdrh /*
5479c5cdca61Sdrh ** Usage: sqlite3_interrupt DB
5480c5cdca61Sdrh **
5481c5cdca61Sdrh ** Trigger an interrupt on DB
5482c5cdca61Sdrh */
test_interrupt(void * clientData,Tcl_Interp * interp,int argc,char ** argv)54837617e4a8Smistachkin static int SQLITE_TCLAPI test_interrupt(
5484c5cdca61Sdrh void * clientData,
5485c5cdca61Sdrh Tcl_Interp *interp,
5486c5cdca61Sdrh int argc,
5487c5cdca61Sdrh char **argv
5488c5cdca61Sdrh ){
5489c5cdca61Sdrh sqlite3 *db;
5490c5cdca61Sdrh if( argc!=2 ){
5491c5cdca61Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
5492c5cdca61Sdrh return TCL_ERROR;
5493c5cdca61Sdrh }
5494c5cdca61Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
5495c5cdca61Sdrh sqlite3_interrupt(db);
5496c5cdca61Sdrh return TCL_OK;
5497c5cdca61Sdrh }
5498c5cdca61Sdrh
5499600dd0baSdanielk1977 /*
55009636c4e1Sdanielk1977 ** Usage: sqlite_delete_function DB function-name
55019636c4e1Sdanielk1977 **
55029636c4e1Sdanielk1977 ** Delete the user function 'function-name' from database handle DB. It
55039636c4e1Sdanielk1977 ** is assumed that the user function was created as UTF8, any number of
55049636c4e1Sdanielk1977 ** arguments (the way the TCL interface does it).
55059636c4e1Sdanielk1977 */
delete_function(void * clientData,Tcl_Interp * interp,int argc,char ** argv)55067617e4a8Smistachkin static int SQLITE_TCLAPI delete_function(
55079636c4e1Sdanielk1977 void * clientData,
55089636c4e1Sdanielk1977 Tcl_Interp *interp,
55099636c4e1Sdanielk1977 int argc,
55109636c4e1Sdanielk1977 char **argv
55119636c4e1Sdanielk1977 ){
55129636c4e1Sdanielk1977 int rc;
55139636c4e1Sdanielk1977 sqlite3 *db;
55149636c4e1Sdanielk1977 if( argc!=3 ){
55159636c4e1Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
55169636c4e1Sdanielk1977 " DB function-name", 0);
55179636c4e1Sdanielk1977 return TCL_ERROR;
55189636c4e1Sdanielk1977 }
55199636c4e1Sdanielk1977 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
55209636c4e1Sdanielk1977 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
55214f0c5878Sdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
55229636c4e1Sdanielk1977 return TCL_OK;
55239636c4e1Sdanielk1977 }
55249636c4e1Sdanielk1977
55259636c4e1Sdanielk1977 /*
55269636c4e1Sdanielk1977 ** Usage: sqlite_delete_collation DB collation-name
55279636c4e1Sdanielk1977 **
55289636c4e1Sdanielk1977 ** Delete the collation sequence 'collation-name' from database handle
55299636c4e1Sdanielk1977 ** DB. It is assumed that the collation sequence was created as UTF8 (the
55309636c4e1Sdanielk1977 ** way the TCL interface does it).
55319636c4e1Sdanielk1977 */
delete_collation(void * clientData,Tcl_Interp * interp,int argc,char ** argv)55327617e4a8Smistachkin static int SQLITE_TCLAPI delete_collation(
55339636c4e1Sdanielk1977 void * clientData,
55349636c4e1Sdanielk1977 Tcl_Interp *interp,
55359636c4e1Sdanielk1977 int argc,
55369636c4e1Sdanielk1977 char **argv
55379636c4e1Sdanielk1977 ){
55389636c4e1Sdanielk1977 int rc;
55399636c4e1Sdanielk1977 sqlite3 *db;
55409636c4e1Sdanielk1977 if( argc!=3 ){
55419636c4e1Sdanielk1977 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
55429636c4e1Sdanielk1977 " DB function-name", 0);
55439636c4e1Sdanielk1977 return TCL_ERROR;
55449636c4e1Sdanielk1977 }
55459636c4e1Sdanielk1977 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
55469636c4e1Sdanielk1977 rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
55474f0c5878Sdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
55489636c4e1Sdanielk1977 return TCL_OK;
55499636c4e1Sdanielk1977 }
55509636c4e1Sdanielk1977
55519636c4e1Sdanielk1977 /*
55523e1d8e63Sdrh ** Usage: sqlite3_get_autocommit DB
55533e1d8e63Sdrh **
55543e1d8e63Sdrh ** Return true if the database DB is currently in auto-commit mode.
55553e1d8e63Sdrh ** Return false if not.
55563e1d8e63Sdrh */
get_autocommit(void * clientData,Tcl_Interp * interp,int argc,char ** argv)55577617e4a8Smistachkin static int SQLITE_TCLAPI get_autocommit(
55583e1d8e63Sdrh void * clientData,
55593e1d8e63Sdrh Tcl_Interp *interp,
55603e1d8e63Sdrh int argc,
55613e1d8e63Sdrh char **argv
55623e1d8e63Sdrh ){
55633e1d8e63Sdrh char zBuf[30];
55643e1d8e63Sdrh sqlite3 *db;
55653e1d8e63Sdrh if( argc!=2 ){
55663e1d8e63Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
55673e1d8e63Sdrh " DB", 0);
55683e1d8e63Sdrh return TCL_ERROR;
55693e1d8e63Sdrh }
55703e1d8e63Sdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
557165545b59Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3_get_autocommit(db));
55723e1d8e63Sdrh Tcl_AppendResult(interp, zBuf, 0);
55733e1d8e63Sdrh return TCL_OK;
55743e1d8e63Sdrh }
55753e1d8e63Sdrh
55763e1d8e63Sdrh /*
55773086765bSdrh ** Usage: sqlite3_busy_timeout DB MS
55783086765bSdrh **
55793086765bSdrh ** Set the busy timeout. This is more easily done using the timeout
55803086765bSdrh ** method of the TCL interface. But we need a way to test the case
55813086765bSdrh ** where it returns SQLITE_MISUSE.
55823086765bSdrh */
test_busy_timeout(void * clientData,Tcl_Interp * interp,int argc,char ** argv)55837617e4a8Smistachkin static int SQLITE_TCLAPI test_busy_timeout(
55843086765bSdrh void * clientData,
55853086765bSdrh Tcl_Interp *interp,
55863086765bSdrh int argc,
55873086765bSdrh char **argv
55883086765bSdrh ){
55893086765bSdrh int rc, ms;
55903086765bSdrh sqlite3 *db;
55913086765bSdrh if( argc!=3 ){
55923086765bSdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
55933086765bSdrh " DB", 0);
55943086765bSdrh return TCL_ERROR;
55953086765bSdrh }
55963086765bSdrh if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
55973086765bSdrh if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR;
55983086765bSdrh rc = sqlite3_busy_timeout(db, ms);
5599e84d8d32Smistachkin Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
56003086765bSdrh return TCL_OK;
56013086765bSdrh }
56023086765bSdrh
56033086765bSdrh /*
560492febd92Sdrh ** Usage: tcl_variable_type VARIABLENAME
560592febd92Sdrh **
560692febd92Sdrh ** Return the name of the internal representation for the
560792febd92Sdrh ** value of the given variable.
560892febd92Sdrh */
tcl_variable_type(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])56097617e4a8Smistachkin static int SQLITE_TCLAPI tcl_variable_type(
561092febd92Sdrh void * clientData,
561192febd92Sdrh Tcl_Interp *interp,
561292febd92Sdrh int objc,
561392febd92Sdrh Tcl_Obj *CONST objv[]
561492febd92Sdrh ){
561592febd92Sdrh Tcl_Obj *pVar;
561692febd92Sdrh if( objc!=2 ){
561792febd92Sdrh Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
561892febd92Sdrh return TCL_ERROR;
561992febd92Sdrh }
562092febd92Sdrh pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
562192febd92Sdrh if( pVar==0 ) return TCL_ERROR;
562292febd92Sdrh if( pVar->typePtr ){
562392febd92Sdrh Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
562492febd92Sdrh }
562592febd92Sdrh return TCL_OK;
562692febd92Sdrh }
562792febd92Sdrh
562892febd92Sdrh /*
56296aafc29bSdrh ** Usage: sqlite3_release_memory ?N?
56306aafc29bSdrh **
56316aafc29bSdrh ** Attempt to release memory currently held but not actually required.
56326aafc29bSdrh ** The integer N is the number of bytes we are trying to release. The
56336aafc29bSdrh ** return value is the amount of memory actually released.
56346aafc29bSdrh */
test_release_memory(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])56357617e4a8Smistachkin static int SQLITE_TCLAPI test_release_memory(
56366aafc29bSdrh void * clientData,
56376aafc29bSdrh Tcl_Interp *interp,
56386aafc29bSdrh int objc,
56396aafc29bSdrh Tcl_Obj *CONST objv[]
56406aafc29bSdrh ){
56416f7adc8aSdrh #if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
56426aafc29bSdrh int N;
56436aafc29bSdrh int amt;
56446aafc29bSdrh if( objc!=1 && objc!=2 ){
56456aafc29bSdrh Tcl_WrongNumArgs(interp, 1, objv, "?N?");
56466aafc29bSdrh return TCL_ERROR;
56476aafc29bSdrh }
56486aafc29bSdrh if( objc==2 ){
56496aafc29bSdrh if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
56506aafc29bSdrh }else{
56516aafc29bSdrh N = -1;
56526aafc29bSdrh }
56536aafc29bSdrh amt = sqlite3_release_memory(N);
56546aafc29bSdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
56556aafc29bSdrh #endif
56566aafc29bSdrh return TCL_OK;
56576aafc29bSdrh }
56586aafc29bSdrh
565909419b4bSdrh
566009419b4bSdrh /*
566109419b4bSdrh ** Usage: sqlite3_db_release_memory DB
566209419b4bSdrh **
566309419b4bSdrh ** Attempt to release memory currently held by database DB. Return the
566409419b4bSdrh ** result code (which in the current implementation is always zero).
566509419b4bSdrh */
test_db_release_memory(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])56667617e4a8Smistachkin static int SQLITE_TCLAPI test_db_release_memory(
566709419b4bSdrh void * clientData,
566809419b4bSdrh Tcl_Interp *interp,
566909419b4bSdrh int objc,
567009419b4bSdrh Tcl_Obj *CONST objv[]
567109419b4bSdrh ){
567209419b4bSdrh sqlite3 *db;
567309419b4bSdrh int rc;
567409419b4bSdrh if( objc!=2 ){
567509419b4bSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB");
567609419b4bSdrh return TCL_ERROR;
567709419b4bSdrh }
567809419b4bSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
567909419b4bSdrh rc = sqlite3_db_release_memory(db);
568009419b4bSdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
568109419b4bSdrh return TCL_OK;
568209419b4bSdrh }
568309419b4bSdrh
56846aafc29bSdrh /*
56856fa255fdSdan ** Usage: sqlite3_db_cacheflush DB
56866fa255fdSdan **
56876fa255fdSdan ** Attempt to flush any dirty pages to disk.
56886fa255fdSdan */
test_db_cacheflush(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])56897617e4a8Smistachkin static int SQLITE_TCLAPI test_db_cacheflush(
56906fa255fdSdan void * clientData,
56916fa255fdSdan Tcl_Interp *interp,
56926fa255fdSdan int objc,
56936fa255fdSdan Tcl_Obj *CONST objv[]
56946fa255fdSdan ){
56956fa255fdSdan sqlite3 *db;
56966fa255fdSdan int rc;
56976fa255fdSdan if( objc!=2 ){
56986fa255fdSdan Tcl_WrongNumArgs(interp, 1, objv, "DB");
56996fa255fdSdan return TCL_ERROR;
57006fa255fdSdan }
57016fa255fdSdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
57026fa255fdSdan rc = sqlite3_db_cacheflush(db);
57036fa255fdSdan if( rc ){
57046fa255fdSdan Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
57056fa255fdSdan return TCL_ERROR;
57066fa255fdSdan }
57076fa255fdSdan
57086fa255fdSdan Tcl_ResetResult(interp);
57096fa255fdSdan return TCL_OK;
57106fa255fdSdan }
57116fa255fdSdan
57126fa255fdSdan /*
57130e80e509Sdrh ** Usage: sqlite3_system_errno DB
57140e80e509Sdrh **
57150e80e509Sdrh ** Return the low-level system errno value.
57160e80e509Sdrh */
test_system_errno(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])57177617e4a8Smistachkin static int SQLITE_TCLAPI test_system_errno(
57180e80e509Sdrh void * clientData,
57190e80e509Sdrh Tcl_Interp *interp,
57200e80e509Sdrh int objc,
57210e80e509Sdrh Tcl_Obj *CONST objv[]
57220e80e509Sdrh ){
57230e80e509Sdrh sqlite3 *db;
57240e80e509Sdrh int iErrno;
57250e80e509Sdrh if( objc!=2 ){
57260e80e509Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DB");
57270e80e509Sdrh return TCL_ERROR;
57280e80e509Sdrh }
57290e80e509Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
57300e80e509Sdrh iErrno = sqlite3_system_errno(db);
57310e80e509Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(iErrno));
57320e80e509Sdrh return TCL_OK;
57330e80e509Sdrh }
57340e80e509Sdrh
57350e80e509Sdrh /*
5736283829cbSdrh ** Usage: sqlite3_db_filename DB DBNAME
5737283829cbSdrh **
5738283829cbSdrh ** Return the name of a file associated with a database.
5739283829cbSdrh */
test_db_filename(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])57407617e4a8Smistachkin static int SQLITE_TCLAPI test_db_filename(
5741283829cbSdrh void * clientData,
5742283829cbSdrh Tcl_Interp *interp,
5743283829cbSdrh int objc,
5744283829cbSdrh Tcl_Obj *CONST objv[]
5745283829cbSdrh ){
5746283829cbSdrh sqlite3 *db;
5747283829cbSdrh const char *zDbName;
5748283829cbSdrh if( objc!=3 ){
5749283829cbSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
5750283829cbSdrh return TCL_ERROR;
5751283829cbSdrh }
5752283829cbSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
5753283829cbSdrh zDbName = Tcl_GetString(objv[2]);
5754283829cbSdrh Tcl_AppendResult(interp, sqlite3_db_filename(db, zDbName), (void*)0);
5755283829cbSdrh return TCL_OK;
5756283829cbSdrh }
5757283829cbSdrh
5758283829cbSdrh /*
5759421377e6Sdrh ** Usage: sqlite3_db_readonly DB DBNAME
5760421377e6Sdrh **
5761421377e6Sdrh ** Return 1 or 0 if DBNAME is readonly or not. Return -1 if DBNAME does
5762421377e6Sdrh ** not exist.
5763421377e6Sdrh */
test_db_readonly(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])57647617e4a8Smistachkin static int SQLITE_TCLAPI test_db_readonly(
5765421377e6Sdrh void * clientData,
5766421377e6Sdrh Tcl_Interp *interp,
5767421377e6Sdrh int objc,
5768421377e6Sdrh Tcl_Obj *CONST objv[]
5769421377e6Sdrh ){
5770421377e6Sdrh sqlite3 *db;
5771421377e6Sdrh const char *zDbName;
5772421377e6Sdrh if( objc!=3 ){
5773421377e6Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
5774421377e6Sdrh return TCL_ERROR;
5775421377e6Sdrh }
5776421377e6Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
5777421377e6Sdrh zDbName = Tcl_GetString(objv[2]);
5778421377e6Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_db_readonly(db, zDbName)));
5779421377e6Sdrh return TCL_OK;
5780421377e6Sdrh }
5781421377e6Sdrh
5782421377e6Sdrh /*
57836aafc29bSdrh ** Usage: sqlite3_soft_heap_limit ?N?
57846aafc29bSdrh **
57856aafc29bSdrh ** Query or set the soft heap limit for the current thread. The
57866aafc29bSdrh ** limit is only changed if the N is present. The previous limit
57876aafc29bSdrh ** is returned.
57886aafc29bSdrh */
test_soft_heap_limit(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])57897617e4a8Smistachkin static int SQLITE_TCLAPI test_soft_heap_limit(
57906aafc29bSdrh void * clientData,
57916aafc29bSdrh Tcl_Interp *interp,
57926aafc29bSdrh int objc,
57936aafc29bSdrh Tcl_Obj *CONST objv[]
57946aafc29bSdrh ){
5795f82ccf64Sdrh sqlite3_int64 amt;
5796b3f787f4Sdrh Tcl_WideInt N = -1;
57976aafc29bSdrh if( objc!=1 && objc!=2 ){
57986aafc29bSdrh Tcl_WrongNumArgs(interp, 1, objv, "?N?");
57996aafc29bSdrh return TCL_ERROR;
58006aafc29bSdrh }
58016aafc29bSdrh if( objc==2 ){
5802f82ccf64Sdrh if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
58036aafc29bSdrh }
5804f82ccf64Sdrh amt = sqlite3_soft_heap_limit64(N);
5805f82ccf64Sdrh Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt));
58066aafc29bSdrh return TCL_OK;
58076aafc29bSdrh }
58086aafc29bSdrh
58096aafc29bSdrh /*
581010c0e711Sdrh ** Usage: sqlite3_hard_heap_limit ?N?
581110c0e711Sdrh **
581210c0e711Sdrh ** Query or set the hard heap limit for the current thread. The
581310c0e711Sdrh ** limit is only changed if the N is present. The previous limit
581410c0e711Sdrh ** is returned.
581510c0e711Sdrh */
test_hard_heap_limit(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])581610c0e711Sdrh static int SQLITE_TCLAPI test_hard_heap_limit(
581710c0e711Sdrh void * clientData,
581810c0e711Sdrh Tcl_Interp *interp,
581910c0e711Sdrh int objc,
582010c0e711Sdrh Tcl_Obj *CONST objv[]
582110c0e711Sdrh ){
582210c0e711Sdrh sqlite3_int64 amt;
582310c0e711Sdrh Tcl_WideInt N = -1;
582410c0e711Sdrh if( objc!=1 && objc!=2 ){
582510c0e711Sdrh Tcl_WrongNumArgs(interp, 1, objv, "?N?");
582610c0e711Sdrh return TCL_ERROR;
582710c0e711Sdrh }
582810c0e711Sdrh if( objc==2 ){
582910c0e711Sdrh if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
583010c0e711Sdrh }
583110c0e711Sdrh amt = sqlite3_hard_heap_limit64(N);
583210c0e711Sdrh Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt));
583310c0e711Sdrh return TCL_OK;
583410c0e711Sdrh }
583510c0e711Sdrh
583610c0e711Sdrh /*
5837b4bc7057Sdrh ** Usage: sqlite3_thread_cleanup
5838b4bc7057Sdrh **
5839b4bc7057Sdrh ** Call the sqlite3_thread_cleanup API.
5840b4bc7057Sdrh */
test_thread_cleanup(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])58417617e4a8Smistachkin static int SQLITE_TCLAPI test_thread_cleanup(
5842b4bc7057Sdrh void * clientData,
5843b4bc7057Sdrh Tcl_Interp *interp,
5844b4bc7057Sdrh int objc,
5845b4bc7057Sdrh Tcl_Obj *CONST objv[]
5846b4bc7057Sdrh ){
5847eec556d3Sshane #ifndef SQLITE_OMIT_DEPRECATED
5848b4bc7057Sdrh sqlite3_thread_cleanup();
5849eec556d3Sshane #endif
5850b4bc7057Sdrh return TCL_OK;
5851b4bc7057Sdrh }
5852b4bc7057Sdrh
5853b4bc7057Sdrh /*
5854c6ba55f4Sdrh ** Usage: sqlite3_pager_refcounts DB
5855c6ba55f4Sdrh **
5856f5345443Sdrh ** Return a list of numbers which are the PagerRefcount for all
5857f5345443Sdrh ** pagers on each database connection.
5858c6ba55f4Sdrh */
test_pager_refcounts(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])58597617e4a8Smistachkin static int SQLITE_TCLAPI test_pager_refcounts(
5860c6ba55f4Sdrh void * clientData,
5861c6ba55f4Sdrh Tcl_Interp *interp,
5862c6ba55f4Sdrh int objc,
5863c6ba55f4Sdrh Tcl_Obj *CONST objv[]
5864c6ba55f4Sdrh ){
5865c6ba55f4Sdrh sqlite3 *db;
5866c6ba55f4Sdrh int i;
5867c6ba55f4Sdrh int v, *a;
5868c6ba55f4Sdrh Tcl_Obj *pResult;
5869c6ba55f4Sdrh
5870c6ba55f4Sdrh if( objc!=2 ){
5871c6ba55f4Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
5872f5345443Sdrh Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
5873c6ba55f4Sdrh return TCL_ERROR;
5874c6ba55f4Sdrh }
5875c6ba55f4Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
5876c6ba55f4Sdrh pResult = Tcl_NewObj();
5877c6ba55f4Sdrh for(i=0; i<db->nDb; i++){
5878c6ba55f4Sdrh if( db->aDb[i].pBt==0 ){
5879c6ba55f4Sdrh v = -1;
5880c6ba55f4Sdrh }else{
588127641703Sdrh sqlite3_mutex_enter(db->mutex);
5882c6ba55f4Sdrh a = sqlite3PagerStats(sqlite3BtreePager(db->aDb[i].pBt));
5883c6ba55f4Sdrh v = a[0];
588427641703Sdrh sqlite3_mutex_leave(db->mutex);
5885c6ba55f4Sdrh }
5886c6ba55f4Sdrh Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(v));
5887c6ba55f4Sdrh }
5888c6ba55f4Sdrh Tcl_SetObjResult(interp, pResult);
5889c6ba55f4Sdrh return TCL_OK;
5890c6ba55f4Sdrh }
5891c6ba55f4Sdrh
5892c6ba55f4Sdrh
5893c6ba55f4Sdrh /*
589480788d8bSdrh ** tclcmd: working_64bit_int
589580788d8bSdrh **
589680788d8bSdrh ** Some TCL builds (ex: cygwin) do not support 64-bit integers. This
589780788d8bSdrh ** leads to a number of test failures. The present command checks the
589880788d8bSdrh ** TCL build to see whether or not it supports 64-bit integers. It
589980788d8bSdrh ** returns TRUE if it does and FALSE if not.
590080788d8bSdrh **
590180788d8bSdrh ** This command is used to warn users that their TCL build is defective
590280788d8bSdrh ** and that the errors they are seeing in the test scripts might be
590380788d8bSdrh ** a result of their defective TCL rather than problems in SQLite.
590480788d8bSdrh */
working_64bit_int(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])59057617e4a8Smistachkin static int SQLITE_TCLAPI working_64bit_int(
590680788d8bSdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
590780788d8bSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
590880788d8bSdrh int objc, /* Number of arguments */
590980788d8bSdrh Tcl_Obj *CONST objv[] /* Command arguments */
591080788d8bSdrh ){
591180788d8bSdrh Tcl_Obj *pTestObj;
591280788d8bSdrh int working = 0;
591380788d8bSdrh
591480788d8bSdrh pTestObj = Tcl_NewWideIntObj(1000000*(i64)1234567890);
591580788d8bSdrh working = strcmp(Tcl_GetString(pTestObj), "1234567890000000")==0;
591680788d8bSdrh Tcl_DecrRefCount(pTestObj);
591780788d8bSdrh Tcl_SetObjResult(interp, Tcl_NewBooleanObj(working));
591880788d8bSdrh return TCL_OK;
591980788d8bSdrh }
592080788d8bSdrh
592180788d8bSdrh
592280788d8bSdrh /*
59239bc5449fSdrh ** tclcmd: vfs_unlink_test
59249bc5449fSdrh **
59259bc5449fSdrh ** This TCL command unregisters the primary VFS and then registers
59269bc5449fSdrh ** it back again. This is used to test the ability to register a
59279bc5449fSdrh ** VFS when none are previously registered, and the ability to
59289bc5449fSdrh ** unregister the only available VFS. Ticket #2738
59299bc5449fSdrh */
vfs_unlink_test(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])59307617e4a8Smistachkin static int SQLITE_TCLAPI vfs_unlink_test(
59319bc5449fSdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
59329bc5449fSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
59339bc5449fSdrh int objc, /* Number of arguments */
59349bc5449fSdrh Tcl_Obj *CONST objv[] /* Command arguments */
59359bc5449fSdrh ){
59369bc5449fSdrh int i;
593791fd4d46Sdrh sqlite3_vfs *pMain;
59389bc5449fSdrh sqlite3_vfs *apVfs[20];
593991fd4d46Sdrh sqlite3_vfs one, two;
59409bc5449fSdrh
594191fd4d46Sdrh sqlite3_vfs_unregister(0); /* Unregister of NULL is harmless */
594291fd4d46Sdrh one.zName = "__one";
594391fd4d46Sdrh two.zName = "__two";
594491fd4d46Sdrh
594591fd4d46Sdrh /* Calling sqlite3_vfs_register with 2nd argument of 0 does not
594691fd4d46Sdrh ** change the default VFS
594791fd4d46Sdrh */
594891fd4d46Sdrh pMain = sqlite3_vfs_find(0);
594991fd4d46Sdrh sqlite3_vfs_register(&one, 0);
595091fd4d46Sdrh assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
595191fd4d46Sdrh sqlite3_vfs_register(&two, 0);
595291fd4d46Sdrh assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
595391fd4d46Sdrh
595491fd4d46Sdrh /* We can find a VFS by its name */
595591fd4d46Sdrh assert( sqlite3_vfs_find("__one")==&one );
595691fd4d46Sdrh assert( sqlite3_vfs_find("__two")==&two );
595791fd4d46Sdrh
595891fd4d46Sdrh /* Calling sqlite_vfs_register with non-zero second parameter changes the
595991fd4d46Sdrh ** default VFS, even if the 1st parameter is an existig VFS that is
596091fd4d46Sdrh ** previously registered as the non-default.
596191fd4d46Sdrh */
596291fd4d46Sdrh sqlite3_vfs_register(&one, 1);
596391fd4d46Sdrh assert( sqlite3_vfs_find("__one")==&one );
596491fd4d46Sdrh assert( sqlite3_vfs_find("__two")==&two );
596591fd4d46Sdrh assert( sqlite3_vfs_find(0)==&one );
596691fd4d46Sdrh sqlite3_vfs_register(&two, 1);
596791fd4d46Sdrh assert( sqlite3_vfs_find("__one")==&one );
596891fd4d46Sdrh assert( sqlite3_vfs_find("__two")==&two );
596991fd4d46Sdrh assert( sqlite3_vfs_find(0)==&two );
597091fd4d46Sdrh if( pMain ){
597191fd4d46Sdrh sqlite3_vfs_register(pMain, 1);
597291fd4d46Sdrh assert( sqlite3_vfs_find("__one")==&one );
597391fd4d46Sdrh assert( sqlite3_vfs_find("__two")==&two );
597491fd4d46Sdrh assert( sqlite3_vfs_find(0)==pMain );
597591fd4d46Sdrh }
597691fd4d46Sdrh
597791fd4d46Sdrh /* Unlink the default VFS. Repeat until there are no more VFSes
597891fd4d46Sdrh ** registered.
597991fd4d46Sdrh */
59809bc5449fSdrh for(i=0; i<sizeof(apVfs)/sizeof(apVfs[0]); i++){
59819bc5449fSdrh apVfs[i] = sqlite3_vfs_find(0);
59829bc5449fSdrh if( apVfs[i] ){
59839bc5449fSdrh assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
59849bc5449fSdrh sqlite3_vfs_unregister(apVfs[i]);
59859bc5449fSdrh assert( 0==sqlite3_vfs_find(apVfs[i]->zName) );
59869bc5449fSdrh }
59879bc5449fSdrh }
59889bc5449fSdrh assert( 0==sqlite3_vfs_find(0) );
598991fd4d46Sdrh
59901f045330Smlcreech /* Register the main VFS as non-default (will be made default, since
59911f045330Smlcreech ** it'll be the only one in existence).
59921f045330Smlcreech */
59931f045330Smlcreech sqlite3_vfs_register(pMain, 0);
59941f045330Smlcreech assert( sqlite3_vfs_find(0)==pMain );
59951f045330Smlcreech
59961f045330Smlcreech /* Un-register the main VFS again to restore an empty VFS list */
59971f045330Smlcreech sqlite3_vfs_unregister(pMain);
59981f045330Smlcreech assert( 0==sqlite3_vfs_find(0) );
59991f045330Smlcreech
600091fd4d46Sdrh /* Relink all VFSes in reverse order. */
60019bc5449fSdrh for(i=sizeof(apVfs)/sizeof(apVfs[0])-1; i>=0; i--){
60029bc5449fSdrh if( apVfs[i] ){
60039bc5449fSdrh sqlite3_vfs_register(apVfs[i], 1);
60049bc5449fSdrh assert( apVfs[i]==sqlite3_vfs_find(0) );
60059bc5449fSdrh assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
60069bc5449fSdrh }
60079bc5449fSdrh }
600891fd4d46Sdrh
600991fd4d46Sdrh /* Unregister out sample VFSes. */
601091fd4d46Sdrh sqlite3_vfs_unregister(&one);
601191fd4d46Sdrh sqlite3_vfs_unregister(&two);
601291fd4d46Sdrh
601391fd4d46Sdrh /* Unregistering a VFS that is not currently registered is harmless */
601491fd4d46Sdrh sqlite3_vfs_unregister(&one);
601591fd4d46Sdrh sqlite3_vfs_unregister(&two);
601691fd4d46Sdrh assert( sqlite3_vfs_find("__one")==0 );
601791fd4d46Sdrh assert( sqlite3_vfs_find("__two")==0 );
601891fd4d46Sdrh
601991fd4d46Sdrh /* We should be left with the original default VFS back as the
602091fd4d46Sdrh ** original */
602191fd4d46Sdrh assert( sqlite3_vfs_find(0)==pMain );
602291fd4d46Sdrh
60239bc5449fSdrh return TCL_OK;
60249bc5449fSdrh }
60259bc5449fSdrh
602693aed5a1Sdrh /*
6027c8d75674Sdrh ** tclcmd: vfs_initfail_test
6028c8d75674Sdrh **
6029c8d75674Sdrh ** This TCL command attempts to vfs_find and vfs_register when the
6030c8d75674Sdrh ** sqlite3_initialize() interface is failing. All calls should fail.
6031c8d75674Sdrh */
vfs_initfail_test(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])60327617e4a8Smistachkin static int SQLITE_TCLAPI vfs_initfail_test(
6033c8d75674Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6034c8d75674Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6035c8d75674Sdrh int objc, /* Number of arguments */
6036c8d75674Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
6037c8d75674Sdrh ){
6038c8d75674Sdrh sqlite3_vfs one;
6039c8d75674Sdrh one.zName = "__one";
6040c8d75674Sdrh
6041c8d75674Sdrh if( sqlite3_vfs_find(0) ) return TCL_ERROR;
6042c8d75674Sdrh sqlite3_vfs_register(&one, 0);
6043c8d75674Sdrh if( sqlite3_vfs_find(0) ) return TCL_ERROR;
6044c8d75674Sdrh sqlite3_vfs_register(&one, 1);
6045c8d75674Sdrh if( sqlite3_vfs_find(0) ) return TCL_ERROR;
6046c8d75674Sdrh return TCL_OK;
6047c8d75674Sdrh }
6048c8d75674Sdrh
6049c8d75674Sdrh /*
6050a2820970Sdrh ** Saved VFSes
6051a2820970Sdrh */
6052a2820970Sdrh static sqlite3_vfs *apVfs[20];
6053a2820970Sdrh static int nVfs = 0;
6054a2820970Sdrh
6055a2820970Sdrh /*
6056a2820970Sdrh ** tclcmd: vfs_unregister_all
6057a2820970Sdrh **
6058a2820970Sdrh ** Unregister all VFSes.
6059a2820970Sdrh */
vfs_unregister_all(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])60607617e4a8Smistachkin static int SQLITE_TCLAPI vfs_unregister_all(
6061a2820970Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6062a2820970Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6063a2820970Sdrh int objc, /* Number of arguments */
6064a2820970Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
6065a2820970Sdrh ){
6066a2820970Sdrh int i;
6067a2820970Sdrh for(i=0; i<ArraySize(apVfs); i++){
6068a2820970Sdrh apVfs[i] = sqlite3_vfs_find(0);
6069a2820970Sdrh if( apVfs[i]==0 ) break;
6070a2820970Sdrh sqlite3_vfs_unregister(apVfs[i]);
6071a2820970Sdrh }
6072a2820970Sdrh nVfs = i;
6073a2820970Sdrh return TCL_OK;
6074a2820970Sdrh }
6075a2820970Sdrh /*
6076a2820970Sdrh ** tclcmd: vfs_reregister_all
6077a2820970Sdrh **
607805accd22Sdan ** Restore all VFSes that were removed using vfs_unregister_all. Taking
607905accd22Sdan ** care to put the linked list back together in the same order as it was
608005accd22Sdan ** in before vfs_unregister_all was invoked.
6081a2820970Sdrh */
vfs_reregister_all(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])60827617e4a8Smistachkin static int SQLITE_TCLAPI vfs_reregister_all(
6083a2820970Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6084a2820970Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6085a2820970Sdrh int objc, /* Number of arguments */
6086a2820970Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
6087a2820970Sdrh ){
6088a2820970Sdrh int i;
608905accd22Sdan for(i=nVfs-1; i>=0; i--){
609005accd22Sdan sqlite3_vfs_register(apVfs[i], 1);
6091a2820970Sdrh }
6092a2820970Sdrh return TCL_OK;
6093a2820970Sdrh }
6094a2820970Sdrh
6095a2820970Sdrh
6096a2820970Sdrh /*
609755176259Sdrh ** tclcmd: file_control_test DB
609855176259Sdrh **
609955176259Sdrh ** This TCL command runs the sqlite3_file_control interface and
610055176259Sdrh ** verifies correct operation of the same.
610155176259Sdrh */
file_control_test(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])61027617e4a8Smistachkin static int SQLITE_TCLAPI file_control_test(
610355176259Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
610455176259Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
610555176259Sdrh int objc, /* Number of arguments */
610655176259Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
610755176259Sdrh ){
610855176259Sdrh int iArg = 0;
610955176259Sdrh sqlite3 *db;
611055176259Sdrh int rc;
611155176259Sdrh
611255176259Sdrh if( objc!=2 ){
611355176259Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
611455176259Sdrh Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
611555176259Sdrh return TCL_ERROR;
611655176259Sdrh }
611755176259Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
611855176259Sdrh rc = sqlite3_file_control(db, 0, 0, &iArg);
61190b52b7d0Sdrh assert( rc==SQLITE_NOTFOUND );
612055176259Sdrh rc = sqlite3_file_control(db, "notadatabase", SQLITE_FCNTL_LOCKSTATE, &iArg);
612155176259Sdrh assert( rc==SQLITE_ERROR );
612255176259Sdrh rc = sqlite3_file_control(db, "main", -1, &iArg);
61230b52b7d0Sdrh assert( rc==SQLITE_NOTFOUND );
612455176259Sdrh rc = sqlite3_file_control(db, "temp", -1, &iArg);
61250b52b7d0Sdrh assert( rc==SQLITE_NOTFOUND || rc==SQLITE_ERROR );
6126aebf413dSaswift
612755176259Sdrh return TCL_OK;
612855176259Sdrh }
612955176259Sdrh
6130aebf413dSaswift
6131aebf413dSaswift /*
6132aebf413dSaswift ** tclcmd: file_control_lasterrno_test DB
6133aebf413dSaswift **
6134aebf413dSaswift ** This TCL command runs the sqlite3_file_control interface and
6135aebf413dSaswift ** verifies correct operation of the SQLITE_LAST_ERRNO verb.
6136aebf413dSaswift */
file_control_lasterrno_test(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])61377617e4a8Smistachkin static int SQLITE_TCLAPI file_control_lasterrno_test(
6138aebf413dSaswift ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6139aebf413dSaswift Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6140aebf413dSaswift int objc, /* Number of arguments */
6141aebf413dSaswift Tcl_Obj *CONST objv[] /* Command arguments */
6142aebf413dSaswift ){
6143aebf413dSaswift int iArg = 0;
6144aebf413dSaswift sqlite3 *db;
6145aebf413dSaswift int rc;
6146aebf413dSaswift
6147aebf413dSaswift if( objc!=2 ){
6148aebf413dSaswift Tcl_AppendResult(interp, "wrong # args: should be \"",
6149aebf413dSaswift Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
6150aebf413dSaswift return TCL_ERROR;
6151aebf413dSaswift }
61529db299fbSshane if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
61539db299fbSshane return TCL_ERROR;
61549db299fbSshane }
6155aebf413dSaswift rc = sqlite3_file_control(db, NULL, SQLITE_LAST_ERRNO, &iArg);
61569db299fbSshane if( rc ){
61579db299fbSshane Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
61589db299fbSshane return TCL_ERROR;
61599db299fbSshane }
6160aebf413dSaswift if( iArg!=0 ) {
6161aebf413dSaswift Tcl_AppendResult(interp, "Unexpected non-zero errno: ",
6162aebf413dSaswift Tcl_GetStringFromObj(Tcl_NewIntObj(iArg), 0), " ", 0);
6163aebf413dSaswift return TCL_ERROR;
6164aebf413dSaswift }
6165aebf413dSaswift return TCL_OK;
6166aebf413dSaswift }
6167aebf413dSaswift
6168aebf413dSaswift /*
6169ea99a31cSdrh ** tclcmd: file_control_data_version DB DBNAME
6170ea99a31cSdrh **
6171ea99a31cSdrh ** This TCL command runs the sqlite3_file_control with the
6172ea99a31cSdrh ** SQLITE_FCNTL_DATA_VERSION opcode, returning the result.
6173ea99a31cSdrh */
file_control_data_version(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])6174ea99a31cSdrh static int SQLITE_TCLAPI file_control_data_version(
6175ea99a31cSdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6176ea99a31cSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6177ea99a31cSdrh int objc, /* Number of arguments */
6178ea99a31cSdrh Tcl_Obj *CONST objv[] /* Command arguments */
6179ea99a31cSdrh ){
6180ea99a31cSdrh unsigned int iVers; /* data version */
6181ea99a31cSdrh char *zDb; /* Db name ("main", "temp" etc.) */
6182ea99a31cSdrh sqlite3 *db; /* Database handle */
6183ea99a31cSdrh int rc; /* file_control() return code */
6184ea99a31cSdrh char zBuf[100];
6185ea99a31cSdrh
6186ea99a31cSdrh if( objc!=3 && objc!=2 ){
6187ea99a31cSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB [DBNAME]");
6188ea99a31cSdrh return TCL_ERROR;
6189ea99a31cSdrh }
6190ea99a31cSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6191ea99a31cSdrh return TCL_ERROR;
6192ea99a31cSdrh }
6193ea99a31cSdrh zDb = objc==3 ? Tcl_GetString(objv[2]) : NULL;
6194ea99a31cSdrh
6195ea99a31cSdrh rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_DATA_VERSION, (void *)&iVers);
6196ea99a31cSdrh if( rc ){
6197ea99a31cSdrh Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
6198ea99a31cSdrh return TCL_ERROR;
6199ea99a31cSdrh }else{
6200ea99a31cSdrh sqlite3_snprintf(sizeof(zBuf),zBuf,"%u",iVers);
6201ea99a31cSdrh Tcl_SetResult(interp, (char *)zBuf, TCL_VOLATILE);
6202ea99a31cSdrh return TCL_OK;
6203ea99a31cSdrh }
6204ea99a31cSdrh }
6205ea99a31cSdrh
6206ea99a31cSdrh /*
62076e09d69cSdan ** tclcmd: file_control_chunksize_test DB DBNAME SIZE
62086e09d69cSdan **
62096e09d69cSdan ** This TCL command runs the sqlite3_file_control interface and
62106e09d69cSdan ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
62116e09d69cSdan ** SQLITE_SET_LOCKPROXYFILE verbs.
62126e09d69cSdan */
file_control_chunksize_test(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])62137617e4a8Smistachkin static int SQLITE_TCLAPI file_control_chunksize_test(
62146e09d69cSdan ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
62156e09d69cSdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
62166e09d69cSdan int objc, /* Number of arguments */
62176e09d69cSdan Tcl_Obj *CONST objv[] /* Command arguments */
62186e09d69cSdan ){
62196e09d69cSdan int nSize; /* New chunk size */
62206e09d69cSdan char *zDb; /* Db name ("main", "temp" etc.) */
62216e09d69cSdan sqlite3 *db; /* Database handle */
62226e09d69cSdan int rc; /* file_control() return code */
62236e09d69cSdan
62246e09d69cSdan if( objc!=4 ){
62256e09d69cSdan Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
62266e09d69cSdan return TCL_ERROR;
62276e09d69cSdan }
62286e09d69cSdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
62296e09d69cSdan || Tcl_GetIntFromObj(interp, objv[3], &nSize)
62306e09d69cSdan ){
62316e09d69cSdan return TCL_ERROR;
62326e09d69cSdan }
62336e09d69cSdan zDb = Tcl_GetString(objv[2]);
62346e09d69cSdan if( zDb[0]=='\0' ) zDb = NULL;
62356e09d69cSdan
62366e09d69cSdan rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_CHUNK_SIZE, (void *)&nSize);
62376e09d69cSdan if( rc ){
6238e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
62396e09d69cSdan return TCL_ERROR;
62406e09d69cSdan }
62416e09d69cSdan return TCL_OK;
62426e09d69cSdan }
62436e09d69cSdan
62446e09d69cSdan /*
6245661d71afSdan ** tclcmd: file_control_sizehint_test DB DBNAME SIZE
6246661d71afSdan **
6247fdd7f71eSdrh ** This TCL command runs the sqlite3_file_control interface
6248fdd7f71eSdrh ** with SQLITE_FCNTL_SIZE_HINT
6249661d71afSdan */
file_control_sizehint_test(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])62507617e4a8Smistachkin static int SQLITE_TCLAPI file_control_sizehint_test(
6251661d71afSdan ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6252661d71afSdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6253661d71afSdan int objc, /* Number of arguments */
6254661d71afSdan Tcl_Obj *CONST objv[] /* Command arguments */
6255661d71afSdan ){
6256b3f787f4Sdrh Tcl_WideInt nSize; /* Hinted size */
6257661d71afSdan char *zDb; /* Db name ("main", "temp" etc.) */
6258661d71afSdan sqlite3 *db; /* Database handle */
6259661d71afSdan int rc; /* file_control() return code */
6260661d71afSdan
6261661d71afSdan if( objc!=4 ){
6262661d71afSdan Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
6263661d71afSdan return TCL_ERROR;
6264661d71afSdan }
6265661d71afSdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
6266661d71afSdan || Tcl_GetWideIntFromObj(interp, objv[3], &nSize)
6267661d71afSdan ){
6268661d71afSdan return TCL_ERROR;
6269661d71afSdan }
6270661d71afSdan zDb = Tcl_GetString(objv[2]);
6271661d71afSdan if( zDb[0]=='\0' ) zDb = NULL;
6272661d71afSdan
6273661d71afSdan rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_SIZE_HINT, (void *)&nSize);
6274661d71afSdan if( rc ){
6275e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
6276661d71afSdan return TCL_ERROR;
6277661d71afSdan }
6278661d71afSdan return TCL_OK;
6279661d71afSdan }
6280661d71afSdan
6281661d71afSdan /*
6282ad24581eSdrh ** tclcmd: file_control_lockproxy_test DB PWD
6283aebf413dSaswift **
6284aebf413dSaswift ** This TCL command runs the sqlite3_file_control interface and
6285aebf413dSaswift ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
6286aebf413dSaswift ** SQLITE_SET_LOCKPROXYFILE verbs.
6287aebf413dSaswift */
file_control_lockproxy_test(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])62887617e4a8Smistachkin static int SQLITE_TCLAPI file_control_lockproxy_test(
6289aebf413dSaswift ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6290aebf413dSaswift Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6291aebf413dSaswift int objc, /* Number of arguments */
6292aebf413dSaswift Tcl_Obj *CONST objv[] /* Command arguments */
6293aebf413dSaswift ){
6294aebf413dSaswift sqlite3 *db;
6295aebf413dSaswift
6296ad24581eSdrh if( objc!=3 ){
6297aebf413dSaswift Tcl_AppendResult(interp, "wrong # args: should be \"",
6298ad24581eSdrh Tcl_GetStringFromObj(objv[0], 0), " DB PWD", 0);
6299aebf413dSaswift return TCL_ERROR;
6300aebf413dSaswift }
63019db299fbSshane if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
63029db299fbSshane return TCL_ERROR;
63039db299fbSshane }
6304aebf413dSaswift
63059b35ea62Sdrh #if !defined(SQLITE_ENABLE_LOCKING_STYLE)
6306d2cb50b7Sdrh # if defined(__APPLE__)
63079b35ea62Sdrh # define SQLITE_ENABLE_LOCKING_STYLE 1
63089b35ea62Sdrh # else
63099b35ea62Sdrh # define SQLITE_ENABLE_LOCKING_STYLE 0
63109b35ea62Sdrh # endif
63119b35ea62Sdrh #endif
6312d2cb50b7Sdrh #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
6313aebf413dSaswift {
6314aebf413dSaswift char *testPath;
6315103fe743Sdrh int rc;
6316caffb1a5Sdrh int nPwd;
6317caffb1a5Sdrh const char *zPwd;
6318ad24581eSdrh char proxyPath[400];
6319ad24581eSdrh
6320caffb1a5Sdrh zPwd = Tcl_GetStringFromObj(objv[2], &nPwd);
6321ad24581eSdrh if( sizeof(proxyPath)<nPwd+20 ){
6322ad24581eSdrh Tcl_AppendResult(interp, "PWD too big", (void*)0);
6323ad24581eSdrh return TCL_ERROR;
6324ad24581eSdrh }
632565545b59Sdrh sqlite3_snprintf(sizeof(proxyPath), proxyPath, "%s/test.proxy", zPwd);
6326aebf413dSaswift rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
63277708e972Sdrh if( rc ){
63289db299fbSshane Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
63299db299fbSshane return TCL_ERROR;
63307708e972Sdrh }
6331aebf413dSaswift rc = sqlite3_file_control(db, NULL, SQLITE_GET_LOCKPROXYFILE, &testPath);
6332aebf413dSaswift if( strncmp(proxyPath,testPath,11) ){
63337708e972Sdrh Tcl_AppendResult(interp, "Lock proxy file did not match the "
63347708e972Sdrh "previously assigned value", 0);
6335aebf413dSaswift return TCL_ERROR;
6336aebf413dSaswift }
63377708e972Sdrh if( rc ){
63387708e972Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
63397708e972Sdrh return TCL_ERROR;
63407708e972Sdrh }
6341aebf413dSaswift rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
63427708e972Sdrh if( rc ){
63437708e972Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
63447708e972Sdrh return TCL_ERROR;
63457708e972Sdrh }
6346aebf413dSaswift }
6347aebf413dSaswift #endif
6348aebf413dSaswift return TCL_OK;
6349aebf413dSaswift }
6350aebf413dSaswift
63516b98d67bSmistachkin #if SQLITE_OS_WIN
6352d0cdf012Sdrh /*
6353d0cdf012Sdrh ** tclcmd: file_control_win32_av_retry DB NRETRY DELAY
6354d0cdf012Sdrh **
6355d0cdf012Sdrh ** This TCL command runs the sqlite3_file_control interface with
6356d0cdf012Sdrh ** the SQLITE_FCNTL_WIN32_AV_RETRY opcode.
6357d0cdf012Sdrh */
file_control_win32_av_retry(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])63587617e4a8Smistachkin static int SQLITE_TCLAPI file_control_win32_av_retry(
6359d0cdf012Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6360d0cdf012Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6361d0cdf012Sdrh int objc, /* Number of arguments */
6362d0cdf012Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
6363d0cdf012Sdrh ){
6364d0cdf012Sdrh sqlite3 *db;
6365d0cdf012Sdrh int rc;
6366d0cdf012Sdrh int a[2];
6367d0cdf012Sdrh char z[100];
6368d0cdf012Sdrh
6369d0cdf012Sdrh if( objc!=4 ){
6370d0cdf012Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
6371d0cdf012Sdrh Tcl_GetStringFromObj(objv[0], 0), " DB NRETRY DELAY", 0);
6372d0cdf012Sdrh return TCL_ERROR;
6373d0cdf012Sdrh }
6374d0cdf012Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6375d0cdf012Sdrh return TCL_ERROR;
6376d0cdf012Sdrh }
6377d0cdf012Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &a[0]) ) return TCL_ERROR;
6378d0cdf012Sdrh if( Tcl_GetIntFromObj(interp, objv[3], &a[1]) ) return TCL_ERROR;
6379d0cdf012Sdrh rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a);
6380d0cdf012Sdrh sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]);
6381d0cdf012Sdrh Tcl_AppendResult(interp, z, (char*)0);
6382d0cdf012Sdrh return TCL_OK;
6383d0cdf012Sdrh }
6384d0cdf012Sdrh
6385253cea5cSdrh /*
63861b361ff3Smistachkin ** tclcmd: file_control_win32_get_handle DB
63871b361ff3Smistachkin **
63881b361ff3Smistachkin ** This TCL command runs the sqlite3_file_control interface with
63891b361ff3Smistachkin ** the SQLITE_FCNTL_WIN32_GET_HANDLE opcode.
63901b361ff3Smistachkin */
file_control_win32_get_handle(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])63911b361ff3Smistachkin static int file_control_win32_get_handle(
63921b361ff3Smistachkin ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
63931b361ff3Smistachkin Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
63941b361ff3Smistachkin int objc, /* Number of arguments */
63951b361ff3Smistachkin Tcl_Obj *CONST objv[] /* Command arguments */
63961b361ff3Smistachkin ){
63971b361ff3Smistachkin sqlite3 *db;
63981b361ff3Smistachkin int rc;
63991b361ff3Smistachkin HANDLE hFile = NULL;
64001b361ff3Smistachkin char z[100];
64011b361ff3Smistachkin
64021b361ff3Smistachkin if( objc!=2 ){
64031b361ff3Smistachkin Tcl_AppendResult(interp, "wrong # args: should be \"",
64041b361ff3Smistachkin Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
64051b361ff3Smistachkin return TCL_ERROR;
64061b361ff3Smistachkin }
64071b361ff3Smistachkin if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
64081b361ff3Smistachkin return TCL_ERROR;
64091b361ff3Smistachkin }
64101b361ff3Smistachkin rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_GET_HANDLE,
64111b361ff3Smistachkin (void*)&hFile);
64121b361ff3Smistachkin sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
64131b361ff3Smistachkin Tcl_AppendResult(interp, z, (char*)0);
64141b361ff3Smistachkin return TCL_OK;
64151b361ff3Smistachkin }
64161b361ff3Smistachkin
64171b361ff3Smistachkin /*
64186b98d67bSmistachkin ** tclcmd: file_control_win32_set_handle DB HANDLE
64196b98d67bSmistachkin **
64206b98d67bSmistachkin ** This TCL command runs the sqlite3_file_control interface with
64216b98d67bSmistachkin ** the SQLITE_FCNTL_WIN32_SET_HANDLE opcode.
64226b98d67bSmistachkin */
file_control_win32_set_handle(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])64237617e4a8Smistachkin static int SQLITE_TCLAPI file_control_win32_set_handle(
64246b98d67bSmistachkin ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
64256b98d67bSmistachkin Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
64266b98d67bSmistachkin int objc, /* Number of arguments */
64276b98d67bSmistachkin Tcl_Obj *CONST objv[] /* Command arguments */
64286b98d67bSmistachkin ){
64296b98d67bSmistachkin sqlite3 *db;
64306b98d67bSmistachkin int rc;
64316b98d67bSmistachkin HANDLE hFile = NULL;
64326b98d67bSmistachkin char z[100];
64336b98d67bSmistachkin
64346b98d67bSmistachkin if( objc!=3 ){
64356b98d67bSmistachkin Tcl_AppendResult(interp, "wrong # args: should be \"",
64366b98d67bSmistachkin Tcl_GetStringFromObj(objv[0], 0), " DB HANDLE", 0);
64376b98d67bSmistachkin return TCL_ERROR;
64386b98d67bSmistachkin }
64396b98d67bSmistachkin if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
64406b98d67bSmistachkin return TCL_ERROR;
64416b98d67bSmistachkin }
64426b98d67bSmistachkin if( getWin32Handle(interp, Tcl_GetString(objv[2]), &hFile) ){
64436b98d67bSmistachkin return TCL_ERROR;
64446b98d67bSmistachkin }
64456b98d67bSmistachkin rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_SET_HANDLE,
64466b98d67bSmistachkin (void*)&hFile);
64476b98d67bSmistachkin sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
64486b98d67bSmistachkin Tcl_AppendResult(interp, z, (char*)0);
64496b98d67bSmistachkin return TCL_OK;
64506b98d67bSmistachkin }
64516b98d67bSmistachkin #endif
64526b98d67bSmistachkin
64536b98d67bSmistachkin /*
6454253cea5cSdrh ** tclcmd: file_control_persist_wal DB PERSIST-FLAG
6455253cea5cSdrh **
6456253cea5cSdrh ** This TCL command runs the sqlite3_file_control interface with
6457253cea5cSdrh ** the SQLITE_FCNTL_PERSIST_WAL opcode.
6458253cea5cSdrh */
file_control_persist_wal(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])64597617e4a8Smistachkin static int SQLITE_TCLAPI file_control_persist_wal(
6460253cea5cSdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6461253cea5cSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6462253cea5cSdrh int objc, /* Number of arguments */
6463253cea5cSdrh Tcl_Obj *CONST objv[] /* Command arguments */
6464253cea5cSdrh ){
6465253cea5cSdrh sqlite3 *db;
6466253cea5cSdrh int rc;
6467253cea5cSdrh int bPersist;
6468253cea5cSdrh char z[100];
6469253cea5cSdrh
6470253cea5cSdrh if( objc!=3 ){
6471253cea5cSdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
6472253cea5cSdrh Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
6473253cea5cSdrh return TCL_ERROR;
6474253cea5cSdrh }
6475253cea5cSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6476253cea5cSdrh return TCL_ERROR;
6477253cea5cSdrh }
6478253cea5cSdrh if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR;
6479253cea5cSdrh rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist);
6480253cea5cSdrh sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist);
6481253cea5cSdrh Tcl_AppendResult(interp, z, (char*)0);
6482253cea5cSdrh return TCL_OK;
6483253cea5cSdrh }
6484253cea5cSdrh
6485f12b3f60Sdrh /*
6486cb15f35fSdrh ** tclcmd: file_control_powersafe_overwrite DB PSOW-FLAG
6487f12b3f60Sdrh **
6488f12b3f60Sdrh ** This TCL command runs the sqlite3_file_control interface with
6489cb15f35fSdrh ** the SQLITE_FCNTL_POWERSAFE_OVERWRITE opcode.
6490f12b3f60Sdrh */
file_control_powersafe_overwrite(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])64917617e4a8Smistachkin static int SQLITE_TCLAPI file_control_powersafe_overwrite(
6492f12b3f60Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6493f12b3f60Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6494f12b3f60Sdrh int objc, /* Number of arguments */
6495f12b3f60Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
6496f12b3f60Sdrh ){
6497f12b3f60Sdrh sqlite3 *db;
6498f12b3f60Sdrh int rc;
6499cb15f35fSdrh int b;
6500f12b3f60Sdrh char z[100];
6501f12b3f60Sdrh
6502f12b3f60Sdrh if( objc!=3 ){
6503f12b3f60Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
6504f12b3f60Sdrh Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
6505f12b3f60Sdrh return TCL_ERROR;
6506f12b3f60Sdrh }
6507f12b3f60Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6508f12b3f60Sdrh return TCL_ERROR;
6509f12b3f60Sdrh }
6510cb15f35fSdrh if( Tcl_GetIntFromObj(interp, objv[2], &b) ) return TCL_ERROR;
6511cb15f35fSdrh rc = sqlite3_file_control(db,NULL,SQLITE_FCNTL_POWERSAFE_OVERWRITE,(void*)&b);
6512cb15f35fSdrh sqlite3_snprintf(sizeof(z), z, "%d %d", rc, b);
6513f12b3f60Sdrh Tcl_AppendResult(interp, z, (char*)0);
6514f12b3f60Sdrh return TCL_OK;
6515f12b3f60Sdrh }
6516f12b3f60Sdrh
6517aebf413dSaswift
651855176259Sdrh /*
6519de60fc2dSdrh ** tclcmd: file_control_vfsname DB ?AUXDB?
6520de60fc2dSdrh **
6521de60fc2dSdrh ** Return a string that describes the stack of VFSes.
6522de60fc2dSdrh */
file_control_vfsname(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])65237617e4a8Smistachkin static int SQLITE_TCLAPI file_control_vfsname(
6524de60fc2dSdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6525de60fc2dSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6526de60fc2dSdrh int objc, /* Number of arguments */
6527de60fc2dSdrh Tcl_Obj *CONST objv[] /* Command arguments */
6528de60fc2dSdrh ){
6529de60fc2dSdrh sqlite3 *db;
6530de60fc2dSdrh const char *zDbName = "main";
6531de60fc2dSdrh char *zVfsName = 0;
6532de60fc2dSdrh
6533de60fc2dSdrh if( objc!=2 && objc!=3 ){
6534de60fc2dSdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
6535de60fc2dSdrh Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
6536de60fc2dSdrh return TCL_ERROR;
6537de60fc2dSdrh }
6538de60fc2dSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6539de60fc2dSdrh return TCL_ERROR;
6540de60fc2dSdrh }
6541de60fc2dSdrh if( objc==3 ){
6542de60fc2dSdrh zDbName = Tcl_GetString(objv[2]);
6543de60fc2dSdrh }
6544de60fc2dSdrh sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName);
6545de60fc2dSdrh Tcl_AppendResult(interp, zVfsName, (char*)0);
6546de60fc2dSdrh sqlite3_free(zVfsName);
6547de60fc2dSdrh return TCL_OK;
6548de60fc2dSdrh }
6549de60fc2dSdrh
6550696b33e6Sdrh /*
6551c30b78f6Sdan ** tclcmd: file_control_reservebytes DB N
6552c30b78f6Sdan */
file_control_reservebytes(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])6553c30b78f6Sdan static int SQLITE_TCLAPI file_control_reservebytes(
6554c30b78f6Sdan ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6555c30b78f6Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6556c30b78f6Sdan int objc, /* Number of arguments */
6557c30b78f6Sdan Tcl_Obj *CONST objv[] /* Command arguments */
6558c30b78f6Sdan ){
6559c30b78f6Sdan sqlite3 *db;
6560c30b78f6Sdan const char *zDbName = "main";
6561c30b78f6Sdan int n = 0;
6562c30b78f6Sdan int rc;
6563c30b78f6Sdan
6564c30b78f6Sdan if( objc!=3 ){
6565c30b78f6Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB N");
6566c30b78f6Sdan return TCL_ERROR;
6567c30b78f6Sdan }
6568c30b78f6Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
6569c30b78f6Sdan || Tcl_GetIntFromObj(interp, objv[2], &n)
6570c30b78f6Sdan ){
6571c30b78f6Sdan return TCL_ERROR;
6572c30b78f6Sdan }
6573c30b78f6Sdan
6574c30b78f6Sdan rc = sqlite3_file_control(db, zDbName, SQLITE_FCNTL_RESERVE_BYTES, (void*)&n);
6575c30b78f6Sdan Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
6576c30b78f6Sdan return TCL_OK;
6577c30b78f6Sdan }
6578c30b78f6Sdan
6579c30b78f6Sdan
6580c30b78f6Sdan /*
6581696b33e6Sdrh ** tclcmd: file_control_tempfilename DB ?AUXDB?
6582696b33e6Sdrh **
6583696b33e6Sdrh ** Return a string that is a temporary filename
6584696b33e6Sdrh */
file_control_tempfilename(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])65857617e4a8Smistachkin static int SQLITE_TCLAPI file_control_tempfilename(
6586696b33e6Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6587696b33e6Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6588696b33e6Sdrh int objc, /* Number of arguments */
6589696b33e6Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
6590696b33e6Sdrh ){
6591696b33e6Sdrh sqlite3 *db;
6592696b33e6Sdrh const char *zDbName = "main";
6593696b33e6Sdrh char *zTName = 0;
6594696b33e6Sdrh
6595696b33e6Sdrh if( objc!=2 && objc!=3 ){
6596696b33e6Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
6597696b33e6Sdrh Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
6598696b33e6Sdrh return TCL_ERROR;
6599696b33e6Sdrh }
6600696b33e6Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6601696b33e6Sdrh return TCL_ERROR;
6602696b33e6Sdrh }
6603696b33e6Sdrh if( objc==3 ){
6604696b33e6Sdrh zDbName = Tcl_GetString(objv[2]);
6605696b33e6Sdrh }
6606696b33e6Sdrh sqlite3_file_control(db, zDbName, SQLITE_FCNTL_TEMPFILENAME, (void*)&zTName);
6607696b33e6Sdrh Tcl_AppendResult(interp, zTName, (char*)0);
6608696b33e6Sdrh sqlite3_free(zTName);
6609696b33e6Sdrh return TCL_OK;
6610696b33e6Sdrh }
6611696b33e6Sdrh
6612aecc04d6Sdan /*
6613aecc04d6Sdan ** tclcmd: file_control_external_reader DB ?AUXDB?
6614aecc04d6Sdan **
6615aecc04d6Sdan ** Return a string that is a temporary filename
6616aecc04d6Sdan */
file_control_external_reader(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])6617aecc04d6Sdan static int SQLITE_TCLAPI file_control_external_reader(
6618aecc04d6Sdan ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6619aecc04d6Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6620aecc04d6Sdan int objc, /* Number of arguments */
6621aecc04d6Sdan Tcl_Obj *CONST objv[] /* Command arguments */
6622aecc04d6Sdan ){
6623aecc04d6Sdan sqlite3 *db;
6624aecc04d6Sdan const char *zName = "main";
6625aecc04d6Sdan int iRes = 0;
6626aecc04d6Sdan int rc = SQLITE_OK;
6627aecc04d6Sdan
6628aecc04d6Sdan if( objc!=2 && objc!=3 ){
6629aecc04d6Sdan Tcl_AppendResult(interp, "wrong # args: should be \"",
6630aecc04d6Sdan Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
6631aecc04d6Sdan return TCL_ERROR;
6632aecc04d6Sdan }
6633aecc04d6Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6634aecc04d6Sdan return TCL_ERROR;
6635aecc04d6Sdan }
6636aecc04d6Sdan if( objc==3 ){
6637aecc04d6Sdan zName = Tcl_GetString(objv[2]);
6638aecc04d6Sdan }
6639aecc04d6Sdan rc = sqlite3_file_control(db, zName, SQLITE_FCNTL_EXTERNAL_READER, &iRes);
6640aecc04d6Sdan if( rc!=SQLITE_OK ){
6641aecc04d6Sdan Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
6642aecc04d6Sdan return TCL_ERROR;
6643aecc04d6Sdan }
6644aecc04d6Sdan Tcl_SetObjResult(interp, Tcl_NewIntObj(iRes));
6645aecc04d6Sdan return TCL_OK;
6646aecc04d6Sdan }
6647aecc04d6Sdan
6648de60fc2dSdrh
6649de60fc2dSdrh /*
6650e339d65aSdanielk1977 ** tclcmd: sqlite3_vfs_list
6651e339d65aSdanielk1977 **
6652e339d65aSdanielk1977 ** Return a tcl list containing the names of all registered vfs's.
6653e339d65aSdanielk1977 */
vfs_list(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])66547617e4a8Smistachkin static int SQLITE_TCLAPI vfs_list(
6655e339d65aSdanielk1977 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6656e339d65aSdanielk1977 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6657e339d65aSdanielk1977 int objc, /* Number of arguments */
6658e339d65aSdanielk1977 Tcl_Obj *CONST objv[] /* Command arguments */
6659e339d65aSdanielk1977 ){
6660e339d65aSdanielk1977 sqlite3_vfs *pVfs;
6661e339d65aSdanielk1977 Tcl_Obj *pRet = Tcl_NewObj();
6662e339d65aSdanielk1977 if( objc!=1 ){
6663e339d65aSdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "");
6664e339d65aSdanielk1977 return TCL_ERROR;
6665e339d65aSdanielk1977 }
6666e339d65aSdanielk1977 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
6667e339d65aSdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(pVfs->zName, -1));
6668e339d65aSdanielk1977 }
6669e339d65aSdanielk1977 Tcl_SetObjResult(interp, pRet);
6670e339d65aSdanielk1977 return TCL_OK;
6671e339d65aSdanielk1977 }
6672e339d65aSdanielk1977
6673e339d65aSdanielk1977 /*
6674b1a6c3c1Sdrh ** tclcmd: sqlite3_limit DB ID VALUE
6675b1a6c3c1Sdrh **
6676b1a6c3c1Sdrh ** This TCL command runs the sqlite3_limit interface and
6677b1a6c3c1Sdrh ** verifies correct operation of the same.
6678b1a6c3c1Sdrh */
test_limit(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])66797617e4a8Smistachkin static int SQLITE_TCLAPI test_limit(
6680b1a6c3c1Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6681b1a6c3c1Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6682b1a6c3c1Sdrh int objc, /* Number of arguments */
6683b1a6c3c1Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
6684b1a6c3c1Sdrh ){
6685b1a6c3c1Sdrh sqlite3 *db;
6686b1a6c3c1Sdrh int rc;
6687b1a6c3c1Sdrh static const struct {
6688b1a6c3c1Sdrh char *zName;
6689b1a6c3c1Sdrh int id;
6690b1a6c3c1Sdrh } aId[] = {
6691b1a6c3c1Sdrh { "SQLITE_LIMIT_LENGTH", SQLITE_LIMIT_LENGTH },
6692b1a6c3c1Sdrh { "SQLITE_LIMIT_SQL_LENGTH", SQLITE_LIMIT_SQL_LENGTH },
6693b1a6c3c1Sdrh { "SQLITE_LIMIT_COLUMN", SQLITE_LIMIT_COLUMN },
6694b1a6c3c1Sdrh { "SQLITE_LIMIT_EXPR_DEPTH", SQLITE_LIMIT_EXPR_DEPTH },
6695b1a6c3c1Sdrh { "SQLITE_LIMIT_COMPOUND_SELECT", SQLITE_LIMIT_COMPOUND_SELECT },
6696b1a6c3c1Sdrh { "SQLITE_LIMIT_VDBE_OP", SQLITE_LIMIT_VDBE_OP },
6697b1a6c3c1Sdrh { "SQLITE_LIMIT_FUNCTION_ARG", SQLITE_LIMIT_FUNCTION_ARG },
6698b1a6c3c1Sdrh { "SQLITE_LIMIT_ATTACHED", SQLITE_LIMIT_ATTACHED },
6699b1a6c3c1Sdrh { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
6700b1a6c3c1Sdrh { "SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER },
6701417168adSdrh { "SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH },
67023705ef6aSdrh { "SQLITE_LIMIT_WORKER_THREADS", SQLITE_LIMIT_WORKER_THREADS },
6703521cc849Sdrh
6704521cc849Sdrh /* Out of range test cases */
6705521cc849Sdrh { "SQLITE_LIMIT_TOOSMALL", -1, },
67063705ef6aSdrh { "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_WORKER_THREADS+1 },
6707b1a6c3c1Sdrh };
670827b2f053Smistachkin int i, id = 0;
6709b1a6c3c1Sdrh int val;
6710b1a6c3c1Sdrh const char *zId;
6711b1a6c3c1Sdrh
6712b1a6c3c1Sdrh if( objc!=4 ){
6713b1a6c3c1Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"",
6714b1a6c3c1Sdrh Tcl_GetStringFromObj(objv[0], 0), " DB ID VALUE", 0);
6715b1a6c3c1Sdrh return TCL_ERROR;
6716b1a6c3c1Sdrh }
6717b1a6c3c1Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
6718b1a6c3c1Sdrh zId = Tcl_GetString(objv[2]);
6719b1a6c3c1Sdrh for(i=0; i<sizeof(aId)/sizeof(aId[0]); i++){
6720b1a6c3c1Sdrh if( strcmp(zId, aId[i].zName)==0 ){
6721b1a6c3c1Sdrh id = aId[i].id;
6722b1a6c3c1Sdrh break;
6723b1a6c3c1Sdrh }
6724b1a6c3c1Sdrh }
6725b1a6c3c1Sdrh if( i>=sizeof(aId)/sizeof(aId[0]) ){
6726b1a6c3c1Sdrh Tcl_AppendResult(interp, "unknown limit type: ", zId, (char*)0);
6727b1a6c3c1Sdrh return TCL_ERROR;
6728b1a6c3c1Sdrh }
6729b1a6c3c1Sdrh if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
6730b1a6c3c1Sdrh rc = sqlite3_limit(db, id, val);
6731b1a6c3c1Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
6732b1a6c3c1Sdrh return TCL_OK;
6733b1a6c3c1Sdrh }
6734b1a6c3c1Sdrh
6735b1a6c3c1Sdrh /*
673693aed5a1Sdrh ** tclcmd: save_prng_state
6737a2820970Sdrh **
6738a2820970Sdrh ** Save the state of the pseudo-random number generator.
6739a2820970Sdrh ** At the same time, verify that sqlite3_test_control works even when
6740a2820970Sdrh ** called with an out-of-range opcode.
674193aed5a1Sdrh */
save_prng_state(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])67427617e4a8Smistachkin static int SQLITE_TCLAPI save_prng_state(
674393aed5a1Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
674493aed5a1Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
674593aed5a1Sdrh int objc, /* Number of arguments */
674693aed5a1Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
674793aed5a1Sdrh ){
6748a2820970Sdrh int rc = sqlite3_test_control(9999);
6749a2820970Sdrh assert( rc==0 );
6750a2820970Sdrh rc = sqlite3_test_control(-1);
6751a2820970Sdrh assert( rc==0 );
67522fa1868fSdrh sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SAVE);
675393aed5a1Sdrh return TCL_OK;
675493aed5a1Sdrh }
675593aed5a1Sdrh /*
675693aed5a1Sdrh ** tclcmd: restore_prng_state
675793aed5a1Sdrh */
restore_prng_state(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])67587617e4a8Smistachkin static int SQLITE_TCLAPI restore_prng_state(
675993aed5a1Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
676093aed5a1Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
676193aed5a1Sdrh int objc, /* Number of arguments */
676293aed5a1Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
676393aed5a1Sdrh ){
67642fa1868fSdrh sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESTORE);
676593aed5a1Sdrh return TCL_OK;
676693aed5a1Sdrh }
676793aed5a1Sdrh /*
676893aed5a1Sdrh ** tclcmd: reset_prng_state
676993aed5a1Sdrh */
reset_prng_state(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])67707617e4a8Smistachkin static int SQLITE_TCLAPI reset_prng_state(
677193aed5a1Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
677293aed5a1Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
677393aed5a1Sdrh int objc, /* Number of arguments */
677493aed5a1Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
677593aed5a1Sdrh ){
6776ade54d68Sdrh sqlite3_randomness(0,0);
6777ade54d68Sdrh return TCL_OK;
6778ade54d68Sdrh }
6779ade54d68Sdrh /*
67802e6d83bcSdrh ** tclcmd: prng_seed INT ?DB?
6781ade54d68Sdrh **
67822e6d83bcSdrh ** Set up the SQLITE_TESTCTRL_PRNG_SEED pragma with parameter INT and DB.
67832e6d83bcSdrh ** INT is an integer. DB is a database connection, or a NULL pointer if
67842e6d83bcSdrh ** omitted.
67852e6d83bcSdrh **
67862e6d83bcSdrh ** When INT!=0 and DB!=0, set the PRNG seed to the value of the schema
67872e6d83bcSdrh ** cookie for DB, or to INT if the schema cookie happens to be zero.
67882e6d83bcSdrh **
67892e6d83bcSdrh ** When INT!=0 and DB==0, set the PRNG seed to just INT.
67902e6d83bcSdrh **
67912e6d83bcSdrh ** If INT==0 and DB==0 then use the default procedure of calling the
67922e6d83bcSdrh ** xRandomness method on the default VFS to get the PRNG seed.
6793ade54d68Sdrh */
prng_seed(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])6794ade54d68Sdrh static int SQLITE_TCLAPI prng_seed(
6795ade54d68Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6796ade54d68Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6797ade54d68Sdrh int objc, /* Number of arguments */
6798ade54d68Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
6799ade54d68Sdrh ){
68002e6d83bcSdrh int i = 0;
68012e6d83bcSdrh sqlite3 *db = 0;
68022e6d83bcSdrh if( objc!=2 && objc!=3 ){
68032e6d83bcSdrh Tcl_WrongNumArgs(interp, 1, objv, "SEED ?DB?");
6804ade54d68Sdrh return TCL_ERROR;
6805ade54d68Sdrh }
68068718f0b6Sdan if( Tcl_GetIntFromObj(interp,objv[1],&i) ) return TCL_ERROR;
68072e6d83bcSdrh if( objc==3 && getDbPointer(interp, Tcl_GetString(objv[2]), &db) ){
68082e6d83bcSdrh return TCL_ERROR;
68092e6d83bcSdrh }
68102e6d83bcSdrh sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, i, db);
681193aed5a1Sdrh return TCL_OK;
681293aed5a1Sdrh }
681393aed5a1Sdrh
6814062d4cb0Sdanielk1977 /*
6815ca439a49Sdrh ** tclcmd: extra_schema_checks BOOLEAN
6816ca439a49Sdrh **
6817ca439a49Sdrh ** Enable or disable schema checks when parsing the sqlite_schema file.
6818ca439a49Sdrh ** This is always enabled in production, but it is sometimes useful to
6819ca439a49Sdrh ** disable the checks in order to make some internal error states reachable
6820ca439a49Sdrh ** for testing.
6821ca439a49Sdrh */
extra_schema_checks(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])6822ca439a49Sdrh static int SQLITE_TCLAPI extra_schema_checks(
6823ca439a49Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6824ca439a49Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6825ca439a49Sdrh int objc, /* Number of arguments */
6826ca439a49Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
6827ca439a49Sdrh ){
6828ca439a49Sdrh int i = 0;
6829ca439a49Sdrh if( objc!=2 ){
6830ca439a49Sdrh Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
6831ca439a49Sdrh return TCL_ERROR;
6832ca439a49Sdrh }
6833ca439a49Sdrh if( Tcl_GetBooleanFromObj(interp,objv[1],&i) ) return TCL_ERROR;
6834ca439a49Sdrh sqlite3_test_control(SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS, i);
6835ca439a49Sdrh return TCL_OK;
6836ca439a49Sdrh }
6837ca439a49Sdrh
6838ca439a49Sdrh /*
683909fe6143Sdrh ** tclcmd: database_may_be_corrupt
684009fe6143Sdrh **
684109fe6143Sdrh ** Indicate that database files might be corrupt. In other words, set the normal
684209fe6143Sdrh ** state of operation.
684309fe6143Sdrh */
database_may_be_corrupt(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])68447617e4a8Smistachkin static int SQLITE_TCLAPI database_may_be_corrupt(
684509fe6143Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
684609fe6143Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
684709fe6143Sdrh int objc, /* Number of arguments */
684809fe6143Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
684909fe6143Sdrh ){
685009fe6143Sdrh sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 0);
685109fe6143Sdrh return TCL_OK;
685209fe6143Sdrh }
685309fe6143Sdrh /*
685409fe6143Sdrh ** tclcmd: database_never_corrupt
685509fe6143Sdrh **
6856eea8eb6dSdrh ** Indicate that database files are always well-formed. This enables
6857eea8eb6dSdrh ** extra assert() statements that test conditions that are always true
6858eea8eb6dSdrh ** for well-formed databases.
685909fe6143Sdrh */
database_never_corrupt(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])68607617e4a8Smistachkin static int SQLITE_TCLAPI database_never_corrupt(
686109fe6143Sdrh ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
686209fe6143Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
686309fe6143Sdrh int objc, /* Number of arguments */
686409fe6143Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
686509fe6143Sdrh ){
686609fe6143Sdrh sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 1);
686709fe6143Sdrh return TCL_OK;
686809fe6143Sdrh }
686909fe6143Sdrh
687009fe6143Sdrh /*
6871062d4cb0Sdanielk1977 ** tclcmd: pcache_stats
6872062d4cb0Sdanielk1977 */
test_pcache_stats(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])68737617e4a8Smistachkin static int SQLITE_TCLAPI test_pcache_stats(
6874062d4cb0Sdanielk1977 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6875062d4cb0Sdanielk1977 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6876062d4cb0Sdanielk1977 int objc, /* Number of arguments */
6877062d4cb0Sdanielk1977 Tcl_Obj *CONST objv[] /* Command arguments */
6878062d4cb0Sdanielk1977 ){
6879062d4cb0Sdanielk1977 int nMin;
6880062d4cb0Sdanielk1977 int nMax;
6881062d4cb0Sdanielk1977 int nCurrent;
6882062d4cb0Sdanielk1977 int nRecyclable;
6883062d4cb0Sdanielk1977 Tcl_Obj *pRet;
6884062d4cb0Sdanielk1977
6885062d4cb0Sdanielk1977 sqlite3PcacheStats(&nCurrent, &nMax, &nMin, &nRecyclable);
6886062d4cb0Sdanielk1977
6887062d4cb0Sdanielk1977 pRet = Tcl_NewObj();
6888062d4cb0Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("current", -1));
6889062d4cb0Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCurrent));
6890062d4cb0Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("max", -1));
6891062d4cb0Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMax));
6892062d4cb0Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("min", -1));
6893062d4cb0Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMin));
6894062d4cb0Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("recyclable", -1));
6895062d4cb0Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nRecyclable));
6896062d4cb0Sdanielk1977
6897062d4cb0Sdanielk1977 Tcl_SetObjResult(interp, pRet);
6898062d4cb0Sdanielk1977
6899062d4cb0Sdanielk1977 return TCL_OK;
6900062d4cb0Sdanielk1977 }
6901062d4cb0Sdanielk1977
690269910da9Sdrh #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
test_unlock_notify_cb(void ** aArg,int nArg)6903404ca075Sdanielk1977 static void test_unlock_notify_cb(void **aArg, int nArg){
6904404ca075Sdanielk1977 int ii;
6905404ca075Sdanielk1977 for(ii=0; ii<nArg; ii++){
6906404ca075Sdanielk1977 Tcl_EvalEx((Tcl_Interp *)aArg[ii], "unlock_notify", -1, TCL_EVAL_GLOBAL);
6907404ca075Sdanielk1977 }
6908404ca075Sdanielk1977 }
690969910da9Sdrh #endif /* SQLITE_ENABLE_UNLOCK_NOTIFY */
6910404ca075Sdanielk1977
6911404ca075Sdanielk1977 /*
6912404ca075Sdanielk1977 ** tclcmd: sqlite3_unlock_notify db
6913404ca075Sdanielk1977 */
6914404ca075Sdanielk1977 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
test_unlock_notify(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])69157617e4a8Smistachkin static int SQLITE_TCLAPI test_unlock_notify(
6916404ca075Sdanielk1977 ClientData clientData, /* Unused */
6917404ca075Sdanielk1977 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
6918404ca075Sdanielk1977 int objc, /* Number of arguments */
6919404ca075Sdanielk1977 Tcl_Obj *CONST objv[] /* Command arguments */
6920404ca075Sdanielk1977 ){
6921404ca075Sdanielk1977 sqlite3 *db;
6922404ca075Sdanielk1977 int rc;
6923404ca075Sdanielk1977
6924404ca075Sdanielk1977 if( objc!=2 ){
6925404ca075Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "DB");
6926404ca075Sdanielk1977 return TCL_ERROR;
6927404ca075Sdanielk1977 }
6928404ca075Sdanielk1977
6929404ca075Sdanielk1977 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
6930404ca075Sdanielk1977 return TCL_ERROR;
6931404ca075Sdanielk1977 }
6932404ca075Sdanielk1977 rc = sqlite3_unlock_notify(db, test_unlock_notify_cb, (void *)interp);
6933404ca075Sdanielk1977 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
6934404ca075Sdanielk1977 return TCL_OK;
6935404ca075Sdanielk1977 }
6936404ca075Sdanielk1977 #endif
6937404ca075Sdanielk1977
693887c1fe1bSdan /*
693987c1fe1bSdan ** tclcmd: sqlite3_wal_checkpoint db ?NAME?
694087c1fe1bSdan */
test_wal_checkpoint(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])69417617e4a8Smistachkin static int SQLITE_TCLAPI test_wal_checkpoint(
694287c1fe1bSdan ClientData clientData, /* Unused */
694387c1fe1bSdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
694487c1fe1bSdan int objc, /* Number of arguments */
694587c1fe1bSdan Tcl_Obj *CONST objv[] /* Command arguments */
694687c1fe1bSdan ){
694787c1fe1bSdan char *zDb = 0;
694887c1fe1bSdan sqlite3 *db;
694987c1fe1bSdan int rc;
695087c1fe1bSdan
695187c1fe1bSdan if( objc!=3 && objc!=2 ){
695287c1fe1bSdan Tcl_WrongNumArgs(interp, 1, objv, "DB ?NAME?");
695387c1fe1bSdan return TCL_ERROR;
695487c1fe1bSdan }
695587c1fe1bSdan
695687c1fe1bSdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
695787c1fe1bSdan return TCL_ERROR;
695887c1fe1bSdan }
695987c1fe1bSdan if( objc==3 ){
696087c1fe1bSdan zDb = Tcl_GetString(objv[2]);
696187c1fe1bSdan }
696287c1fe1bSdan rc = sqlite3_wal_checkpoint(db, zDb);
696387c1fe1bSdan Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
696487c1fe1bSdan return TCL_OK;
696587c1fe1bSdan }
696687c1fe1bSdan
6967eb8763d7Sdan /*
69689c5e3680Sdan ** tclcmd: sqlite3_wal_checkpoint_v2 db MODE ?NAME?
69699c5e3680Sdan **
69709c5e3680Sdan ** This command calls the wal_checkpoint_v2() function with the specified
69719c5e3680Sdan ** mode argument (passive, full or restart). If present, the database name
69729c5e3680Sdan ** NAME is passed as the second argument to wal_checkpoint_v2(). If it the
69739c5e3680Sdan ** NAME argument is not present, a NULL pointer is passed instead.
69749c5e3680Sdan **
69759c5e3680Sdan ** If wal_checkpoint_v2() returns any value other than SQLITE_BUSY or
69769c5e3680Sdan ** SQLITE_OK, then this command returns TCL_ERROR. The Tcl result is set
69779c5e3680Sdan ** to the error message obtained from sqlite3_errmsg().
69789c5e3680Sdan **
69799c5e3680Sdan ** Otherwise, this command returns a list of three integers. The first integer
69809c5e3680Sdan ** is 1 if SQLITE_BUSY was returned, or 0 otherwise. The following two integers
6981f7b5496eSdrh ** are the values returned via the output parameters by wal_checkpoint_v2() -
69829c5e3680Sdan ** the number of frames in the log and the number of frames in the log
69839c5e3680Sdan ** that have been checkpointed.
69849c5e3680Sdan */
test_wal_checkpoint_v2(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])69857617e4a8Smistachkin static int SQLITE_TCLAPI test_wal_checkpoint_v2(
69869c5e3680Sdan ClientData clientData, /* Unused */
69879c5e3680Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
69889c5e3680Sdan int objc, /* Number of arguments */
69899c5e3680Sdan Tcl_Obj *CONST objv[] /* Command arguments */
69909c5e3680Sdan ){
69919c5e3680Sdan char *zDb = 0;
69929c5e3680Sdan sqlite3 *db;
69939c5e3680Sdan int rc;
69949c5e3680Sdan
69959c5e3680Sdan int eMode;
69969c5e3680Sdan int nLog = -555;
69979c5e3680Sdan int nCkpt = -555;
69989c5e3680Sdan Tcl_Obj *pRet;
69999c5e3680Sdan
7000f26a1549Sdan const char * aMode[] = { "passive", "full", "restart", "truncate", 0 };
70019c5e3680Sdan assert( SQLITE_CHECKPOINT_PASSIVE==0 );
70029c5e3680Sdan assert( SQLITE_CHECKPOINT_FULL==1 );
70039c5e3680Sdan assert( SQLITE_CHECKPOINT_RESTART==2 );
7004f26a1549Sdan assert( SQLITE_CHECKPOINT_TRUNCATE==3 );
70059c5e3680Sdan
70069c5e3680Sdan if( objc!=3 && objc!=4 ){
70079c5e3680Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB MODE ?NAME?");
70089c5e3680Sdan return TCL_ERROR;
70099c5e3680Sdan }
70109c5e3680Sdan
70119c5e3680Sdan if( objc==4 ){
70129c5e3680Sdan zDb = Tcl_GetString(objv[3]);
70139c5e3680Sdan }
70142928d327Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) || (
70152928d327Sdan TCL_OK!=Tcl_GetIntFromObj(0, objv[2], &eMode)
70162928d327Sdan && TCL_OK!=Tcl_GetIndexFromObj(interp, objv[2], aMode, "mode", 0, &eMode)
70172928d327Sdan )){
70189c5e3680Sdan return TCL_ERROR;
70199c5e3680Sdan }
70209c5e3680Sdan
70219c5e3680Sdan rc = sqlite3_wal_checkpoint_v2(db, zDb, eMode, &nLog, &nCkpt);
70229c5e3680Sdan if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
70232928d327Sdan const char *zErrCode = sqlite3ErrName(rc);
70249778bd72Sdan Tcl_ResetResult(interp);
70252928d327Sdan Tcl_AppendResult(interp, zErrCode, " - ", (char *)sqlite3_errmsg(db), 0);
70269c5e3680Sdan return TCL_ERROR;
70279c5e3680Sdan }
70289c5e3680Sdan
70299c5e3680Sdan pRet = Tcl_NewObj();
70309c5e3680Sdan Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(rc==SQLITE_BUSY?1:0));
70319c5e3680Sdan Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nLog));
70329c5e3680Sdan Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCkpt));
70339c5e3680Sdan Tcl_SetObjResult(interp, pRet);
70349c5e3680Sdan
70359c5e3680Sdan return TCL_OK;
70369c5e3680Sdan }
70379c5e3680Sdan
70389c5e3680Sdan /*
70399af10620Sdan ** tclcmd: sqlite3_wal_autocheckpoint db VALUE
70409af10620Sdan */
test_wal_autocheckpoint(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])70417617e4a8Smistachkin static int SQLITE_TCLAPI test_wal_autocheckpoint(
70429af10620Sdan ClientData clientData, /* Unused */
70439af10620Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
70449af10620Sdan int objc, /* Number of arguments */
70459af10620Sdan Tcl_Obj *CONST objv[] /* Command arguments */
70469af10620Sdan ){
70479af10620Sdan sqlite3 *db;
70489af10620Sdan int rc;
70499af10620Sdan int iVal;
70509af10620Sdan
70519af10620Sdan
70529af10620Sdan if( objc!=3 ){
70539af10620Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB VALUE");
70549af10620Sdan return TCL_ERROR;
70559af10620Sdan }
70569af10620Sdan
70579af10620Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
70589af10620Sdan || Tcl_GetIntFromObj(0, objv[2], &iVal)
70599af10620Sdan ){
70609af10620Sdan return TCL_ERROR;
70619af10620Sdan }
70629af10620Sdan
70639af10620Sdan rc = sqlite3_wal_autocheckpoint(db, iVal);
70649af10620Sdan Tcl_ResetResult(interp);
70659af10620Sdan if( rc!=SQLITE_OK ){
70669af10620Sdan const char *zErrCode = sqlite3ErrName(rc);
70679af10620Sdan Tcl_SetObjResult(interp, Tcl_NewStringObj(zErrCode, -1));
70689af10620Sdan return TCL_ERROR;
70699af10620Sdan }
70709af10620Sdan
70719af10620Sdan return TCL_OK;
70729af10620Sdan }
70739af10620Sdan
70749af10620Sdan
70759af10620Sdan /*
7076eb8763d7Sdan ** tclcmd: test_sqlite3_log ?SCRIPT?
7077eb8763d7Sdan */
7078eb8763d7Sdan static struct LogCallback {
7079eb8763d7Sdan Tcl_Interp *pInterp;
7080eb8763d7Sdan Tcl_Obj *pObj;
7081eb8763d7Sdan } logcallback = {0, 0};
xLogcallback(void * unused,int err,char * zMsg)7082eb8763d7Sdan static void xLogcallback(void *unused, int err, char *zMsg){
7083eb8763d7Sdan Tcl_Obj *pNew = Tcl_DuplicateObj(logcallback.pObj);
7084eb8763d7Sdan Tcl_IncrRefCount(pNew);
7085eb8763d7Sdan Tcl_ListObjAppendElement(
7086e84d8d32Smistachkin 0, pNew, Tcl_NewStringObj(sqlite3ErrName(err), -1)
7087eb8763d7Sdan );
7088eb8763d7Sdan Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zMsg, -1));
7089eb8763d7Sdan Tcl_EvalObjEx(logcallback.pInterp, pNew, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
7090eb8763d7Sdan Tcl_DecrRefCount(pNew);
7091eb8763d7Sdan }
test_sqlite3_log(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])70927617e4a8Smistachkin static int SQLITE_TCLAPI test_sqlite3_log(
7093eb8763d7Sdan ClientData clientData,
7094eb8763d7Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
7095eb8763d7Sdan int objc, /* Number of arguments */
7096eb8763d7Sdan Tcl_Obj *CONST objv[] /* Command arguments */
7097eb8763d7Sdan ){
7098eb8763d7Sdan if( objc>2 ){
7099eb8763d7Sdan Tcl_WrongNumArgs(interp, 1, objv, "SCRIPT");
7100eb8763d7Sdan return TCL_ERROR;
7101eb8763d7Sdan }
7102eb8763d7Sdan if( logcallback.pObj ){
7103eb8763d7Sdan Tcl_DecrRefCount(logcallback.pObj);
7104eb8763d7Sdan logcallback.pObj = 0;
7105eb8763d7Sdan logcallback.pInterp = 0;
7106d797a9b5Sdrh sqlite3_config(SQLITE_CONFIG_LOG, (void*)0, (void*)0);
7107eb8763d7Sdan }
7108eb8763d7Sdan if( objc>1 ){
7109eb8763d7Sdan logcallback.pObj = objv[1];
7110eb8763d7Sdan Tcl_IncrRefCount(logcallback.pObj);
7111eb8763d7Sdan logcallback.pInterp = interp;
7112d797a9b5Sdrh sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, (void*)0);
7113eb8763d7Sdan }
7114eb8763d7Sdan return TCL_OK;
7115eb8763d7Sdan }
71169bc5449fSdrh
71179bc5449fSdrh /*
7118a2c8a95bSdrh ** tcl_objproc COMMANDNAME ARGS...
7119a2c8a95bSdrh **
7120a2c8a95bSdrh ** Run a TCL command using its objProc interface. Throw an error if
7121a2c8a95bSdrh ** the command has no objProc interface.
7122a2c8a95bSdrh */
runAsObjProc(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])71237617e4a8Smistachkin static int SQLITE_TCLAPI runAsObjProc(
7124a2c8a95bSdrh void * clientData,
7125a2c8a95bSdrh Tcl_Interp *interp,
7126a2c8a95bSdrh int objc,
7127a2c8a95bSdrh Tcl_Obj *CONST objv[]
7128a2c8a95bSdrh ){
7129a2c8a95bSdrh Tcl_CmdInfo cmdInfo;
7130a2c8a95bSdrh if( objc<2 ){
7131a2c8a95bSdrh Tcl_WrongNumArgs(interp, 1, objv, "COMMAND ...");
7132a2c8a95bSdrh return TCL_ERROR;
7133a2c8a95bSdrh }
7134a2c8a95bSdrh if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
7135a2c8a95bSdrh Tcl_AppendResult(interp, "command not found: ",
7136a2c8a95bSdrh Tcl_GetString(objv[1]), (char*)0);
7137a2c8a95bSdrh return TCL_ERROR;
7138a2c8a95bSdrh }
7139a2c8a95bSdrh if( cmdInfo.objProc==0 ){
7140a2c8a95bSdrh Tcl_AppendResult(interp, "command has no objProc: ",
7141a2c8a95bSdrh Tcl_GetString(objv[1]), (char*)0);
7142a2c8a95bSdrh return TCL_ERROR;
7143a2c8a95bSdrh }
7144a2c8a95bSdrh return cmdInfo.objProc(cmdInfo.objClientData, interp, objc-1, objv+1);
7145a2c8a95bSdrh }
7146a2c8a95bSdrh
714791da6b83Sdan #ifndef SQLITE_OMIT_EXPLAIN
714891da6b83Sdan /*
714991da6b83Sdan ** WARNING: The following function, printExplainQueryPlan() is an exact
715091da6b83Sdan ** copy of example code from eqp.in (eqp.html). If this code is modified,
715191da6b83Sdan ** then the documentation copy needs to be modified as well.
715291da6b83Sdan */
715391da6b83Sdan /*
715491da6b83Sdan ** Argument pStmt is a prepared SQL statement. This function compiles
715591da6b83Sdan ** an EXPLAIN QUERY PLAN command to report on the prepared statement,
715691da6b83Sdan ** and prints the report to stdout using printf().
715791da6b83Sdan */
printExplainQueryPlan(sqlite3_stmt * pStmt)715891da6b83Sdan int printExplainQueryPlan(sqlite3_stmt *pStmt){
715991da6b83Sdan const char *zSql; /* Input SQL */
716091da6b83Sdan char *zExplain; /* SQL with EXPLAIN QUERY PLAN prepended */
716191da6b83Sdan sqlite3_stmt *pExplain; /* Compiled EXPLAIN QUERY PLAN command */
716291da6b83Sdan int rc; /* Return code from sqlite3_prepare_v2() */
716391da6b83Sdan
716491da6b83Sdan zSql = sqlite3_sql(pStmt);
716591da6b83Sdan if( zSql==0 ) return SQLITE_ERROR;
716691da6b83Sdan
716791da6b83Sdan zExplain = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zSql);
716891da6b83Sdan if( zExplain==0 ) return SQLITE_NOMEM;
716991da6b83Sdan
717091da6b83Sdan rc = sqlite3_prepare_v2(sqlite3_db_handle(pStmt), zExplain, -1, &pExplain, 0);
717191da6b83Sdan sqlite3_free(zExplain);
717291da6b83Sdan if( rc!=SQLITE_OK ) return rc;
717391da6b83Sdan
717491da6b83Sdan while( SQLITE_ROW==sqlite3_step(pExplain) ){
717591da6b83Sdan int iSelectid = sqlite3_column_int(pExplain, 0);
717691da6b83Sdan int iOrder = sqlite3_column_int(pExplain, 1);
717791da6b83Sdan int iFrom = sqlite3_column_int(pExplain, 2);
717891da6b83Sdan const char *zDetail = (const char *)sqlite3_column_text(pExplain, 3);
717991da6b83Sdan
718091da6b83Sdan printf("%d %d %d %s\n", iSelectid, iOrder, iFrom, zDetail);
718191da6b83Sdan }
718291da6b83Sdan
718391da6b83Sdan return sqlite3_finalize(pExplain);
718491da6b83Sdan }
718591da6b83Sdan
test_print_eqp(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])71867617e4a8Smistachkin static int SQLITE_TCLAPI test_print_eqp(
718791da6b83Sdan void * clientData,
718891da6b83Sdan Tcl_Interp *interp,
718991da6b83Sdan int objc,
719091da6b83Sdan Tcl_Obj *CONST objv[]
719191da6b83Sdan ){
719291da6b83Sdan int rc;
719391da6b83Sdan sqlite3_stmt *pStmt;
719491da6b83Sdan
719591da6b83Sdan if( objc!=2 ){
719691da6b83Sdan Tcl_WrongNumArgs(interp, 1, objv, "STMT");
719791da6b83Sdan return TCL_ERROR;
719891da6b83Sdan }
719991da6b83Sdan if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
720091da6b83Sdan rc = printExplainQueryPlan(pStmt);
72017c5d8fb7Sshaneh /* This is needed on Windows so that a test case using this
72027c5d8fb7Sshaneh ** function can open a read pipe and get the output of
72037c5d8fb7Sshaneh ** printExplainQueryPlan() immediately.
72047c5d8fb7Sshaneh */
72057c5d8fb7Sshaneh fflush(stdout);
720691da6b83Sdan Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
720791da6b83Sdan return TCL_OK;
720891da6b83Sdan }
720991da6b83Sdan #endif /* SQLITE_OMIT_EXPLAIN */
7210a2c8a95bSdrh
721185548facSdrh #include <time.h>
721285548facSdrh /*
721385548facSdrh ** This is an alternative localtime_r() implementation used for testing
721485548facSdrh ** the 'localtime' and 'utc' modifiers of date-time functions. Because
721585548facSdrh ** the OS-supplied localtime_r() is locale-dependent, this alternative is
721685548facSdrh ** provided as a stable test platform.
721785548facSdrh **
721885548facSdrh ** Operation:
721985548facSdrh **
722085548facSdrh ** (1) Localtime is 30 minutes earlier than (west of) UTC on
722185548facSdrh ** even days (counting from 1970-01-01)
722285548facSdrh **
722385548facSdrh ** (2) Localtime is 30 minutes later than (east of) UTC on odd days.
722485548facSdrh **
722585548facSdrh ** (3) The function fails for the specific date/time value
722685548facSdrh ** of 2000-05-29 14:16:00 in order to test the ability of
722785548facSdrh ** SQLite to deal with localtime_r() failures.
722885548facSdrh */
testLocaltime(const void * aliasT,void * aliasTM)722985548facSdrh static int testLocaltime(const void *aliasT, void *aliasTM){
723085548facSdrh const time_t t = *(const time_t*)aliasT;
723185548facSdrh struct tm *pTm = (struct tm *)aliasTM;
723285548facSdrh time_t altT;
723385548facSdrh sqlite3_int64 iJD;
723485548facSdrh int Z, A, B, C, D, E, X1, S;
723585548facSdrh
723685548facSdrh if( (t/86400) & 1 ){
723785548facSdrh altT = t + 1800; /* 30 minutes later on odd days */
723885548facSdrh }else{
723985548facSdrh altT = t - 1800; /* 30 minutes earlier on even days */
724085548facSdrh }
724185548facSdrh iJD = (sqlite3_int64)(altT + 210866760000);
724285548facSdrh Z = (int)((iJD + 43200)/86400);
724385548facSdrh A = (int)((Z - 1867216.25)/36524.25);
724485548facSdrh A = Z + 1 + A - (A/4);
724585548facSdrh B = A + 1524;
724685548facSdrh C = (int)((B - 122.1)/365.25);
724785548facSdrh D = (36525*(C&32767))/100;
724885548facSdrh E = (int)((B-D)/30.6001);
724985548facSdrh X1 = (int)(30.6001*E);
725085548facSdrh pTm->tm_mday = B - D - X1;
725185548facSdrh pTm->tm_mon = E<14 ? E-2 : E-14;
725285548facSdrh pTm->tm_year = (pTm->tm_mon>1 ? C - 4716 : C - 4715) - 1900;
725385548facSdrh S = (int)((iJD + 43200)%86400);
725485548facSdrh pTm->tm_hour = S/3600;
725585548facSdrh pTm->tm_min = (S/60)%60;
725685548facSdrh pTm->tm_sec = S % 60;
725785548facSdrh return t==959609760; /* Special case: 2000-05-29 14:16:00 fails */
725885548facSdrh }
725985548facSdrh
7260a2c8a95bSdrh /*
7261c17d696cSdan ** sqlite3_test_control VERB ARGS...
7262c17d696cSdan */
test_test_control(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])72637617e4a8Smistachkin static int SQLITE_TCLAPI test_test_control(
7264c17d696cSdan void * clientData,
7265c17d696cSdan Tcl_Interp *interp,
7266c17d696cSdan int objc,
7267c17d696cSdan Tcl_Obj *CONST objv[]
7268c17d696cSdan ){
7269c17d696cSdan struct Verb {
7270c17d696cSdan const char *zName;
7271c17d696cSdan int i;
7272c17d696cSdan } aVerb[] = {
7273c17d696cSdan { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
72748930c2abSdan { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP },
72751ffede8cSdrh { "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER },
7276eea8eb6dSdrh { "SQLITE_TESTCTRL_INTERNAL_FUNCTIONS", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS},
72779b6a2833Sdan { 0, 0 }
7278c17d696cSdan };
7279c17d696cSdan int iVerb;
7280c17d696cSdan int iFlag;
7281c17d696cSdan int rc;
7282c17d696cSdan
7283c17d696cSdan if( objc<2 ){
7284c17d696cSdan Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS...");
7285c17d696cSdan return TCL_ERROR;
7286c17d696cSdan }
7287c17d696cSdan
7288c17d696cSdan rc = Tcl_GetIndexFromObjStruct(
7289c17d696cSdan interp, objv[1], aVerb, sizeof(aVerb[0]), "VERB", 0, &iVerb
7290c17d696cSdan );
7291c17d696cSdan if( rc!=TCL_OK ) return rc;
7292c17d696cSdan
7293c17d696cSdan iFlag = aVerb[iVerb].i;
7294c17d696cSdan switch( iFlag ){
7295171c50ecSdrh case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: {
7296171c50ecSdrh sqlite3 *db = 0;
7297171c50ecSdrh if( objc!=3 ){
7298171c50ecSdrh Tcl_WrongNumArgs(interp, 2, objv, "DB");
7299171c50ecSdrh return TCL_ERROR;
7300171c50ecSdrh }
7301171c50ecSdrh if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
7302171c50ecSdrh sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, db);
7303171c50ecSdrh break;
7304171c50ecSdrh }
7305c17d696cSdan case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
7306c17d696cSdan int val;
7307c17d696cSdan if( objc!=3 ){
730885548facSdrh Tcl_WrongNumArgs(interp, 2, objv, "0|1|2");
7309c17d696cSdan return TCL_ERROR;
7310c17d696cSdan }
731185548facSdrh if( Tcl_GetIntFromObj(interp, objv[2], &val) ) return TCL_ERROR;
731285548facSdrh sqlite3_test_control(iFlag, val, testLocaltime);
7313c17d696cSdan break;
7314c17d696cSdan }
73158930c2abSdan
73168930c2abSdan case SQLITE_TESTCTRL_SORTER_MMAP: {
73178930c2abSdan int val;
73188930c2abSdan sqlite3 *db;
73198930c2abSdan if( objc!=4 ){
73208930c2abSdan Tcl_WrongNumArgs(interp, 2, objv, "DB LIMIT");
73218930c2abSdan return TCL_ERROR;
73228930c2abSdan }
73238930c2abSdan if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
73248930c2abSdan if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
73258930c2abSdan sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, val);
73268930c2abSdan break;
73278930c2abSdan }
7328917682a4Sdrh
73291ffede8cSdrh case SQLITE_TESTCTRL_IMPOSTER: {
73301ffede8cSdrh int onOff, tnum;
73311ffede8cSdrh const char *zDbName;
7332917682a4Sdrh sqlite3 *db;
7333917682a4Sdrh if( objc!=6 ){
73341ffede8cSdrh Tcl_WrongNumArgs(interp, 2, objv, "DB dbName onOff tnum");
7335917682a4Sdrh return TCL_ERROR;
7336917682a4Sdrh }
7337917682a4Sdrh if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
73381ffede8cSdrh zDbName = Tcl_GetString(objv[3]);
73391ffede8cSdrh if( Tcl_GetIntFromObj(interp, objv[4], &onOff) ) return TCL_ERROR;
73401ffede8cSdrh if( Tcl_GetIntFromObj(interp, objv[5], &tnum) ) return TCL_ERROR;
73411ffede8cSdrh sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zDbName, onOff, tnum);
7342917682a4Sdrh break;
7343917682a4Sdrh }
7344c17d696cSdan }
7345c17d696cSdan
7346c17d696cSdan Tcl_ResetResult(interp);
7347c17d696cSdan return TCL_OK;
7348c17d696cSdan }
7349c17d696cSdan
7350daf9a5a4Smistachkin #if SQLITE_OS_UNIX
7351a72014faSdan #include <sys/time.h>
7352a72014faSdan #include <sys/resource.h>
7353a72014faSdan
test_getrusage(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])73547617e4a8Smistachkin static int SQLITE_TCLAPI test_getrusage(
7355a72014faSdan void * clientData,
7356a72014faSdan Tcl_Interp *interp,
7357a72014faSdan int objc,
7358a72014faSdan Tcl_Obj *CONST objv[]
7359a72014faSdan ){
7360a72014faSdan char buf[1024];
7361a72014faSdan struct rusage r;
7362a72014faSdan memset(&r, 0, sizeof(r));
7363a72014faSdan getrusage(RUSAGE_SELF, &r);
7364a72014faSdan
736565545b59Sdrh sqlite3_snprintf(sizeof(buf), buf,
736665545b59Sdrh "ru_utime=%d.%06d ru_stime=%d.%06d ru_minflt=%d ru_majflt=%d",
73675d8a1372Sdan (int)r.ru_utime.tv_sec, (int)r.ru_utime.tv_usec,
73685d8a1372Sdan (int)r.ru_stime.tv_sec, (int)r.ru_stime.tv_usec,
73695d8a1372Sdan (int)r.ru_minflt, (int)r.ru_majflt
7370a72014faSdan );
7371a72014faSdan Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
7372a72014faSdan return TCL_OK;
7373a72014faSdan }
7374daf9a5a4Smistachkin #endif
7375a72014faSdan
737680084ca8Sdrh #if SQLITE_OS_WIN
737780084ca8Sdrh /*
737880084ca8Sdrh ** Information passed from the main thread into the windows file locker
737980084ca8Sdrh ** background thread.
738080084ca8Sdrh */
738180084ca8Sdrh struct win32FileLocker {
7382176f1b47Smistachkin char *evName; /* Name of event to signal thread startup */
738380084ca8Sdrh HANDLE h; /* Handle of the file to be locked */
738480084ca8Sdrh int delay1; /* Delay before locking */
738580084ca8Sdrh int delay2; /* Delay before unlocking */
738680084ca8Sdrh int ok; /* Finished ok */
738780084ca8Sdrh int err; /* True if an error occurs */
738880084ca8Sdrh };
738980084ca8Sdrh #endif
739080084ca8Sdrh
739180084ca8Sdrh
739280084ca8Sdrh #if SQLITE_OS_WIN
73937da5fcb0Sdrh #include <process.h>
739480084ca8Sdrh /*
739580084ca8Sdrh ** The background thread that does file locking.
739680084ca8Sdrh */
win32_file_locker(void * pAppData)739769def7ffSmistachkin static void SQLITE_CDECL win32_file_locker(void *pAppData){
739880084ca8Sdrh struct win32FileLocker *p = (struct win32FileLocker*)pAppData;
7399176f1b47Smistachkin if( p->evName ){
7400176f1b47Smistachkin HANDLE ev = OpenEvent(EVENT_MODIFY_STATE, FALSE, p->evName);
7401176f1b47Smistachkin if ( ev ){
7402176f1b47Smistachkin SetEvent(ev);
7403176f1b47Smistachkin CloseHandle(ev);
7404176f1b47Smistachkin }
7405176f1b47Smistachkin }
740680084ca8Sdrh if( p->delay1 ) Sleep(p->delay1);
740780084ca8Sdrh if( LockFile(p->h, 0, 0, 100000000, 0) ){
740880084ca8Sdrh Sleep(p->delay2);
740980084ca8Sdrh UnlockFile(p->h, 0, 0, 100000000, 0);
741080084ca8Sdrh p->ok = 1;
741180084ca8Sdrh }else{
741280084ca8Sdrh p->err = 1;
741380084ca8Sdrh }
741480084ca8Sdrh CloseHandle(p->h);
741580084ca8Sdrh p->h = 0;
741680084ca8Sdrh p->delay1 = 0;
741780084ca8Sdrh p->delay2 = 0;
741880084ca8Sdrh }
741980084ca8Sdrh #endif
742080084ca8Sdrh
742180084ca8Sdrh #if SQLITE_OS_WIN
742280084ca8Sdrh /*
742380084ca8Sdrh ** lock_win32_file FILENAME DELAY1 DELAY2
742480084ca8Sdrh **
742580084ca8Sdrh ** Get an exclusive manditory lock on file for DELAY2 milliseconds.
742680084ca8Sdrh ** Wait DELAY1 milliseconds before acquiring the lock.
742780084ca8Sdrh */
win32_file_lock(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])74287617e4a8Smistachkin static int SQLITE_TCLAPI win32_file_lock(
742980084ca8Sdrh void * clientData,
743080084ca8Sdrh Tcl_Interp *interp,
743180084ca8Sdrh int objc,
743280084ca8Sdrh Tcl_Obj *CONST objv[]
743380084ca8Sdrh ){
7434176f1b47Smistachkin static struct win32FileLocker x = { "win32_file_lock", 0, 0, 0, 0, 0 };
743580084ca8Sdrh const char *zFilename;
7436176f1b47Smistachkin char zBuf[200];
743780084ca8Sdrh int retry = 0;
7438176f1b47Smistachkin HANDLE ev;
7439176f1b47Smistachkin DWORD wResult;
744080084ca8Sdrh
744180084ca8Sdrh if( objc!=4 && objc!=1 ){
744280084ca8Sdrh Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2");
744380084ca8Sdrh return TCL_ERROR;
744480084ca8Sdrh }
744580084ca8Sdrh if( objc==1 ){
744680084ca8Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d",
744780084ca8Sdrh x.ok, x.err, x.delay1, x.delay2, x.h);
744880084ca8Sdrh Tcl_AppendResult(interp, zBuf, (char*)0);
744980084ca8Sdrh return TCL_OK;
745080084ca8Sdrh }
7451d0cdf012Sdrh while( x.h && retry<30 ){
745280084ca8Sdrh retry++;
745380084ca8Sdrh Sleep(100);
745480084ca8Sdrh }
745580084ca8Sdrh if( x.h ){
745680084ca8Sdrh Tcl_AppendResult(interp, "busy", (char*)0);
745780084ca8Sdrh return TCL_ERROR;
745880084ca8Sdrh }
745980084ca8Sdrh if( Tcl_GetIntFromObj(interp, objv[2], &x.delay1) ) return TCL_ERROR;
746080084ca8Sdrh if( Tcl_GetIntFromObj(interp, objv[3], &x.delay2) ) return TCL_ERROR;
746180084ca8Sdrh zFilename = Tcl_GetString(objv[1]);
746280084ca8Sdrh x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE,
746380084ca8Sdrh FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
746480084ca8Sdrh FILE_ATTRIBUTE_NORMAL, 0);
746580084ca8Sdrh if( !x.h ){
746680084ca8Sdrh Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0);
746780084ca8Sdrh return TCL_ERROR;
746880084ca8Sdrh }
7469176f1b47Smistachkin ev = CreateEvent(NULL, TRUE, FALSE, x.evName);
7470176f1b47Smistachkin if ( !ev ){
7471176f1b47Smistachkin Tcl_AppendResult(interp, "cannot create event: ", x.evName, (char*)0);
7472176f1b47Smistachkin return TCL_ERROR;
7473176f1b47Smistachkin }
747480084ca8Sdrh _beginthread(win32_file_locker, 0, (void*)&x);
747580084ca8Sdrh Sleep(0);
7476176f1b47Smistachkin if ( (wResult = WaitForSingleObject(ev, 10000))!=WAIT_OBJECT_0 ){
7477176f1b47Smistachkin sqlite3_snprintf(sizeof(zBuf), zBuf, "0x%x", wResult);
7478176f1b47Smistachkin Tcl_AppendResult(interp, "wait failed: ", zBuf, (char*)0);
7479176f1b47Smistachkin CloseHandle(ev);
7480176f1b47Smistachkin return TCL_ERROR;
7481176f1b47Smistachkin }
7482176f1b47Smistachkin CloseHandle(ev);
748380084ca8Sdrh return TCL_OK;
748480084ca8Sdrh }
74853741827eSmistachkin
74863741827eSmistachkin /*
74873741827eSmistachkin ** exists_win32_path PATH
74883741827eSmistachkin **
74893741827eSmistachkin ** Returns non-zero if the specified path exists, whose fully qualified name
74903259fe79Smistachkin ** may exceed 260 characters if it is prefixed with "\\?\".
74913741827eSmistachkin */
win32_exists_path(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])74927617e4a8Smistachkin static int SQLITE_TCLAPI win32_exists_path(
74933741827eSmistachkin void *clientData,
74943741827eSmistachkin Tcl_Interp *interp,
74953741827eSmistachkin int objc,
74963741827eSmistachkin Tcl_Obj *CONST objv[]
74973741827eSmistachkin ){
74983741827eSmistachkin if( objc!=2 ){
74993741827eSmistachkin Tcl_WrongNumArgs(interp, 1, objv, "PATH");
75003741827eSmistachkin return TCL_ERROR;
75013741827eSmistachkin }
75023741827eSmistachkin Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
75033741827eSmistachkin GetFileAttributesW( Tcl_GetUnicode(objv[1]))!=INVALID_FILE_ATTRIBUTES ));
75043741827eSmistachkin return TCL_OK;
75053741827eSmistachkin }
75063741827eSmistachkin
75073741827eSmistachkin /*
75083741827eSmistachkin ** find_win32_file PATTERN
75093741827eSmistachkin **
75103741827eSmistachkin ** Returns a list of entries in a directory that match the specified pattern,
75113741827eSmistachkin ** whose fully qualified name may exceed 248 characters if it is prefixed with
75123741827eSmistachkin ** "\\?\".
75133741827eSmistachkin */
win32_find_file(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])75147617e4a8Smistachkin static int SQLITE_TCLAPI win32_find_file(
75153741827eSmistachkin void *clientData,
75163741827eSmistachkin Tcl_Interp *interp,
75173741827eSmistachkin int objc,
75183741827eSmistachkin Tcl_Obj *CONST objv[]
75193741827eSmistachkin ){
75203741827eSmistachkin HANDLE hFindFile = INVALID_HANDLE_VALUE;
75213741827eSmistachkin WIN32_FIND_DATAW findData;
75223741827eSmistachkin Tcl_Obj *listObj;
75233741827eSmistachkin DWORD lastErrno;
75243741827eSmistachkin if( objc!=2 ){
75253741827eSmistachkin Tcl_WrongNumArgs(interp, 1, objv, "PATTERN");
75263741827eSmistachkin return TCL_ERROR;
75273741827eSmistachkin }
75283741827eSmistachkin hFindFile = FindFirstFileW(Tcl_GetUnicode(objv[1]), &findData);
75293741827eSmistachkin if( hFindFile==INVALID_HANDLE_VALUE ){
75303741827eSmistachkin Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
75313741827eSmistachkin return TCL_ERROR;
75323741827eSmistachkin }
75333741827eSmistachkin listObj = Tcl_NewObj();
75343741827eSmistachkin Tcl_IncrRefCount(listObj);
75353741827eSmistachkin do {
75363741827eSmistachkin Tcl_ListObjAppendElement(interp, listObj, Tcl_NewUnicodeObj(
75373741827eSmistachkin findData.cFileName, -1));
75383741827eSmistachkin Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(
75393741827eSmistachkin findData.dwFileAttributes));
75403741827eSmistachkin } while( FindNextFileW(hFindFile, &findData) );
75413741827eSmistachkin lastErrno = GetLastError();
75423741827eSmistachkin if( lastErrno!=NO_ERROR && lastErrno!=ERROR_NO_MORE_FILES ){
75433741827eSmistachkin FindClose(hFindFile);
75443741827eSmistachkin Tcl_DecrRefCount(listObj);
75453741827eSmistachkin Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
75463741827eSmistachkin return TCL_ERROR;
75473741827eSmistachkin }
75483741827eSmistachkin FindClose(hFindFile);
75493741827eSmistachkin Tcl_SetObjResult(interp, listObj);
75503741827eSmistachkin return TCL_OK;
75513741827eSmistachkin }
75523741827eSmistachkin
75533741827eSmistachkin /*
75543741827eSmistachkin ** delete_win32_file FILENAME
75553741827eSmistachkin **
75563259fe79Smistachkin ** Deletes the specified file, whose fully qualified name may exceed 260
75573741827eSmistachkin ** characters if it is prefixed with "\\?\".
75583741827eSmistachkin */
win32_delete_file(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])75597617e4a8Smistachkin static int SQLITE_TCLAPI win32_delete_file(
75603741827eSmistachkin void *clientData,
75613741827eSmistachkin Tcl_Interp *interp,
75623741827eSmistachkin int objc,
75633741827eSmistachkin Tcl_Obj *CONST objv[]
75643741827eSmistachkin ){
75653741827eSmistachkin if( objc!=2 ){
75663741827eSmistachkin Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
75673741827eSmistachkin return TCL_ERROR;
75683741827eSmistachkin }
75693741827eSmistachkin if( !DeleteFileW(Tcl_GetUnicode(objv[1])) ){
75703741827eSmistachkin Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
75713741827eSmistachkin return TCL_ERROR;
75723741827eSmistachkin }
75733741827eSmistachkin Tcl_ResetResult(interp);
75743741827eSmistachkin return TCL_OK;
75753741827eSmistachkin }
75763741827eSmistachkin
75773741827eSmistachkin /*
75783741827eSmistachkin ** make_win32_dir DIRECTORY
75793741827eSmistachkin **
75803741827eSmistachkin ** Creates the specified directory, whose fully qualified name may exceed 248
75813741827eSmistachkin ** characters if it is prefixed with "\\?\".
75823741827eSmistachkin */
win32_mkdir(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])75837617e4a8Smistachkin static int SQLITE_TCLAPI win32_mkdir(
75843741827eSmistachkin void *clientData,
75853741827eSmistachkin Tcl_Interp *interp,
75863741827eSmistachkin int objc,
75873741827eSmistachkin Tcl_Obj *CONST objv[]
75883741827eSmistachkin ){
75893741827eSmistachkin if( objc!=2 ){
75903741827eSmistachkin Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY");
75913741827eSmistachkin return TCL_ERROR;
75923741827eSmistachkin }
75933741827eSmistachkin if( !CreateDirectoryW(Tcl_GetUnicode(objv[1]), NULL) ){
75943741827eSmistachkin Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
75953741827eSmistachkin return TCL_ERROR;
75963741827eSmistachkin }
75973741827eSmistachkin Tcl_ResetResult(interp);
75983741827eSmistachkin return TCL_OK;
75993741827eSmistachkin }
76003741827eSmistachkin
76013741827eSmistachkin /*
76023741827eSmistachkin ** remove_win32_dir DIRECTORY
76033741827eSmistachkin **
76043741827eSmistachkin ** Removes the specified directory, whose fully qualified name may exceed 248
76053741827eSmistachkin ** characters if it is prefixed with "\\?\".
76063741827eSmistachkin */
win32_rmdir(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])76077617e4a8Smistachkin static int SQLITE_TCLAPI win32_rmdir(
76083741827eSmistachkin void *clientData,
76093741827eSmistachkin Tcl_Interp *interp,
76103741827eSmistachkin int objc,
76113741827eSmistachkin Tcl_Obj *CONST objv[]
76123741827eSmistachkin ){
76133741827eSmistachkin if( objc!=2 ){
76143741827eSmistachkin Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY");
76153741827eSmistachkin return TCL_ERROR;
76163741827eSmistachkin }
76173741827eSmistachkin if( !RemoveDirectoryW(Tcl_GetUnicode(objv[1])) ){
76183741827eSmistachkin Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
76193741827eSmistachkin return TCL_ERROR;
76203741827eSmistachkin }
76213741827eSmistachkin Tcl_ResetResult(interp);
76223741827eSmistachkin return TCL_OK;
76233741827eSmistachkin }
762480084ca8Sdrh #endif
7625c17d696cSdan
7626d0cdf012Sdrh
7627c17d696cSdan /*
7628f58ee7f1Sdrh ** optimization_control DB OPT BOOLEAN
7629f58ee7f1Sdrh **
7630f58ee7f1Sdrh ** Enable or disable query optimizations using the sqlite3_test_control()
7631f58ee7f1Sdrh ** interface. Disable if BOOLEAN is false and enable if BOOLEAN is true.
7632*dc5e8c63Sdrh ** OPT is the name of the optimization to be disabled. OPT can also be a
7633*dc5e8c63Sdrh ** list or optimizations names, in which case all optimizations named are
7634*dc5e8c63Sdrh ** enabled or disabled.
7635*dc5e8c63Sdrh **
7636*dc5e8c63Sdrh ** Each invocation of this control overrides all prior invocations. The
7637*dc5e8c63Sdrh ** changes are not cumulative.
7638f58ee7f1Sdrh */
optimization_control(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])76397617e4a8Smistachkin static int SQLITE_TCLAPI optimization_control(
7640f58ee7f1Sdrh void * clientData,
7641f58ee7f1Sdrh Tcl_Interp *interp,
7642f58ee7f1Sdrh int objc,
7643f58ee7f1Sdrh Tcl_Obj *CONST objv[]
7644f58ee7f1Sdrh ){
7645f58ee7f1Sdrh int i;
7646f58ee7f1Sdrh sqlite3 *db;
7647f58ee7f1Sdrh const char *zOpt;
7648f58ee7f1Sdrh int onoff;
7649fc30b042Sdrh int mask = 0;
7650b6d91679Sdrh int cnt = 0;
7651f58ee7f1Sdrh static const struct {
7652f58ee7f1Sdrh const char *zOptName;
7653f58ee7f1Sdrh int mask;
7654f58ee7f1Sdrh } aOpt[] = {
76557e5418e4Sdrh { "all", SQLITE_AllOpts },
76569d5a579cSdrh { "none", 0 },
7657f58ee7f1Sdrh { "query-flattener", SQLITE_QueryFlattener },
7658f58ee7f1Sdrh { "groupby-order", SQLITE_GroupByOrder },
7659f58ee7f1Sdrh { "factor-constants", SQLITE_FactorOutConst },
7660f4af1089Sdrh { "distinct-opt", SQLITE_DistinctOpt },
7661de9a7b8aSdrh { "cover-idx-scan", SQLITE_CoverIdxScan },
76627e5418e4Sdrh { "order-by-idx-join", SQLITE_OrderByIdxJoin },
76639d5a579cSdrh { "transitive", SQLITE_Transitive },
76649d5a579cSdrh { "omit-noop-join", SQLITE_OmitNoopJoin },
76655eae1d1bSdrh { "stat4", SQLITE_Stat4 },
7666e8825519Sdan { "skip-scan", SQLITE_SkipScan },
7667fa508349Sdan { "push-down", SQLITE_PushDown },
766838cebe07Sdrh { "balanced-merge", SQLITE_BalancedMerge },
76699b6a2833Sdan { "propagate-const", SQLITE_PropagateConst },
7670f58ee7f1Sdrh };
7671f58ee7f1Sdrh
7672f58ee7f1Sdrh if( objc!=4 ){
7673f58ee7f1Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN");
7674f58ee7f1Sdrh return TCL_ERROR;
7675f58ee7f1Sdrh }
7676f58ee7f1Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
7677f58ee7f1Sdrh if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR;
7678f58ee7f1Sdrh zOpt = Tcl_GetString(objv[2]);
7679f58ee7f1Sdrh for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
7680b6d91679Sdrh if( strstr(zOpt, aOpt[i].zOptName)!=0 ){
7681b6d91679Sdrh mask |= aOpt[i].mask;
7682b6d91679Sdrh cnt++;
7683f58ee7f1Sdrh }
7684f58ee7f1Sdrh }
7685f58ee7f1Sdrh if( onoff ) mask = ~mask;
7686b6d91679Sdrh if( cnt==0 ){
7687f58ee7f1Sdrh Tcl_AppendResult(interp, "unknown optimization - should be one of:",
7688f58ee7f1Sdrh (char*)0);
7689f58ee7f1Sdrh for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
76909d5a579cSdrh Tcl_AppendResult(interp, " ", aOpt[i].zOptName, (char*)0);
7691f58ee7f1Sdrh }
7692f58ee7f1Sdrh return TCL_ERROR;
7693f58ee7f1Sdrh }
7694f58ee7f1Sdrh sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask);
7695*dc5e8c63Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(mask));
7696f58ee7f1Sdrh return TCL_OK;
7697f58ee7f1Sdrh }
7698f58ee7f1Sdrh
7699248f2be9Sdrh /*
7700ea41dc44Sdrh ** load_static_extension DB NAME ...
7701248f2be9Sdrh **
7702ea41dc44Sdrh ** Load one or more statically linked extensions.
7703248f2be9Sdrh */
tclLoadStaticExtensionCmd(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])77047617e4a8Smistachkin static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
7705248f2be9Sdrh void * clientData,
7706248f2be9Sdrh Tcl_Interp *interp,
7707248f2be9Sdrh int objc,
7708248f2be9Sdrh Tcl_Obj *CONST objv[]
7709248f2be9Sdrh ){
77108416fc7fSdrh extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*);
77111b22ad8aSlarrybr extern int sqlite3_appendvfs_init(sqlite3*,char**,const sqlite3_api_routines*);
77122e3f87aeSdrh extern int sqlite3_carray_init(sqlite3*,char**,const sqlite3_api_routines*);
77138416fc7fSdrh extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
771435db31b2Sdrh extern int sqlite3_csv_init(sqlite3*,char**,const sqlite3_api_routines*);
77151728bcb0Sdrh extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*);
77169b84f035Sdrh extern int sqlite3_explain_init(sqlite3*,char**,const sqlite3_api_routines*);
771751ed2983Sdrh extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
7718beb9def0Sdrh extern int sqlite3_decimal_init(sqlite3*,char**,const sqlite3_api_routines*);
7719e50db1c5Sdrh extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
77208416fc7fSdrh extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
7721ea41dc44Sdrh extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*);
7722def3367eSdrh extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
7723871b1349Sdan #ifndef SQLITE_OMIT_VIRTUALTABLE
77249c039d9fSdan extern int sqlite3_prefixes_init(sqlite3*,char**,const sqlite3_api_routines*);
7725871b1349Sdan #endif
772682801a5bSdrh extern int sqlite3_qpvtab_init(sqlite3*,char**,const sqlite3_api_routines*);
7727248f2be9Sdrh extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*);
77286bada272Sdrh extern int sqlite3_remember_init(sqlite3*,char**,const sqlite3_api_routines*);
7729398f872dSdrh extern int sqlite3_series_init(sqlite3*,char**,const sqlite3_api_routines*);
7730b7045ab2Sdrh extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*);
77315f8cdac6Sdrh extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*);
773224b6422dSdrh extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*);
7733d8ecefa5Sdan extern int sqlite3_unionvtab_init(sqlite3*,char**,const sqlite3_api_routines*);
773491f7211cSmistachkin #ifdef SQLITE_HAVE_ZLIB
7735373dc3bbSdan extern int sqlite3_zipfile_init(sqlite3*,char**,const sqlite3_api_routines*);
773691f7211cSmistachkin #endif
7737248f2be9Sdrh static const struct {
7738248f2be9Sdrh const char *zExtName;
7739248f2be9Sdrh int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*);
7740248f2be9Sdrh } aExtension[] = {
77418416fc7fSdrh { "amatch", sqlite3_amatch_init },
77421b22ad8aSlarrybr { "appendvfs", sqlite3_appendvfs_init },
77432e3f87aeSdrh { "carray", sqlite3_carray_init },
77448416fc7fSdrh { "closure", sqlite3_closure_init },
774535db31b2Sdrh { "csv", sqlite3_csv_init },
7746beb9def0Sdrh { "decimal", sqlite3_decimal_init },
77471728bcb0Sdrh { "eval", sqlite3_eval_init },
77489b84f035Sdrh { "explain", sqlite3_explain_init },
774951ed2983Sdrh { "fileio", sqlite3_fileio_init },
7750e50db1c5Sdrh { "fuzzer", sqlite3_fuzzer_init },
77518416fc7fSdrh { "ieee754", sqlite3_ieee_init },
7752ea41dc44Sdrh { "nextchar", sqlite3_nextchar_init },
7753def3367eSdrh { "percentile", sqlite3_percentile_init },
7754871b1349Sdan #ifndef SQLITE_OMIT_VIRTUALTABLE
77559c039d9fSdan { "prefixes", sqlite3_prefixes_init },
7756871b1349Sdan #endif
775782801a5bSdrh { "qpvtab", sqlite3_qpvtab_init },
7758248f2be9Sdrh { "regexp", sqlite3_regexp_init },
77596bada272Sdrh { "remember", sqlite3_remember_init },
7760398f872dSdrh { "series", sqlite3_series_init },
7761b7045ab2Sdrh { "spellfix", sqlite3_spellfix_init },
77625f8cdac6Sdrh { "totype", sqlite3_totype_init },
7763d8ecefa5Sdan { "unionvtab", sqlite3_unionvtab_init },
776424b6422dSdrh { "wholenumber", sqlite3_wholenumber_init },
776591f7211cSmistachkin #ifdef SQLITE_HAVE_ZLIB
7766373dc3bbSdan { "zipfile", sqlite3_zipfile_init },
776791f7211cSmistachkin #endif
7768248f2be9Sdrh };
7769248f2be9Sdrh sqlite3 *db;
7770248f2be9Sdrh const char *zName;
7771ea41dc44Sdrh int i, j, rc;
7772248f2be9Sdrh char *zErrMsg = 0;
7773ea41dc44Sdrh if( objc<3 ){
7774ea41dc44Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DB NAME ...");
7775248f2be9Sdrh return TCL_ERROR;
7776248f2be9Sdrh }
7777248f2be9Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
7778ea41dc44Sdrh for(j=2; j<objc; j++){
7779ea41dc44Sdrh zName = Tcl_GetString(objv[j]);
7780248f2be9Sdrh for(i=0; i<ArraySize(aExtension); i++){
7781248f2be9Sdrh if( strcmp(zName, aExtension[i].zExtName)==0 ) break;
7782248f2be9Sdrh }
7783248f2be9Sdrh if( i>=ArraySize(aExtension) ){
7784248f2be9Sdrh Tcl_AppendResult(interp, "no such extension: ", zName, (char*)0);
7785248f2be9Sdrh return TCL_ERROR;
7786248f2be9Sdrh }
7787c306e08aSdrh if( aExtension[i].pInit ){
7788248f2be9Sdrh rc = aExtension[i].pInit(db, &zErrMsg, 0);
7789c306e08aSdrh }else{
7790c306e08aSdrh rc = SQLITE_OK;
7791c306e08aSdrh }
77921b22ad8aSlarrybr if( (rc!=SQLITE_OK && rc!=SQLITE_OK_LOAD_PERMANENTLY) || zErrMsg ){
7793248f2be9Sdrh Tcl_AppendResult(interp, "initialization of ", zName, " failed: ", zErrMsg,
7794248f2be9Sdrh (char*)0);
7795248f2be9Sdrh sqlite3_free(zErrMsg);
7796248f2be9Sdrh return TCL_ERROR;
7797248f2be9Sdrh }
7798ea41dc44Sdrh }
7799248f2be9Sdrh return TCL_OK;
7800248f2be9Sdrh }
7801248f2be9Sdrh
78020d51def2Sdan /*
78030d51def2Sdan ** sorter_test_fakeheap BOOL
78040d51def2Sdan **
78050d51def2Sdan */
sorter_test_fakeheap(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])78067617e4a8Smistachkin static int SQLITE_TCLAPI sorter_test_fakeheap(
78070d51def2Sdan void * clientData,
78080d51def2Sdan Tcl_Interp *interp,
78090d51def2Sdan int objc,
78100d51def2Sdan Tcl_Obj *CONST objv[]
78110d51def2Sdan ){
78120d51def2Sdan int bArg;
78130d51def2Sdan if( objc!=2 ){
78140d51def2Sdan Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
78150d51def2Sdan return TCL_ERROR;
78160d51def2Sdan }
78170d51def2Sdan
78180d51def2Sdan if( Tcl_GetBooleanFromObj(interp, objv[1], &bArg) ){
78190d51def2Sdan return TCL_ERROR;
78200d51def2Sdan }
78210d51def2Sdan
78220d51def2Sdan if( bArg ){
78230d51def2Sdan if( sqlite3GlobalConfig.pHeap==0 ){
78240d51def2Sdan sqlite3GlobalConfig.pHeap = SQLITE_INT_TO_PTR(-1);
78250d51def2Sdan }
78260d51def2Sdan }else{
78270d51def2Sdan if( sqlite3GlobalConfig.pHeap==SQLITE_INT_TO_PTR(-1) ){
78280d51def2Sdan sqlite3GlobalConfig.pHeap = 0;
78290d51def2Sdan }
78300d51def2Sdan }
78310d51def2Sdan
78320d51def2Sdan Tcl_ResetResult(interp);
78330d51def2Sdan return TCL_OK;
78340d51def2Sdan }
78350d51def2Sdan
7836dfea4533Sdan /*
7837dfea4533Sdan ** sorter_test_sort4_helper DB SQL1 NSTEP SQL2
7838dfea4533Sdan **
7839dfea4533Sdan ** Compile SQL statement $SQL1 and step it $NSTEP times. For each row,
7840dfea4533Sdan ** check that the leftmost and rightmost columns returned are both integers,
7841dfea4533Sdan ** and that both contain the same value.
7842dfea4533Sdan **
7843dfea4533Sdan ** Then execute statement $SQL2. Check that the statement returns the same
7844dfea4533Sdan ** set of integers in the same order as in the previous step (using $SQL1).
7845dfea4533Sdan */
sorter_test_sort4_helper(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])78467617e4a8Smistachkin static int SQLITE_TCLAPI sorter_test_sort4_helper(
7847dfea4533Sdan void * clientData,
7848dfea4533Sdan Tcl_Interp *interp,
7849dfea4533Sdan int objc,
7850dfea4533Sdan Tcl_Obj *CONST objv[]
7851dfea4533Sdan ){
7852dfea4533Sdan const char *zSql1;
7853dfea4533Sdan const char *zSql2;
7854dfea4533Sdan int nStep;
7855dfea4533Sdan int iStep;
785648cd59a5Sdrh unsigned int iCksum1 = 0;
785748cd59a5Sdrh unsigned int iCksum2 = 0;
7858dfea4533Sdan int rc;
7859dfea4533Sdan int iB;
7860dfea4533Sdan sqlite3 *db;
7861dfea4533Sdan sqlite3_stmt *pStmt;
7862dfea4533Sdan
7863dfea4533Sdan if( objc!=5 ){
7864dfea4533Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB SQL1 NSTEP SQL2");
7865dfea4533Sdan return TCL_ERROR;
7866dfea4533Sdan }
7867dfea4533Sdan
7868dfea4533Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
7869dfea4533Sdan zSql1 = Tcl_GetString(objv[2]);
7870dfea4533Sdan if( Tcl_GetIntFromObj(interp, objv[3], &nStep) ) return TCL_ERROR;
7871dfea4533Sdan zSql2 = Tcl_GetString(objv[4]);
7872dfea4533Sdan
7873dfea4533Sdan rc = sqlite3_prepare_v2(db, zSql1, -1, &pStmt, 0);
7874dfea4533Sdan if( rc!=SQLITE_OK ) goto sql_error;
7875dfea4533Sdan
7876dfea4533Sdan iB = sqlite3_column_count(pStmt)-1;
7877dfea4533Sdan for(iStep=0; iStep<nStep && SQLITE_ROW==sqlite3_step(pStmt); iStep++){
7878dfea4533Sdan int a = sqlite3_column_int(pStmt, 0);
7879dfea4533Sdan if( a!=sqlite3_column_int(pStmt, iB) ){
7880dfea4533Sdan Tcl_AppendResult(interp, "data error: (a!=b)", 0);
7881dfea4533Sdan return TCL_ERROR;
7882dfea4533Sdan }
7883dfea4533Sdan
788448cd59a5Sdrh iCksum1 += (iCksum1 << 3) + (unsigned int)a;
7885dfea4533Sdan }
7886dfea4533Sdan rc = sqlite3_finalize(pStmt);
7887dfea4533Sdan if( rc!=SQLITE_OK ) goto sql_error;
7888dfea4533Sdan
7889dfea4533Sdan rc = sqlite3_prepare_v2(db, zSql2, -1, &pStmt, 0);
7890dfea4533Sdan if( rc!=SQLITE_OK ) goto sql_error;
7891dfea4533Sdan for(iStep=0; SQLITE_ROW==sqlite3_step(pStmt); iStep++){
7892dfea4533Sdan int a = sqlite3_column_int(pStmt, 0);
789348cd59a5Sdrh iCksum2 += (iCksum2 << 3) + (unsigned int)a;
7894dfea4533Sdan }
7895dfea4533Sdan rc = sqlite3_finalize(pStmt);
7896dfea4533Sdan if( rc!=SQLITE_OK ) goto sql_error;
7897dfea4533Sdan
7898dfea4533Sdan if( iCksum1!=iCksum2 ){
7899dfea4533Sdan Tcl_AppendResult(interp, "checksum mismatch", 0);
7900dfea4533Sdan return TCL_ERROR;
7901dfea4533Sdan }
7902dfea4533Sdan
7903dfea4533Sdan return TCL_OK;
7904dfea4533Sdan sql_error:
7905dfea4533Sdan Tcl_AppendResult(interp, "sql error: ", sqlite3_errmsg(db), 0);
7906dfea4533Sdan return TCL_ERROR;
7907dfea4533Sdan }
7908dfea4533Sdan
7909248f2be9Sdrh
7910d39c40ffSdrh #ifdef SQLITE_USER_AUTHENTICATION
7911d39c40ffSdrh #include "sqlite3userauth.h"
7912d39c40ffSdrh /*
7913d39c40ffSdrh ** tclcmd: sqlite3_user_authenticate DB USERNAME PASSWORD
7914d39c40ffSdrh */
test_user_authenticate(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])79157617e4a8Smistachkin static int SQLITE_TCLAPI test_user_authenticate(
7916d39c40ffSdrh ClientData clientData, /* Unused */
7917d39c40ffSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
7918d39c40ffSdrh int objc, /* Number of arguments */
7919d39c40ffSdrh Tcl_Obj *CONST objv[] /* Command arguments */
7920d39c40ffSdrh ){
7921d39c40ffSdrh char *zUser = 0;
7922d39c40ffSdrh char *zPasswd = 0;
7923d39c40ffSdrh int nPasswd = 0;
7924d39c40ffSdrh sqlite3 *db;
7925d39c40ffSdrh int rc;
7926d39c40ffSdrh
7927d39c40ffSdrh if( objc!=4 ){
7928d39c40ffSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD");
7929d39c40ffSdrh return TCL_ERROR;
7930d39c40ffSdrh }
7931d39c40ffSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
7932d39c40ffSdrh return TCL_ERROR;
7933d39c40ffSdrh }
7934d39c40ffSdrh zUser = Tcl_GetString(objv[2]);
7935d39c40ffSdrh zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
7936d39c40ffSdrh rc = sqlite3_user_authenticate(db, zUser, zPasswd, nPasswd);
7937d39c40ffSdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
7938d39c40ffSdrh return TCL_OK;
7939d39c40ffSdrh }
7940d39c40ffSdrh #endif /* SQLITE_USER_AUTHENTICATION */
7941d39c40ffSdrh
7942d39c40ffSdrh #ifdef SQLITE_USER_AUTHENTICATION
7943d39c40ffSdrh /*
7944d39c40ffSdrh ** tclcmd: sqlite3_user_add DB USERNAME PASSWORD ISADMIN
7945d39c40ffSdrh */
test_user_add(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])79467617e4a8Smistachkin static int SQLITE_TCLAPI test_user_add(
7947d39c40ffSdrh ClientData clientData, /* Unused */
7948d39c40ffSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
7949d39c40ffSdrh int objc, /* Number of arguments */
7950d39c40ffSdrh Tcl_Obj *CONST objv[] /* Command arguments */
7951d39c40ffSdrh ){
7952d39c40ffSdrh char *zUser = 0;
7953d39c40ffSdrh char *zPasswd = 0;
7954d39c40ffSdrh int nPasswd = 0;
7955d39c40ffSdrh int isAdmin = 0;
7956d39c40ffSdrh sqlite3 *db;
7957d39c40ffSdrh int rc;
7958d39c40ffSdrh
7959d39c40ffSdrh if( objc!=5 ){
7960d39c40ffSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
7961d39c40ffSdrh return TCL_ERROR;
7962d39c40ffSdrh }
7963d39c40ffSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
7964d39c40ffSdrh return TCL_ERROR;
7965d39c40ffSdrh }
7966d39c40ffSdrh zUser = Tcl_GetString(objv[2]);
7967d39c40ffSdrh zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
7968d39c40ffSdrh Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
7969d39c40ffSdrh rc = sqlite3_user_add(db, zUser, zPasswd, nPasswd, isAdmin);
7970d39c40ffSdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
7971d39c40ffSdrh return TCL_OK;
7972d39c40ffSdrh }
7973d39c40ffSdrh #endif /* SQLITE_USER_AUTHENTICATION */
7974d39c40ffSdrh
7975d39c40ffSdrh #ifdef SQLITE_USER_AUTHENTICATION
7976d39c40ffSdrh /*
7977d39c40ffSdrh ** tclcmd: sqlite3_user_change DB USERNAME PASSWORD ISADMIN
7978d39c40ffSdrh */
test_user_change(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])79797617e4a8Smistachkin static int SQLITE_TCLAPI test_user_change(
7980d39c40ffSdrh ClientData clientData, /* Unused */
7981d39c40ffSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
7982d39c40ffSdrh int objc, /* Number of arguments */
7983d39c40ffSdrh Tcl_Obj *CONST objv[] /* Command arguments */
7984d39c40ffSdrh ){
7985d39c40ffSdrh char *zUser = 0;
7986d39c40ffSdrh char *zPasswd = 0;
7987d39c40ffSdrh int nPasswd = 0;
7988d39c40ffSdrh int isAdmin = 0;
7989d39c40ffSdrh sqlite3 *db;
7990d39c40ffSdrh int rc;
7991d39c40ffSdrh
7992d39c40ffSdrh if( objc!=5 ){
7993d39c40ffSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
7994d39c40ffSdrh return TCL_ERROR;
7995d39c40ffSdrh }
7996d39c40ffSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
7997d39c40ffSdrh return TCL_ERROR;
7998d39c40ffSdrh }
7999d39c40ffSdrh zUser = Tcl_GetString(objv[2]);
8000d39c40ffSdrh zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
8001d39c40ffSdrh Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
8002d39c40ffSdrh rc = sqlite3_user_change(db, zUser, zPasswd, nPasswd, isAdmin);
8003d39c40ffSdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
8004d39c40ffSdrh return TCL_OK;
8005d39c40ffSdrh }
8006d39c40ffSdrh #endif /* SQLITE_USER_AUTHENTICATION */
8007d39c40ffSdrh
8008d39c40ffSdrh #ifdef SQLITE_USER_AUTHENTICATION
8009d39c40ffSdrh /*
8010d39c40ffSdrh ** tclcmd: sqlite3_user_delete DB USERNAME
8011d39c40ffSdrh */
test_user_delete(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])80127617e4a8Smistachkin static int SQLITE_TCLAPI test_user_delete(
8013d39c40ffSdrh ClientData clientData, /* Unused */
8014d39c40ffSdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
8015d39c40ffSdrh int objc, /* Number of arguments */
8016d39c40ffSdrh Tcl_Obj *CONST objv[] /* Command arguments */
8017d39c40ffSdrh ){
8018d39c40ffSdrh char *zUser = 0;
8019d39c40ffSdrh sqlite3 *db;
8020d39c40ffSdrh int rc;
8021d39c40ffSdrh
8022d39c40ffSdrh if( objc!=3 ){
8023d39c40ffSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME");
8024d39c40ffSdrh return TCL_ERROR;
8025d39c40ffSdrh }
8026d39c40ffSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
8027d39c40ffSdrh return TCL_ERROR;
8028d39c40ffSdrh }
8029d39c40ffSdrh zUser = Tcl_GetString(objv[2]);
8030d39c40ffSdrh rc = sqlite3_user_delete(db, zUser);
8031d39c40ffSdrh Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
8032d39c40ffSdrh return TCL_OK;
8033d39c40ffSdrh }
8034d39c40ffSdrh #endif /* SQLITE_USER_AUTHENTICATION */
8035d39c40ffSdrh
8036f58ee7f1Sdrh /*
8037edb31cd1Sdrh ** tclcmd: bad_behavior TYPE
8038edb31cd1Sdrh **
8039edb31cd1Sdrh ** Do some things that should trigger a valgrind or -fsanitize=undefined
8040edb31cd1Sdrh ** warning. This is used to verify that errors and warnings output by those
8041edb31cd1Sdrh ** tools are detected by the test scripts.
8042edb31cd1Sdrh **
8043edb31cd1Sdrh ** TYPE BEHAVIOR
8044edb31cd1Sdrh ** 1 Overflow a signed integer
8045edb31cd1Sdrh ** 2 Jump based on an uninitialized variable
8046edb31cd1Sdrh ** 3 Read after free
8047db6bafaeSdrh ** 4 Panic
8048edb31cd1Sdrh */
test_bad_behavior(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])80497617e4a8Smistachkin static int SQLITE_TCLAPI test_bad_behavior(
8050edb31cd1Sdrh ClientData clientData, /* Pointer to an integer containing zero */
8051edb31cd1Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
8052edb31cd1Sdrh int objc, /* Number of arguments */
8053edb31cd1Sdrh Tcl_Obj *CONST objv[] /* Command arguments */
8054edb31cd1Sdrh ){
8055edb31cd1Sdrh int iType;
8056edb31cd1Sdrh int xyz;
8057edb31cd1Sdrh int i = *(int*)clientData;
8058edb31cd1Sdrh int j;
8059edb31cd1Sdrh int w[10];
8060edb31cd1Sdrh int *a;
8061edb31cd1Sdrh if( objc!=2 ){
8062edb31cd1Sdrh Tcl_WrongNumArgs(interp, 1, objv, "TYPE");
8063edb31cd1Sdrh return TCL_ERROR;
8064edb31cd1Sdrh }
8065edb31cd1Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &iType) ) return TCL_ERROR;
8066edb31cd1Sdrh switch( iType ){
8067edb31cd1Sdrh case 1: {
8068edb31cd1Sdrh xyz = 0x7fffff00 - i;
8069edb31cd1Sdrh xyz += 0x100;
8070edb31cd1Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(xyz));
8071edb31cd1Sdrh break;
8072edb31cd1Sdrh }
8073edb31cd1Sdrh case 2: {
8074edb31cd1Sdrh w[1] = 5;
8075edb31cd1Sdrh if( w[i]>0 ) w[1]++;
8076edb31cd1Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(w[1]));
8077edb31cd1Sdrh break;
8078edb31cd1Sdrh }
8079edb31cd1Sdrh case 3: {
8080edb31cd1Sdrh a = malloc( sizeof(int)*10 );
8081edb31cd1Sdrh for(j=0; j<10; j++) a[j] = j;
8082edb31cd1Sdrh free(a);
8083edb31cd1Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(a[i]));
8084edb31cd1Sdrh break;
8085edb31cd1Sdrh }
8086db6bafaeSdrh case 4: {
8087db6bafaeSdrh Tcl_Panic("Deliberate panic");
8088db6bafaeSdrh break;
8089db6bafaeSdrh }
8090edb31cd1Sdrh }
8091edb31cd1Sdrh return TCL_OK;
8092edb31cd1Sdrh }
8093edb31cd1Sdrh
80943e0327d5Sdrh /*
80953e0327d5Sdrh ** tclcmd: register_dbstat_vtab DB
80963e0327d5Sdrh **
80973e0327d5Sdrh ** Cause the dbstat virtual table to be available on the connection DB
80983e0327d5Sdrh */
test_register_dbstat_vtab(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])80997617e4a8Smistachkin static int SQLITE_TCLAPI test_register_dbstat_vtab(
81003e0327d5Sdrh void *clientData,
81013e0327d5Sdrh Tcl_Interp *interp,
81023e0327d5Sdrh int objc,
81033e0327d5Sdrh Tcl_Obj *CONST objv[]
81043e0327d5Sdrh ){
81053e0327d5Sdrh #ifdef SQLITE_OMIT_VIRTUALTABLE
81063e0327d5Sdrh Tcl_AppendResult(interp, "dbstat not available because of "
81073e0327d5Sdrh "SQLITE_OMIT_VIRTUALTABLE", (void*)0);
81083e0327d5Sdrh return TCL_ERROR;
81093e0327d5Sdrh #else
81103e0327d5Sdrh struct SqliteDb { sqlite3 *db; };
81113e0327d5Sdrh char *zDb;
81123e0327d5Sdrh Tcl_CmdInfo cmdInfo;
81133e0327d5Sdrh
81143e0327d5Sdrh if( objc!=2 ){
81153e0327d5Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DB");
81163e0327d5Sdrh return TCL_ERROR;
81173e0327d5Sdrh }
81183e0327d5Sdrh
81193e0327d5Sdrh zDb = Tcl_GetString(objv[1]);
81203e0327d5Sdrh if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
81213e0327d5Sdrh sqlite3* db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
81223e0327d5Sdrh sqlite3DbstatRegister(db);
81233e0327d5Sdrh }
81243e0327d5Sdrh return TCL_OK;
81253e0327d5Sdrh #endif /* SQLITE_OMIT_VIRTUALTABLE */
81263e0327d5Sdrh }
8127edb31cd1Sdrh
8128edb31cd1Sdrh /*
8129d42908fbSdrh ** tclcmd: sqlite3_db_config DB SETTING VALUE
8130d42908fbSdrh **
8131d42908fbSdrh ** Invoke sqlite3_db_config() for one of the setting values.
8132d42908fbSdrh */
test_sqlite3_db_config(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])81337617e4a8Smistachkin static int SQLITE_TCLAPI test_sqlite3_db_config(
8134d42908fbSdrh void *clientData,
8135d42908fbSdrh Tcl_Interp *interp,
8136d42908fbSdrh int objc,
8137d42908fbSdrh Tcl_Obj *CONST objv[]
8138d42908fbSdrh ){
8139d42908fbSdrh static const struct {
8140d42908fbSdrh const char *zName;
8141d42908fbSdrh int eVal;
8142d42908fbSdrh } aSetting[] = {
8143d42908fbSdrh { "FKEY", SQLITE_DBCONFIG_ENABLE_FKEY },
8144d42908fbSdrh { "TRIGGER", SQLITE_DBCONFIG_ENABLE_TRIGGER },
8145d42908fbSdrh { "FTS3_TOKENIZER", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
8146191dd061Sdrh { "LOAD_EXTENSION", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
8147298af023Sdan { "NO_CKPT_ON_CLOSE", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
8148169dd928Sdrh { "QPSG", SQLITE_DBCONFIG_ENABLE_QPSG },
81497df01196Sdrh { "TRIGGER_EQP", SQLITE_DBCONFIG_TRIGGER_EQP },
81507df01196Sdrh { "RESET_DB", SQLITE_DBCONFIG_RESET_DATABASE },
81510f1c2eb5Sdrh { "DEFENSIVE", SQLITE_DBCONFIG_DEFENSIVE },
81520a6873bfSdrh { "WRITABLE_SCHEMA", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
81530a6873bfSdrh { "LEGACY_ALTER_TABLE", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
8154d0ff601cSdrh { "DQS_DML", SQLITE_DBCONFIG_DQS_DML },
8155d0ff601cSdrh { "DQS_DDL", SQLITE_DBCONFIG_DQS_DDL },
815666c48907Sdrh { "LEGACY_FILE_FORMAT", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
8157d42908fbSdrh };
8158d42908fbSdrh int i;
815966c48907Sdrh int v = 0;
8160d42908fbSdrh const char *zSetting;
8161d42908fbSdrh sqlite3 *db;
8162d42908fbSdrh
816366c48907Sdrh if( objc!=4 && objc!=3 ){
816466c48907Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DB SETTING [VALUE]");
8165d42908fbSdrh return TCL_ERROR;
8166d42908fbSdrh }
8167d42908fbSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
8168d42908fbSdrh zSetting = Tcl_GetString(objv[2]);
8169d42908fbSdrh if( sqlite3_strglob("SQLITE_*", zSetting)==0 ) zSetting += 7;
8170d42908fbSdrh if( sqlite3_strglob("DBCONFIG_*", zSetting)==0 ) zSetting += 9;
8171d42908fbSdrh if( sqlite3_strglob("ENABLE_*", zSetting)==0 ) zSetting += 7;
8172d42908fbSdrh for(i=0; i<ArraySize(aSetting); i++){
8173d42908fbSdrh if( strcmp(zSetting, aSetting[i].zName)==0 ) break;
8174d42908fbSdrh }
8175d42908fbSdrh if( i>=ArraySize(aSetting) ){
8176d42908fbSdrh Tcl_SetObjResult(interp,
8177d42908fbSdrh Tcl_NewStringObj("unknown sqlite3_db_config setting", -1));
8178d42908fbSdrh return TCL_ERROR;
8179d42908fbSdrh }
818066c48907Sdrh if( objc==4 ){
8181d42908fbSdrh if( Tcl_GetIntFromObj(interp, objv[3], &v) ) return TCL_ERROR;
818266c48907Sdrh }else{
818366c48907Sdrh v = -1;
818466c48907Sdrh }
8185d42908fbSdrh sqlite3_db_config(db, aSetting[i].eVal, v, &v);
8186d42908fbSdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(v));
8187d42908fbSdrh return TCL_OK;
8188d42908fbSdrh }
818999744fa4Sdrh /*
819099744fa4Sdrh ** tclcmd: sqlite3_txn_state DB ?SCHEMA?
819199744fa4Sdrh **
819299744fa4Sdrh ** Invoke sqlite3_txn_state(DB,SCHEMA) and return the
819399744fa4Sdrh ** numeric value that results. Use NULL for SCHEMA if the 3 argument
819499744fa4Sdrh ** is omitted.
819599744fa4Sdrh */
test_sqlite3_txn_state(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])819699744fa4Sdrh static int SQLITE_TCLAPI test_sqlite3_txn_state(
819799744fa4Sdrh void *clientData,
819899744fa4Sdrh Tcl_Interp *interp,
819999744fa4Sdrh int objc,
820099744fa4Sdrh Tcl_Obj *CONST objv[]
820199744fa4Sdrh ){
820299744fa4Sdrh sqlite3 *db;
820399744fa4Sdrh const char *zSchema;
820499744fa4Sdrh int iTxn;
820599744fa4Sdrh
820699744fa4Sdrh if( objc!=2 && objc!=3 ){
820799744fa4Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DB ?SCHEMA?");
820899744fa4Sdrh return TCL_ERROR;
820999744fa4Sdrh }
821099744fa4Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
821199744fa4Sdrh zSchema = objc==3 ? Tcl_GetString(objv[2]) : 0;
821299744fa4Sdrh iTxn = sqlite3_txn_state(db, zSchema);
821399744fa4Sdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(iTxn));
821499744fa4Sdrh return TCL_OK;
821599744fa4Sdrh }
8216d42908fbSdrh
8217d42908fbSdrh /*
8218da84dcaeSdrh ** Change the name of the main database schema from "main" to "icecube".
8219da84dcaeSdrh */
test_dbconfig_maindbname_icecube(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])8220da84dcaeSdrh static int SQLITE_TCLAPI test_dbconfig_maindbname_icecube(
8221da84dcaeSdrh void * clientData,
8222da84dcaeSdrh Tcl_Interp *interp,
8223da84dcaeSdrh int objc,
8224da84dcaeSdrh Tcl_Obj *CONST objv[]
8225da84dcaeSdrh ){
8226da84dcaeSdrh int rc;
8227da84dcaeSdrh sqlite3 *db;
8228da84dcaeSdrh extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
8229da84dcaeSdrh if( objc!=2 ){
8230da84dcaeSdrh Tcl_WrongNumArgs(interp, 1, objv, "DB");
8231da84dcaeSdrh return TCL_ERROR;
8232da84dcaeSdrh }else{
8233da84dcaeSdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
8234da84dcaeSdrh rc = sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, "icecube");
8235da84dcaeSdrh Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
8236da84dcaeSdrh return TCL_OK;
8237da84dcaeSdrh }
8238da84dcaeSdrh }
8239da84dcaeSdrh
8240da84dcaeSdrh /*
8241460f1fa5Sdan ** Usage: sqlite3_mmap_warm DB DBNAME
8242460f1fa5Sdan */
test_mmap_warm(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])8243460f1fa5Sdan static int SQLITE_TCLAPI test_mmap_warm(
8244460f1fa5Sdan void * clientData,
8245460f1fa5Sdan Tcl_Interp *interp,
8246460f1fa5Sdan int objc,
8247460f1fa5Sdan Tcl_Obj *CONST objv[]
8248460f1fa5Sdan ){
8249460f1fa5Sdan extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
8250460f1fa5Sdan extern int sqlite3_mmap_warm(sqlite3 *db, const char *);
8251460f1fa5Sdan
8252460f1fa5Sdan if( objc!=2 && objc!=3 ){
8253460f1fa5Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB ?DBNAME?");
8254460f1fa5Sdan return TCL_ERROR;
8255460f1fa5Sdan }else{
8256460f1fa5Sdan int rc;
8257460f1fa5Sdan sqlite3 *db;
8258460f1fa5Sdan const char *zDb = 0;
8259460f1fa5Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
8260460f1fa5Sdan if( objc==3 ){
8261460f1fa5Sdan zDb = Tcl_GetString(objv[2]);
8262460f1fa5Sdan }
8263460f1fa5Sdan rc = sqlite3_mmap_warm(db, zDb);
8264460f1fa5Sdan Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
8265460f1fa5Sdan return TCL_OK;
8266460f1fa5Sdan }
8267460f1fa5Sdan }
8268460f1fa5Sdan
8269460f1fa5Sdan /*
827091faeec8Sdan ** Usage: test_write_db DB OFFSET DATA
827191faeec8Sdan **
827291faeec8Sdan ** Obtain the sqlite3_file* object for the database file for the "main" db
827391faeec8Sdan ** of handle DB. Then invoke its xWrite method to write data DATA to offset
827491faeec8Sdan ** OFFSET.
827591faeec8Sdan */
test_write_db(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])827691faeec8Sdan static int SQLITE_TCLAPI test_write_db(
827791faeec8Sdan void * clientData,
827891faeec8Sdan Tcl_Interp *interp,
827991faeec8Sdan int objc,
828091faeec8Sdan Tcl_Obj *CONST objv[]
828191faeec8Sdan ){
828291faeec8Sdan sqlite3 *db = 0;
828391faeec8Sdan Tcl_WideInt iOff = 0;
828491faeec8Sdan const unsigned char *aData = 0;
828591faeec8Sdan int nData = 0;
828691faeec8Sdan sqlite3_file *pFile = 0;
828791faeec8Sdan int rc;
828891faeec8Sdan
828991faeec8Sdan if( objc!=4 ){
829091faeec8Sdan Tcl_WrongNumArgs(interp, 1, objv, "DB OFFSET DATA");
829191faeec8Sdan return TCL_ERROR;
829291faeec8Sdan }
829391faeec8Sdan if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
829491faeec8Sdan if( Tcl_GetWideIntFromObj(interp, objv[2], &iOff) ) return TCL_ERROR;
829591faeec8Sdan aData = Tcl_GetByteArrayFromObj(objv[3], &nData);
829691faeec8Sdan
829791faeec8Sdan sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, (void*)&pFile);
829891faeec8Sdan rc = pFile->pMethods->xWrite(pFile, aData, nData, iOff);
829991faeec8Sdan
830091faeec8Sdan Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
830191faeec8Sdan return TCL_OK;
830291faeec8Sdan }
830391faeec8Sdan
830491faeec8Sdan /*
8305c30b78f6Sdan ** Usage: sqlite3_register_cksumvfs
8306c30b78f6Sdan **
8307c30b78f6Sdan */
test_register_cksumvfs(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])8308c30b78f6Sdan static int SQLITE_TCLAPI test_register_cksumvfs(
8309c30b78f6Sdan void * clientData,
8310c30b78f6Sdan Tcl_Interp *interp,
8311c30b78f6Sdan int objc,
8312c30b78f6Sdan Tcl_Obj *CONST objv[]
8313c30b78f6Sdan ){
8314c30b78f6Sdan if( objc!=1 ){
8315c30b78f6Sdan Tcl_WrongNumArgs(interp, 1, objv, "");
8316c30b78f6Sdan return TCL_ERROR;
8317c30b78f6Sdan }else{
8318c30b78f6Sdan extern int sqlite3_register_cksumvfs(const char*);
8319c30b78f6Sdan int rc = sqlite3_register_cksumvfs(0);
8320c30b78f6Sdan Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
8321c30b78f6Sdan }
8322c30b78f6Sdan return TCL_OK;
8323c30b78f6Sdan }
8324c30b78f6Sdan
8325c30b78f6Sdan /*
8326c30b78f6Sdan ** Usage: sqlite3_unregister_cksumvfs
8327c30b78f6Sdan **
8328c30b78f6Sdan */
test_unregister_cksumvfs(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])8329c30b78f6Sdan static int SQLITE_TCLAPI test_unregister_cksumvfs(
8330c30b78f6Sdan void * clientData,
8331c30b78f6Sdan Tcl_Interp *interp,
8332c30b78f6Sdan int objc,
8333c30b78f6Sdan Tcl_Obj *CONST objv[]
8334c30b78f6Sdan ){
8335c30b78f6Sdan if( objc!=1 ){
8336c30b78f6Sdan Tcl_WrongNumArgs(interp, 1, objv, "");
8337c30b78f6Sdan return TCL_ERROR;
8338c30b78f6Sdan }else{
8339c30b78f6Sdan extern int sqlite3_unregister_cksumvfs(void);
8340c30b78f6Sdan int rc = sqlite3_unregister_cksumvfs();
8341c30b78f6Sdan Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
8342c30b78f6Sdan }
8343c30b78f6Sdan return TCL_OK;
8344c30b78f6Sdan }
8345c30b78f6Sdan
8346c30b78f6Sdan /*
8347f7e74904Sdrh ** Usage: decode_hexdb TEXT
8348f7e74904Sdrh **
8349f7e74904Sdrh ** Example: db deserialize [decode_hexdb $output_of_dbtotxt]
8350f7e74904Sdrh **
8351f7e74904Sdrh ** This routine returns a byte-array for an SQLite database file that
8352f7e74904Sdrh ** is constructed from a text input which is the output of the "dbtotxt"
8353f7e74904Sdrh ** utility.
8354f7e74904Sdrh */
test_decode_hexdb(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])8355f7e74904Sdrh static int SQLITE_TCLAPI test_decode_hexdb(
8356f7e74904Sdrh void * clientData,
8357f7e74904Sdrh Tcl_Interp *interp,
8358f7e74904Sdrh int objc,
8359f7e74904Sdrh Tcl_Obj *CONST objv[]
8360f7e74904Sdrh ){
8361f7e74904Sdrh const char *zIn = 0;
8362f7e74904Sdrh unsigned char *a = 0;
8363f7e74904Sdrh int n = 0;
8364f7e74904Sdrh int lineno = 0;
8365f7e74904Sdrh int i, iNext;
8366f7e74904Sdrh int iOffset = 0;
8367f7e74904Sdrh int j, k;
8368f7e74904Sdrh int rc;
83693ea557e0Sdrh unsigned int x[16];
8370f7e74904Sdrh if( objc!=2 ){
8371f7e74904Sdrh Tcl_WrongNumArgs(interp, 1, objv, "HEXDB");
8372f7e74904Sdrh return TCL_ERROR;
8373f7e74904Sdrh }
8374f7e74904Sdrh zIn = Tcl_GetString(objv[1]);
8375f7e74904Sdrh for(i=0; zIn[i]; i=iNext){
8376f7e74904Sdrh lineno++;
8377f7e74904Sdrh for(iNext=i; zIn[iNext] && zIn[iNext]!='\n'; iNext++){}
8378f7e74904Sdrh if( zIn[iNext]=='\n' ) iNext++;
8379f7e74904Sdrh while( zIn[i]==' ' || zIn[i]=='\t' ){ i++; }
8380f7e74904Sdrh if( a==0 ){
8381f7e74904Sdrh int pgsz;
8382f7e74904Sdrh rc = sscanf(zIn+i, "| size %d pagesize %d", &n, &pgsz);
8383f7e74904Sdrh if( rc!=2 ) continue;
838409ea1256Sdrh if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ){
838509ea1256Sdrh Tcl_AppendResult(interp, "bad 'pagesize' field", (void*)0);
838609ea1256Sdrh return TCL_ERROR;
838709ea1256Sdrh }
838809ea1256Sdrh n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
8389f7e74904Sdrh if( n<512 ){
8390f7e74904Sdrh Tcl_AppendResult(interp, "bad 'size' field", (void*)0);
8391f7e74904Sdrh return TCL_ERROR;
8392f7e74904Sdrh }
8393f7e74904Sdrh a = malloc( n );
8394f7e74904Sdrh if( a==0 ){
8395f7e74904Sdrh Tcl_AppendResult(interp, "out of memory", (void*)0);
8396f7e74904Sdrh return TCL_ERROR;
8397f7e74904Sdrh }
8398f7e74904Sdrh memset(a, 0, n);
8399f7e74904Sdrh continue;
8400f7e74904Sdrh }
8401f7e74904Sdrh rc = sscanf(zIn+i, "| page %d offset %d", &j, &k);
8402f7e74904Sdrh if( rc==2 ){
8403f7e74904Sdrh iOffset = k;
8404f7e74904Sdrh continue;
8405f7e74904Sdrh }
84063ea557e0Sdrh rc = sscanf(zIn+i,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
8407f7e74904Sdrh &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
8408f7e74904Sdrh &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
8409f7e74904Sdrh if( rc==17 ){
8410f7e74904Sdrh k = iOffset+j;
8411f7e74904Sdrh if( k+16<=n ){
84123ea557e0Sdrh int ii;
84133ea557e0Sdrh for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
8414f7e74904Sdrh }
8415f7e74904Sdrh continue;
8416f7e74904Sdrh }
8417f7e74904Sdrh }
8418f7e74904Sdrh Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(a, n));
8419f7e74904Sdrh free(a);
8420f7e74904Sdrh return TCL_OK;
8421f7e74904Sdrh }
8422f7e74904Sdrh
84231bbfc674Sdrh /*
84241bbfc674Sdrh ** Client data for the autovacuum_pages callback.
84251bbfc674Sdrh */
84261bbfc674Sdrh struct AutovacPageData {
84271bbfc674Sdrh Tcl_Interp *interp;
84281bbfc674Sdrh char *zScript;
84291bbfc674Sdrh };
84301bbfc674Sdrh typedef struct AutovacPageData AutovacPageData;
84311bbfc674Sdrh
84321bbfc674Sdrh /*
84331bbfc674Sdrh ** Callback functions for sqlite3_autovacuum_pages
84341bbfc674Sdrh */
test_autovacuum_pages_callback(void * pClientData,const char * zSchema,unsigned int nFilePages,unsigned int nFreePages,unsigned int nBytePerPage)84351bbfc674Sdrh static unsigned int test_autovacuum_pages_callback(
84361bbfc674Sdrh void *pClientData,
84371bbfc674Sdrh const char *zSchema,
84381bbfc674Sdrh unsigned int nFilePages,
84391bbfc674Sdrh unsigned int nFreePages,
84401bbfc674Sdrh unsigned int nBytePerPage
84411bbfc674Sdrh ){
84421bbfc674Sdrh AutovacPageData *pData = (AutovacPageData*)pClientData;
84431bbfc674Sdrh Tcl_DString str;
84441bbfc674Sdrh unsigned int x;
84451bbfc674Sdrh char zBuf[100];
84461bbfc674Sdrh Tcl_DStringInit(&str);
84471bbfc674Sdrh Tcl_DStringAppend(&str, pData->zScript, -1);
84481bbfc674Sdrh Tcl_DStringAppendElement(&str, zSchema);
84491bbfc674Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%u", nFilePages);
84501bbfc674Sdrh Tcl_DStringAppendElement(&str, zBuf);
84511bbfc674Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%u", nFreePages);
84521bbfc674Sdrh Tcl_DStringAppendElement(&str, zBuf);
84531bbfc674Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%u", nBytePerPage);
84541bbfc674Sdrh Tcl_DStringAppendElement(&str, zBuf);
84551bbfc674Sdrh Tcl_ResetResult(pData->interp);
84561bbfc674Sdrh Tcl_Eval(pData->interp, Tcl_DStringValue(&str));
84571bbfc674Sdrh Tcl_DStringFree(&str);
84581bbfc674Sdrh x = nFreePages;
84591bbfc674Sdrh (void)Tcl_GetIntFromObj(0, Tcl_GetObjResult(pData->interp), (int*)&x);
84601bbfc674Sdrh return x;
84611bbfc674Sdrh }
84621bbfc674Sdrh
84631bbfc674Sdrh /*
84641bbfc674Sdrh ** Usage: sqlite3_autovacuum_pages DB SCRIPT
84651bbfc674Sdrh **
84661bbfc674Sdrh ** Add an autovacuum-pages callback to database connection DB. The callback
84671bbfc674Sdrh ** will invoke SCRIPT, after appending parameters.
84681bbfc674Sdrh **
84691bbfc674Sdrh ** If SCRIPT is an empty string or is omitted, then the callback is
84701bbfc674Sdrh ** cancelled.
84711bbfc674Sdrh */
test_autovacuum_pages(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])84721bbfc674Sdrh static int SQLITE_TCLAPI test_autovacuum_pages(
84731bbfc674Sdrh void * clientData,
84741bbfc674Sdrh Tcl_Interp *interp,
84751bbfc674Sdrh int objc,
84761bbfc674Sdrh Tcl_Obj *CONST objv[]
84771bbfc674Sdrh ){
84781bbfc674Sdrh AutovacPageData *pData;
84791bbfc674Sdrh sqlite3 *db;
84801bbfc674Sdrh int rc;
84811bbfc674Sdrh const char *zScript;
84821bbfc674Sdrh if( objc!=2 && objc!=3 ){
84831bbfc674Sdrh Tcl_WrongNumArgs(interp, 1, objv, "DB ?SCRIPT?");
84841bbfc674Sdrh return TCL_ERROR;
84851bbfc674Sdrh }
84861bbfc674Sdrh if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
84871bbfc674Sdrh zScript = objc==3 ? Tcl_GetString(objv[2]) : 0;
848821b1c6ddSdan if( zScript ){
848921b1c6ddSdan size_t nScript = strlen(zScript);
84901bbfc674Sdrh pData = sqlite3_malloc64( sizeof(*pData) + nScript + 1 );
84911bbfc674Sdrh if( pData==0 ){
84921bbfc674Sdrh Tcl_AppendResult(interp, "out of memory", (void*)0);
84931bbfc674Sdrh return TCL_ERROR;
84941bbfc674Sdrh }
84951bbfc674Sdrh pData->interp = interp;
84961bbfc674Sdrh pData->zScript = (char*)&pData[1];
84971bbfc674Sdrh memcpy(pData->zScript, zScript, nScript+1);
84981bbfc674Sdrh rc = sqlite3_autovacuum_pages(db,test_autovacuum_pages_callback,
84991bbfc674Sdrh pData, sqlite3_free);
85001bbfc674Sdrh }else{
85011bbfc674Sdrh rc = sqlite3_autovacuum_pages(db, 0, 0, 0);
85021bbfc674Sdrh }
85031bbfc674Sdrh if( rc ){
85041bbfc674Sdrh char zBuf[1000];
85051bbfc674Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf,
85061bbfc674Sdrh "sqlite3_autovacuum_pages() returns %d", rc);
85071bbfc674Sdrh Tcl_AppendResult(interp, zBuf, (void*)0);
85081bbfc674Sdrh return TCL_ERROR;
85091bbfc674Sdrh }
85101bbfc674Sdrh return TCL_OK;
85111bbfc674Sdrh }
85121bbfc674Sdrh
8513f7e74904Sdrh
8514f7e74904Sdrh /*
8515d1bf3512Sdrh ** Register commands with the TCL interpreter.
8516d1bf3512Sdrh */
Sqlitetest1_Init(Tcl_Interp * interp)8517d1bf3512Sdrh int Sqlitetest1_Init(Tcl_Interp *interp){
85186f8a503dSdanielk1977 extern int sqlite3_search_count;
85190ff297eaSdan extern int sqlite3_found_count;
85206f8a503dSdanielk1977 extern int sqlite3_interrupt_count;
85216f8a503dSdanielk1977 extern int sqlite3_open_file_count;
85226bf89570Sdrh extern int sqlite3_sort_count;
85236f8a503dSdanielk1977 extern int sqlite3_current_time;
852484a2bf67Sdrh #if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
8525aebf413dSaswift extern int sqlite3_hostid_num;
8526aabbed22Spweilbacher #endif
8527ae7e151aSdrh extern int sqlite3_max_blobsize;
85287617e4a8Smistachkin extern int SQLITE_TCLAPI sqlite3BtreeSharedCacheReport(void*,
852916a9b836Sdrh Tcl_Interp*,int,Tcl_Obj*CONST*);
8530edb31cd1Sdrh static int iZero = 0;
8531c2eef3b3Sdrh static struct {
8532c2eef3b3Sdrh char *zName;
8533c2eef3b3Sdrh Tcl_CmdProc *xProc;
8534c2eef3b3Sdrh } aCmd[] = {
853527641703Sdrh { "db_enter", (Tcl_CmdProc*)db_enter },
853627641703Sdrh { "db_leave", (Tcl_CmdProc*)db_leave },
85376f8a503dSdanielk1977 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int },
8538e9707671Sdrh { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 },
8539c5cad1e3Sdrh { "sqlite3_mprintf_long", (Tcl_CmdProc*)sqlite3_mprintf_long },
85406f8a503dSdanielk1977 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str },
8541b3738b6cSdrh { "sqlite3_snprintf_str", (Tcl_CmdProc*)sqlite3_snprintf_str },
8542e29b1a05Sdrh { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly},
85436f8a503dSdanielk1977 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double },
85446f8a503dSdanielk1977 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled },
854563782855Sdrh { "sqlite3_mprintf_hexdouble", (Tcl_CmdProc*)sqlite3_mprintf_hexdouble},
85466f8a503dSdanielk1977 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z },
854705a82983Sdrh { "sqlite3_mprintf_n_test", (Tcl_CmdProc*)test_mprintf_n },
854868853907Sdrh { "sqlite3_snprintf_int", (Tcl_CmdProc*)test_snprintf_int },
85496f8a503dSdanielk1977 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid },
85506f8a503dSdanielk1977 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf },
85515bd98aefSdrh { "sqlite3_exec_hex", (Tcl_CmdProc*)test_exec_hex },
8552b62c335eSdrh { "sqlite3_exec", (Tcl_CmdProc*)test_exec },
8553b62c335eSdrh { "sqlite3_exec_nr", (Tcl_CmdProc*)test_exec_nr },
85548225f5acSshane #ifndef SQLITE_OMIT_GET_TABLE
85556f8a503dSdanielk1977 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
85568225f5acSshane #endif
85576f8a503dSdanielk1977 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close },
8558617dc860Sdan { "sqlite3_close_v2", (Tcl_CmdProc*)sqlite_test_close_v2 },
85596f8a503dSdanielk1977 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
85606f8a503dSdanielk1977 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
85618c754a36Sdrh { "sqlite3_drop_modules", (Tcl_CmdProc*)test_drop_modules },
8562c2eef3b3Sdrh { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
8563c2eef3b3Sdrh { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
856496fc5fe6Sdanielk1977 { "sqlite_bind", (Tcl_CmdProc*)test_bind },
856599ee3600Sdrh { "breakpoint", (Tcl_CmdProc*)test_breakpoint },
856625d6543dSdrh { "sqlite3_key", (Tcl_CmdProc*)test_key },
856725d6543dSdrh { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey },
8568c5cdca61Sdrh { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt },
85699636c4e1Sdanielk1977 { "sqlite_delete_function", (Tcl_CmdProc*)delete_function },
85703e1d8e63Sdrh { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation },
85713e1d8e63Sdrh { "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit },
85723086765bSdrh { "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout },
85733c23a885Sdrh { "printf", (Tcl_CmdProc*)test_printf },
85743a00f907Smlcreech { "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace },
8575afcf9bd8Sdan { "clang_sanitize_address", (Tcl_CmdProc*)clang_sanitize_address },
8576c2eef3b3Sdrh };
857751e3d8e2Sdanielk1977 static struct {
857851e3d8e2Sdanielk1977 char *zName;
857951e3d8e2Sdanielk1977 Tcl_ObjCmdProc *xProc;
858004f2e68dSdanielk1977 void *clientData;
858151e3d8e2Sdanielk1977 } aObjCmd[] = {
8582d42908fbSdrh { "sqlite3_db_config", test_sqlite3_db_config, 0 },
858399744fa4Sdrh { "sqlite3_txn_state", test_sqlite3_txn_state, 0 },
8584edb31cd1Sdrh { "bad_behavior", test_bad_behavior, (void*)&iZero },
85853e0327d5Sdrh { "register_dbstat_vtab", test_register_dbstat_vtab },
8586dddca286Sdrh { "sqlite3_connection_pointer", get_sqlite_pointer, 0 },
85872e3f87aeSdrh { "intarray_addr", test_intarray_addr, 0 },
85882e3f87aeSdrh { "int64array_addr", test_int64array_addr, 0 },
85892e3f87aeSdrh { "doublearray_addr", test_doublearray_addr, 0 },
85902e3f87aeSdrh { "textarray_addr", test_textarray_addr, 0 },
8591241db313Sdrh { "sqlite3_bind_int", test_bind_int, 0 },
8592b026e05eSdrh { "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 },
859380c03022Sdan { "sqlite3_bind_zeroblob64", test_bind_zeroblob64, 0 },
859404f2e68dSdanielk1977 { "sqlite3_bind_int64", test_bind_int64, 0 },
859504f2e68dSdanielk1977 { "sqlite3_bind_double", test_bind_double, 0 },
859604f2e68dSdanielk1977 { "sqlite3_bind_null", test_bind_null ,0 },
859704f2e68dSdanielk1977 { "sqlite3_bind_text", test_bind_text ,0 },
859804f2e68dSdanielk1977 { "sqlite3_bind_text16", test_bind_text16 ,0 },
859904f2e68dSdanielk1977 { "sqlite3_bind_blob", test_bind_blob ,0 },
8600252fe67bSdan { "sqlite3_bind_value_from_select",test_bind_value_from_select ,0 },
8601252fe67bSdan { "sqlite3_bind_value_from_preupdate",test_bind_value_from_preupdate ,0 },
86025011bb8dSdan #ifndef SQLITE_OMIT_VIRTUALTABLE
8603ea847f1bSdrh { "sqlite3_carray_bind", test_carray_bind ,0 },
86045011bb8dSdan #endif
860575f6a032Sdrh { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0},
8606895d7472Sdrh { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0},
8607fa6bc000Sdrh { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0},
8608600dd0baSdanielk1977 { "sqlite3_clear_bindings", test_clear_bindings, 0},
8609f9cb7f58Sdrh { "sqlite3_sleep", test_sleep, 0},
861004f2e68dSdanielk1977 { "sqlite3_errcode", test_errcode ,0 },
861199dfe5ebSdrh { "sqlite3_extended_errcode", test_ex_errcode ,0 },
861204f2e68dSdanielk1977 { "sqlite3_errmsg", test_errmsg ,0 },
8613f62641e9Sdrh { "sqlite3_error_offset", test_error_offset ,0 },
861404f2e68dSdanielk1977 { "sqlite3_errmsg16", test_errmsg16 ,0 },
861504f2e68dSdanielk1977 { "sqlite3_open", test_open ,0 },
861604f2e68dSdanielk1977 { "sqlite3_open16", test_open16 ,0 },
8617286ab7c2Sdan { "sqlite3_open_v2", test_open_v2 ,0 },
8618bc6ada41Sdanielk1977 { "sqlite3_complete16", test_complete16 ,0 },
861991694dbdSdrh { "sqlite3_normalize", test_normalize ,0 },
862004f2e68dSdanielk1977
862104f2e68dSdanielk1977 { "sqlite3_prepare", test_prepare ,0 },
862204f2e68dSdanielk1977 { "sqlite3_prepare16", test_prepare16 ,0 },
8623b900aaf3Sdrh { "sqlite3_prepare_v2", test_prepare_v2 ,0 },
86248bee11a4Smistachkin { "sqlite3_prepare_v3", test_prepare_v3 ,0 },
86254837f531Sdrh { "sqlite3_prepare_tkt3134", test_prepare_tkt3134, 0},
8626b900aaf3Sdrh { "sqlite3_prepare16_v2", test_prepare16_v2 ,0 },
862704f2e68dSdanielk1977 { "sqlite3_finalize", test_finalize ,0 },
8628d1d38488Sdrh { "sqlite3_stmt_status", test_stmt_status ,0 },
862904f2e68dSdanielk1977 { "sqlite3_reset", test_reset ,0 },
8630d89bd007Sdrh { "sqlite3_expired", test_expired ,0 },
8631f8db1bc0Sdrh { "sqlite3_transfer_bindings", test_transfer_bind ,0 },
8632fbcd585fSdanielk1977 { "sqlite3_changes", test_changes ,0 },
863304f2e68dSdanielk1977 { "sqlite3_step", test_step ,0 },
8634404ca075Sdanielk1977 { "sqlite3_sql", test_sql ,0 },
8635fca760c8Sdrh { "sqlite3_expanded_sql", test_ex_sql ,0 },
86368bee11a4Smistachkin #ifdef SQLITE_ENABLE_NORMALIZE
86378bee11a4Smistachkin { "sqlite3_normalized_sql", test_norm_sql ,0 },
86388bee11a4Smistachkin #endif
8639bb5a9c3eSdrh { "sqlite3_next_stmt", test_next_stmt ,0 },
8640f03d9cccSdrh { "sqlite3_stmt_readonly", test_stmt_readonly ,0 },
864139c5c4aeSdrh { "sqlite3_stmt_isexplain", test_stmt_isexplain,0 },
86422fb6693eSdrh { "sqlite3_stmt_busy", test_stmt_busy ,0 },
8643d9495cd0Sdan { "uses_stmt_journal", uses_stmt_journal ,0 },
864404f2e68dSdanielk1977
86456aafc29bSdrh { "sqlite3_release_memory", test_release_memory, 0},
864609419b4bSdrh { "sqlite3_db_release_memory", test_db_release_memory, 0},
86476fa255fdSdan { "sqlite3_db_cacheflush", test_db_cacheflush, 0},
86480e80e509Sdrh { "sqlite3_system_errno", test_system_errno, 0},
8649283829cbSdrh { "sqlite3_db_filename", test_db_filename, 0},
8650421377e6Sdrh { "sqlite3_db_readonly", test_db_readonly, 0},
86516aafc29bSdrh { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
865210c0e711Sdrh { "sqlite3_soft_heap_limit64", test_soft_heap_limit, 0},
865310c0e711Sdrh { "sqlite3_hard_heap_limit64", test_hard_heap_limit, 0},
8654b4bc7057Sdrh { "sqlite3_thread_cleanup", test_thread_cleanup, 0},
8655c6ba55f4Sdrh { "sqlite3_pager_refcounts", test_pager_refcounts, 0},
86566aafc29bSdrh
8657c2e87a3eSdrh { "sqlite3_load_extension", test_load_extension, 0},
8658c2e87a3eSdrh { "sqlite3_enable_load_extension", test_enable_load, 0},
86594ac285a1Sdrh { "sqlite3_extended_result_codes", test_extended_result_codes, 0},
8660b1a6c3c1Sdrh { "sqlite3_limit", test_limit, 0},
8661da84dcaeSdrh { "dbconfig_maindbname_icecube", test_dbconfig_maindbname_icecube },
8662c2e87a3eSdrh
866393aed5a1Sdrh { "save_prng_state", save_prng_state, 0 },
866493aed5a1Sdrh { "restore_prng_state", restore_prng_state, 0 },
866593aed5a1Sdrh { "reset_prng_state", reset_prng_state, 0 },
8666ade54d68Sdrh { "prng_seed", prng_seed, 0 },
8667ca439a49Sdrh { "extra_schema_checks", extra_schema_checks, 0},
866809fe6143Sdrh { "database_never_corrupt", database_never_corrupt, 0},
866909fe6143Sdrh { "database_may_be_corrupt", database_may_be_corrupt, 0},
8670f58ee7f1Sdrh { "optimization_control", optimization_control,0},
867180084ca8Sdrh #if SQLITE_OS_WIN
867280084ca8Sdrh { "lock_win32_file", win32_file_lock, 0 },
86733741827eSmistachkin { "exists_win32_path", win32_exists_path, 0 },
86743741827eSmistachkin { "find_win32_file", win32_find_file, 0 },
86753741827eSmistachkin { "delete_win32_file", win32_delete_file, 0 },
86763741827eSmistachkin { "make_win32_dir", win32_mkdir, 0 },
86773741827eSmistachkin { "remove_win32_dir", win32_rmdir, 0 },
867880084ca8Sdrh #endif
8679a2c8a95bSdrh { "tcl_objproc", runAsObjProc, 0 },
868093aed5a1Sdrh
868104f2e68dSdanielk1977 /* sqlite3_column_*() API */
868204f2e68dSdanielk1977 { "sqlite3_column_count", test_column_count ,0 },
868304f2e68dSdanielk1977 { "sqlite3_data_count", test_data_count ,0 },
868404f2e68dSdanielk1977 { "sqlite3_column_type", test_column_type ,0 },
8685ea61b2c4Sdanielk1977 { "sqlite3_column_blob", test_column_blob ,0 },
868604f2e68dSdanielk1977 { "sqlite3_column_double", test_column_double ,0 },
868704f2e68dSdanielk1977 { "sqlite3_column_int64", test_column_int64 ,0 },
868844a376f6Sdanielk1977 { "sqlite3_column_text", test_stmt_utf8, (void*)sqlite3_column_text },
868944a376f6Sdanielk1977 { "sqlite3_column_name", test_stmt_utf8, (void*)sqlite3_column_name },
869044a376f6Sdanielk1977 { "sqlite3_column_int", test_stmt_int, (void*)sqlite3_column_int },
869144a376f6Sdanielk1977 { "sqlite3_column_bytes", test_stmt_int, (void*)sqlite3_column_bytes},
86923f913576Sdrh #ifndef SQLITE_OMIT_DECLTYPE
869344a376f6Sdanielk1977 { "sqlite3_column_decltype",test_stmt_utf8,(void*)sqlite3_column_decltype},
86943f913576Sdrh #endif
86954b1ae99dSdanielk1977 #ifdef SQLITE_ENABLE_COLUMN_METADATA
869644a376f6Sdanielk1977 { "sqlite3_column_database_name",test_stmt_utf8,(void*)sqlite3_column_database_name},
869744a376f6Sdanielk1977 { "sqlite3_column_table_name",test_stmt_utf8,(void*)sqlite3_column_table_name},
869844a376f6Sdanielk1977 { "sqlite3_column_origin_name",test_stmt_utf8,(void*)sqlite3_column_origin_name},
86994b1ae99dSdanielk1977 #endif
8700955de52cSdanielk1977
87016c62608fSdrh #ifndef SQLITE_OMIT_UTF16
870244a376f6Sdanielk1977 { "sqlite3_column_bytes16", test_stmt_int, (void*)sqlite3_column_bytes16 },
870344a376f6Sdanielk1977 { "sqlite3_column_text16", test_stmt_utf16, (void*)sqlite3_column_text16},
870444a376f6Sdanielk1977 { "sqlite3_column_name16", test_stmt_utf16, (void*)sqlite3_column_name16},
87057d9bd4e1Sdrh { "add_alignment_test_collations", add_alignment_test_collations, 0 },
87063f913576Sdrh #ifndef SQLITE_OMIT_DECLTYPE
870744a376f6Sdanielk1977 { "sqlite3_column_decltype16",test_stmt_utf16,(void*)sqlite3_column_decltype16},
87083f913576Sdrh #endif
87094b1ae99dSdanielk1977 #ifdef SQLITE_ENABLE_COLUMN_METADATA
8710955de52cSdanielk1977 {"sqlite3_column_database_name16",
87117da5fcb0Sdrh test_stmt_utf16, (void*)sqlite3_column_database_name16},
871244a376f6Sdanielk1977 {"sqlite3_column_table_name16", test_stmt_utf16, (void*)sqlite3_column_table_name16},
871344a376f6Sdanielk1977 {"sqlite3_column_origin_name16", test_stmt_utf16, (void*)sqlite3_column_origin_name16},
87146c62608fSdrh #endif
87154b1ae99dSdanielk1977 #endif
8716a393c036Sdanielk1977 { "sqlite3_create_collation_v2", test_create_collation_v2, 0 },
87176b456a2bSdanielk1977 { "sqlite3_global_recover", test_global_recover, 0 },
871880788d8bSdrh { "working_64bit_int", working_64bit_int, 0 },
87199bc5449fSdrh { "vfs_unlink_test", vfs_unlink_test, 0 },
8720c8d75674Sdrh { "vfs_initfail_test", vfs_initfail_test, 0 },
8721a2820970Sdrh { "vfs_unregister_all", vfs_unregister_all, 0 },
8722a2820970Sdrh { "vfs_reregister_all", vfs_reregister_all, 0 },
872355176259Sdrh { "file_control_test", file_control_test, 0 },
8724aebf413dSaswift { "file_control_lasterrno_test", file_control_lasterrno_test, 0 },
8725aebf413dSaswift { "file_control_lockproxy_test", file_control_lockproxy_test, 0 },
87266e09d69cSdan { "file_control_chunksize_test", file_control_chunksize_test, 0 },
8727661d71afSdan { "file_control_sizehint_test", file_control_sizehint_test, 0 },
8728ea99a31cSdrh { "file_control_data_version", file_control_data_version, 0 },
87296b98d67bSmistachkin #if SQLITE_OS_WIN
8730d0cdf012Sdrh { "file_control_win32_av_retry", file_control_win32_av_retry, 0 },
87311b361ff3Smistachkin { "file_control_win32_get_handle", file_control_win32_get_handle, 0 },
87326b98d67bSmistachkin { "file_control_win32_set_handle", file_control_win32_set_handle, 0 },
87336b98d67bSmistachkin #endif
8734253cea5cSdrh { "file_control_persist_wal", file_control_persist_wal, 0 },
8735cb15f35fSdrh { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
8736de60fc2dSdrh { "file_control_vfsname", file_control_vfsname, 0 },
8737c30b78f6Sdan { "file_control_reservebytes", file_control_reservebytes, 0 },
8738696b33e6Sdrh { "file_control_tempfilename", file_control_tempfilename, 0 },
8739aecc04d6Sdan { "file_control_external_reader", file_control_external_reader, 0 },
8740e339d65aSdanielk1977 { "sqlite3_vfs_list", vfs_list, 0 },
8741d2199f0fSdan { "sqlite3_create_function_v2", test_create_function_v2, 0 },
874204f2e68dSdanielk1977
87439a1d0abeSdanielk1977 /* Functions from os.h */
87445436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
87454e6af134Sdanielk1977 { "add_test_collate", test_collate, 0 },
8746312d6b36Sdanielk1977 { "add_test_collate_needed", test_collate_needed, 0 },
8747c8e9a2dfSdanielk1977 { "add_test_function", test_function, 0 },
874838fdead8Sdan { "add_test_utf16bin_collate", test_utf16bin_collate, 0 },
87495436dc2dSdrh #endif
8750312d6b36Sdanielk1977 { "sqlite3_test_errstr", test_errstr, 0 },
875192febd92Sdrh { "tcl_variable_type", tcl_variable_type, 0 },
8752aef0bf64Sdanielk1977 #ifndef SQLITE_OMIT_SHARED_CACHE
87536f7adc8aSdrh { "sqlite3_enable_shared_cache", test_enable_shared, 0 },
875416a9b836Sdrh { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0},
8755aef0bf64Sdanielk1977 #endif
8756161fb796Sdanielk1977 { "sqlite3_libversion_number", test_libversion_number, 0 },
8757deb802cdSdanielk1977 { "sqlite3_table_column_metadata", test_table_column_metadata, 0 },
8758dcbb5d3fSdanielk1977 #ifndef SQLITE_OMIT_INCRBLOB
87594e76cc36Sdan { "sqlite3_blob_reopen", test_blob_reopen, 0 },
8760dcbb5d3fSdanielk1977 #endif
8761062d4cb0Sdanielk1977 { "pcache_stats", test_pcache_stats, 0 },
8762404ca075Sdanielk1977 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
8763404ca075Sdanielk1977 { "sqlite3_unlock_notify", test_unlock_notify, 0 },
8764404ca075Sdanielk1977 #endif
876587c1fe1bSdan { "sqlite3_wal_checkpoint", test_wal_checkpoint, 0 },
87669c5e3680Sdan { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0 },
87679af10620Sdan { "sqlite3_wal_autocheckpoint",test_wal_autocheckpoint, 0 },
8768eb8763d7Sdan { "test_sqlite3_log", test_sqlite3_log, 0 },
8769bb201344Sshaneh #ifndef SQLITE_OMIT_EXPLAIN
877091da6b83Sdan { "print_explain_query_plan", test_print_eqp, 0 },
8771bb201344Sshaneh #endif
8772c17d696cSdan { "sqlite3_test_control", test_test_control },
8773daf9a5a4Smistachkin #if SQLITE_OS_UNIX
8774a72014faSdan { "getrusage", test_getrusage },
8775daf9a5a4Smistachkin #endif
8776248f2be9Sdrh { "load_static_extension", tclLoadStaticExtensionCmd },
87770d51def2Sdan { "sorter_test_fakeheap", sorter_test_fakeheap },
8778dfea4533Sdan { "sorter_test_sort4_helper", sorter_test_sort4_helper },
8779d39c40ffSdrh #ifdef SQLITE_USER_AUTHENTICATION
8780d39c40ffSdrh { "sqlite3_user_authenticate", test_user_authenticate, 0 },
8781d39c40ffSdrh { "sqlite3_user_add", test_user_add, 0 },
8782d39c40ffSdrh { "sqlite3_user_change", test_user_change, 0 },
8783d39c40ffSdrh { "sqlite3_user_delete", test_user_delete, 0 },
8784d39c40ffSdrh #endif
878504489b6dSdan #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
878604489b6dSdan { "sqlite3_stmt_scanstatus", test_stmt_scanstatus, 0 },
878704489b6dSdan { "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset, 0 },
878804489b6dSdan #endif
8789d83f7ca1Sdan #ifdef SQLITE_ENABLE_SQLLOG
8790d83f7ca1Sdan { "sqlite3_config_sqllog", test_config_sqllog, 0 },
8791d83f7ca1Sdan #endif
8792e4e416e8Sdan { "vfs_current_time_int64", vfsCurrentTimeInt64, 0 },
8793fc1acf33Sdan #ifdef SQLITE_ENABLE_SNAPSHOT
8794fc1acf33Sdan { "sqlite3_snapshot_get", test_snapshot_get, 0 },
8795fc1acf33Sdan { "sqlite3_snapshot_open", test_snapshot_open, 0 },
8796fc1acf33Sdan { "sqlite3_snapshot_free", test_snapshot_free, 0 },
8797ad2d5bafSdan { "sqlite3_snapshot_cmp", test_snapshot_cmp, 0 },
87981158498dSdan { "sqlite3_snapshot_recover", test_snapshot_recover, 0 },
879925accbcaSdan { "sqlite3_snapshot_get_blob", test_snapshot_get_blob, 0 },
880025accbcaSdan { "sqlite3_snapshot_open_blob", test_snapshot_open_blob, 0 },
880125accbcaSdan { "sqlite3_snapshot_cmp_blob", test_snapshot_cmp_blob, 0 },
8802fc1acf33Sdan #endif
8803000f95b1Sdan { "sqlite3_delete_database", test_delete_database, 0 },
88044da30f88Sdan { "atomic_batch_write", test_atomic_batch_write, 0 },
8805460f1fa5Sdan { "sqlite3_mmap_warm", test_mmap_warm, 0 },
88062e3a5a81Sdan { "sqlite3_config_sorterref", test_config_sorterref, 0 },
88071bbfc674Sdrh { "sqlite3_autovacuum_pages", test_autovacuum_pages, 0 },
8808f7e74904Sdrh { "decode_hexdb", test_decode_hexdb, 0 },
880991faeec8Sdan { "test_write_db", test_write_db, 0 },
8810c30b78f6Sdan { "sqlite3_register_cksumvfs", test_register_cksumvfs, 0 },
8811c30b78f6Sdan { "sqlite3_unregister_cksumvfs", test_unregister_cksumvfs, 0 },
881251e3d8e2Sdanielk1977 };
88131398ad36Sdrh static int bitmask_size = sizeof(Bitmask)*8;
88142ab410aaSdrh static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
8815c2eef3b3Sdrh int i;
8816b851b2c9Sdrh extern int sqlite3_sync_count, sqlite3_fullsync_count;
8817af6df11fSdrh extern int sqlite3_opentemp_count;
881855ef4d97Sdrh extern int sqlite3_like_count;
8819dd73521bSdrh extern int sqlite3_xferopt_count;
8820538f570cSdrh extern int sqlite3_pager_readdb_count;
8821538f570cSdrh extern int sqlite3_pager_writedb_count;
8822538f570cSdrh extern int sqlite3_pager_writej_count;
882329bafeabSdanielk1977 #if SQLITE_OS_WIN
8824202cb641Smistachkin extern LONG volatile sqlite3_os_type;
8825c0929987Sdrh #endif
88268b3d990bSdrh #ifdef SQLITE_DEBUG
88277b0ab210Sdrh extern u32 sqlite3WhereTrace;
88283a00f907Smlcreech extern int sqlite3OSTrace;
8829c74c3334Sdrh extern int sqlite3WalTrace;
8830549c8b68Sdrh #endif
8831549c8b68Sdrh #ifdef SQLITE_TEST
883233e89035Sdanielk1977 #ifdef SQLITE_ENABLE_FTS3
883333e89035Sdanielk1977 extern int sqlite3_fts3_enable_parentheses;
883433e89035Sdanielk1977 #endif
883548083ceeSdrh #endif
8836c2eef3b3Sdrh
8837c2eef3b3Sdrh for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
8838c2eef3b3Sdrh Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
8839c2eef3b3Sdrh }
884051e3d8e2Sdanielk1977 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
8841c572ef7fSdanielk1977 Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
8842c572ef7fSdanielk1977 aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
884351e3d8e2Sdanielk1977 }
88446490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_search_count",
88456f8a503dSdanielk1977 (char*)&sqlite3_search_count, TCL_LINK_INT);
88460ff297eaSdan Tcl_LinkVar(interp, "sqlite_found_count",
88470ff297eaSdan (char*)&sqlite3_found_count, TCL_LINK_INT);
88486bf89570Sdrh Tcl_LinkVar(interp, "sqlite_sort_count",
88496bf89570Sdrh (char*)&sqlite3_sort_count, TCL_LINK_INT);
8850ae7e151aSdrh Tcl_LinkVar(interp, "sqlite3_max_blobsize",
8851ae7e151aSdrh (char*)&sqlite3_max_blobsize, TCL_LINK_INT);
885255ef4d97Sdrh Tcl_LinkVar(interp, "sqlite_like_count",
885355ef4d97Sdrh (char*)&sqlite3_like_count, TCL_LINK_INT);
88546490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_interrupt_count",
88556f8a503dSdanielk1977 (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
88566490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_open_file_count",
88576f8a503dSdanielk1977 (char*)&sqlite3_open_file_count, TCL_LINK_INT);
88586490bebdSdanielk1977 Tcl_LinkVar(interp, "sqlite_current_time",
88596f8a503dSdanielk1977 (char*)&sqlite3_current_time, TCL_LINK_INT);
886084a2bf67Sdrh #if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
8861aebf413dSaswift Tcl_LinkVar(interp, "sqlite_hostid_num",
8862aebf413dSaswift (char*)&sqlite3_hostid_num, TCL_LINK_INT);
8863aabbed22Spweilbacher #endif
8864dd73521bSdrh Tcl_LinkVar(interp, "sqlite3_xferopt_count",
8865dd73521bSdrh (char*)&sqlite3_xferopt_count, TCL_LINK_INT);
8866538f570cSdrh Tcl_LinkVar(interp, "sqlite3_pager_readdb_count",
8867538f570cSdrh (char*)&sqlite3_pager_readdb_count, TCL_LINK_INT);
8868538f570cSdrh Tcl_LinkVar(interp, "sqlite3_pager_writedb_count",
8869538f570cSdrh (char*)&sqlite3_pager_writedb_count, TCL_LINK_INT);
8870538f570cSdrh Tcl_LinkVar(interp, "sqlite3_pager_writej_count",
8871538f570cSdrh (char*)&sqlite3_pager_writej_count, TCL_LINK_INT);
88724b2688abSdanielk1977 #ifndef SQLITE_OMIT_UTF16
88737d9bd4e1Sdrh Tcl_LinkVar(interp, "unaligned_string_counter",
88747d9bd4e1Sdrh (char*)&unaligned_string_counter, TCL_LINK_INT);
88754b2688abSdanielk1977 #endif
8876268803a9Sdrh #ifndef SQLITE_OMIT_UTF16
8877268803a9Sdrh Tcl_LinkVar(interp, "sqlite_last_needed_collation",
8878268803a9Sdrh (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
8879268803a9Sdrh #endif
888029bafeabSdanielk1977 #if SQLITE_OS_WIN
8881c0929987Sdrh Tcl_LinkVar(interp, "sqlite_os_type",
8882202cb641Smistachkin (char*)&sqlite3_os_type, TCL_LINK_LONG);
8883c0929987Sdrh #endif
8884549c8b68Sdrh #ifdef SQLITE_TEST
88856fa978daSdrh {
88866fa978daSdrh static const char *query_plan = "*** OBSOLETE VARIABLE ***";
8887549c8b68Sdrh Tcl_LinkVar(interp, "sqlite_query_plan",
8888549c8b68Sdrh (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
88896fa978daSdrh }
8890549c8b68Sdrh #endif
88918b3d990bSdrh #ifdef SQLITE_DEBUG
889248083ceeSdrh Tcl_LinkVar(interp, "sqlite_where_trace",
88933a00f907Smlcreech (char*)&sqlite3WhereTrace, TCL_LINK_INT);
889473be5013Sdrh Tcl_LinkVar(interp, "sqlite_os_trace",
88953a00f907Smlcreech (char*)&sqlite3OSTrace, TCL_LINK_INT);
889638e1a279Sdan #ifndef SQLITE_OMIT_WAL
8897c74c3334Sdrh Tcl_LinkVar(interp, "sqlite_wal_trace",
8898c74c3334Sdrh (char*)&sqlite3WalTrace, TCL_LINK_INT);
88998b3d990bSdrh #endif
890038e1a279Sdan #endif
8901cbe21be3Sdanielk1977 #ifndef SQLITE_OMIT_DISKIO
8902af6df11fSdrh Tcl_LinkVar(interp, "sqlite_opentemp_count",
8903af6df11fSdrh (char*)&sqlite3_opentemp_count, TCL_LINK_INT);
8904cbe21be3Sdanielk1977 #endif
89057c972decSdrh Tcl_LinkVar(interp, "sqlite_static_bind_value",
89067c972decSdrh (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
8907f0313813Sdrh Tcl_LinkVar(interp, "sqlite_static_bind_nbyte",
8908f0313813Sdrh (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT);
8909ab3f9feaSdrh Tcl_LinkVar(interp, "sqlite_temp_directory",
8910effd02bcSdrh (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
8911a112d140Smistachkin Tcl_LinkVar(interp, "sqlite_data_directory",
8912a112d140Smistachkin (char*)&sqlite3_data_directory, TCL_LINK_STRING);
89131398ad36Sdrh Tcl_LinkVar(interp, "bitmask_size",
89141398ad36Sdrh (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
89152ab410aaSdrh Tcl_LinkVar(interp, "longdouble_size",
89162ab410aaSdrh (char*)&longdouble_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
8917b851b2c9Sdrh Tcl_LinkVar(interp, "sqlite_sync_count",
8918b851b2c9Sdrh (char*)&sqlite3_sync_count, TCL_LINK_INT);
8919b851b2c9Sdrh Tcl_LinkVar(interp, "sqlite_fullsync_count",
8920b851b2c9Sdrh (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
89215e431beaSdrh #if defined(SQLITE_ENABLE_TREETRACE)
89225e431beaSdrh Tcl_LinkVar(interp, "sqlite3_unsupported_treetrace",
89235e431beaSdrh (char*)&sqlite3TreeTrace, TCL_LINK_INT);
892486fb6e17Sdan #endif
8925d1fa7bcaSdrh #if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST)
892633e89035Sdanielk1977 Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses",
892733e89035Sdanielk1977 (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT);
892833e89035Sdanielk1977 #endif
8929d1bf3512Sdrh return TCL_OK;
8930d1bf3512Sdrh }
8931