Annotation of embedaddon/sqlite3/src/test1.c, revision 1.1.1.1
1.1 misho 1: /*
2: ** 2001 September 15
3: **
4: ** The author disclaims copyright to this source code. In place of
5: ** a legal notice, here is a blessing:
6: **
7: ** May you do good and not evil.
8: ** May you find forgiveness for yourself and forgive others.
9: ** May you share freely, never taking more than you give.
10: **
11: *************************************************************************
12: ** Code for testing all sorts of SQLite interfaces. This code
13: ** is not included in the SQLite library. It is used for automated
14: ** testing of the SQLite library.
15: */
16: #include "sqliteInt.h"
17: #include "vdbeInt.h"
18: #include "tcl.h"
19: #include <stdlib.h>
20: #include <string.h>
21:
22: /*
23: ** This is a copy of the first part of the SqliteDb structure in
24: ** tclsqlite.c. We need it here so that the get_sqlite_pointer routine
25: ** can extract the sqlite3* pointer from an existing Tcl SQLite
26: ** connection.
27: */
28: struct SqliteDb {
29: sqlite3 *db;
30: };
31:
32: /*
33: ** Convert text generated by the "%p" conversion format back into
34: ** a pointer.
35: */
36: static int testHexToInt(int h){
37: if( h>='0' && h<='9' ){
38: return h - '0';
39: }else if( h>='a' && h<='f' ){
40: return h - 'a' + 10;
41: }else{
42: assert( h>='A' && h<='F' );
43: return h - 'A' + 10;
44: }
45: }
46: void *sqlite3TestTextToPtr(const char *z){
47: void *p;
48: u64 v;
49: u32 v2;
50: if( z[0]=='0' && z[1]=='x' ){
51: z += 2;
52: }
53: v = 0;
54: while( *z ){
55: v = (v<<4) + testHexToInt(*z);
56: z++;
57: }
58: if( sizeof(p)==sizeof(v) ){
59: memcpy(&p, &v, sizeof(p));
60: }else{
61: assert( sizeof(p)==sizeof(v2) );
62: v2 = (u32)v;
63: memcpy(&p, &v2, sizeof(p));
64: }
65: return p;
66: }
67:
68:
69: /*
70: ** A TCL command that returns the address of the sqlite* pointer
71: ** for an sqlite connection instance. Bad things happen if the
72: ** input is not an sqlite connection.
73: */
74: static int get_sqlite_pointer(
75: void * clientData,
76: Tcl_Interp *interp,
77: int objc,
78: Tcl_Obj *CONST objv[]
79: ){
80: struct SqliteDb *p;
81: Tcl_CmdInfo cmdInfo;
82: char zBuf[100];
83: if( objc!=2 ){
84: Tcl_WrongNumArgs(interp, 1, objv, "SQLITE-CONNECTION");
85: return TCL_ERROR;
86: }
87: if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
88: Tcl_AppendResult(interp, "command not found: ",
89: Tcl_GetString(objv[1]), (char*)0);
90: return TCL_ERROR;
91: }
92: p = (struct SqliteDb*)cmdInfo.objClientData;
93: sprintf(zBuf, "%p", p->db);
94: if( strncmp(zBuf,"0x",2) ){
95: sprintf(zBuf, "0x%p", p->db);
96: }
97: Tcl_AppendResult(interp, zBuf, 0);
98: return TCL_OK;
99: }
100:
101: /*
102: ** Decode a pointer to an sqlite3 object.
103: */
104: int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
105: struct SqliteDb *p;
106: Tcl_CmdInfo cmdInfo;
107: if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){
108: p = (struct SqliteDb*)cmdInfo.objClientData;
109: *ppDb = p->db;
110: }else{
111: *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA);
112: }
113: return TCL_OK;
114: }
115:
116:
117: const char *sqlite3TestErrorName(int rc){
118: const char *zName = 0;
119: switch( rc ){
120: case SQLITE_OK: zName = "SQLITE_OK"; break;
121: case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
122: case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break;
123: case SQLITE_PERM: zName = "SQLITE_PERM"; break;
124: case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
125: case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
126: case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break;
127: case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE";break;
128: case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
129: case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
130: case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
131: case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
132: case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
133: case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break;
134: case SQLITE_FULL: zName = "SQLITE_FULL"; break;
135: case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
136: case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
137: case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
138: case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break;
139: case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break;
140: case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break;
141: case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break;
142: case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break;
143: case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break;
144: case SQLITE_AUTH: zName = "SQLITE_AUTH"; break;
145: case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break;
146: case SQLITE_RANGE: zName = "SQLITE_RANGE"; break;
147: case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break;
148: case SQLITE_ROW: zName = "SQLITE_ROW"; break;
149: case SQLITE_DONE: zName = "SQLITE_DONE"; break;
150: case SQLITE_IOERR_READ: zName = "SQLITE_IOERR_READ"; break;
151: case SQLITE_IOERR_SHORT_READ: zName = "SQLITE_IOERR_SHORT_READ"; break;
152: case SQLITE_IOERR_WRITE: zName = "SQLITE_IOERR_WRITE"; break;
153: case SQLITE_IOERR_FSYNC: zName = "SQLITE_IOERR_FSYNC"; break;
154: case SQLITE_IOERR_DIR_FSYNC: zName = "SQLITE_IOERR_DIR_FSYNC"; break;
155: case SQLITE_IOERR_TRUNCATE: zName = "SQLITE_IOERR_TRUNCATE"; break;
156: case SQLITE_IOERR_FSTAT: zName = "SQLITE_IOERR_FSTAT"; break;
157: case SQLITE_IOERR_UNLOCK: zName = "SQLITE_IOERR_UNLOCK"; break;
158: case SQLITE_IOERR_RDLOCK: zName = "SQLITE_IOERR_RDLOCK"; break;
159: case SQLITE_IOERR_DELETE: zName = "SQLITE_IOERR_DELETE"; break;
160: case SQLITE_IOERR_BLOCKED: zName = "SQLITE_IOERR_BLOCKED"; break;
161: case SQLITE_IOERR_NOMEM: zName = "SQLITE_IOERR_NOMEM"; break;
162: case SQLITE_IOERR_ACCESS: zName = "SQLITE_IOERR_ACCESS"; break;
163: case SQLITE_IOERR_CHECKRESERVEDLOCK:
164: zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
165: case SQLITE_IOERR_LOCK: zName = "SQLITE_IOERR_LOCK"; break;
166: case SQLITE_CORRUPT_VTAB: zName = "SQLITE_CORRUPT_VTAB"; break;
167: case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break;
168: case SQLITE_READONLY_CANTLOCK: zName = "SQLITE_READONLY_CANTLOCK"; break;
169: default: zName = "SQLITE_Unknown"; break;
170: }
171: return zName;
172: }
173: #define t1ErrorName sqlite3TestErrorName
174:
175: /*
176: ** Convert an sqlite3_stmt* into an sqlite3*. This depends on the
177: ** fact that the sqlite3* is the first field in the Vdbe structure.
178: */
179: #define StmtToDb(X) sqlite3_db_handle(X)
180:
181: /*
182: ** Check a return value to make sure it agrees with the results
183: ** from sqlite3_errcode.
184: */
185: int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
186: if( sqlite3_threadsafe()==0 && rc!=SQLITE_MISUSE && rc!=SQLITE_OK
187: && sqlite3_errcode(db)!=rc ){
188: char zBuf[200];
189: int r2 = sqlite3_errcode(db);
190: sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)",
191: t1ErrorName(rc), rc, t1ErrorName(r2), r2);
192: Tcl_ResetResult(interp);
193: Tcl_AppendResult(interp, zBuf, 0);
194: return 1;
195: }
196: return 0;
197: }
198:
199: /*
200: ** Decode a pointer to an sqlite3_stmt object.
201: */
202: static int getStmtPointer(
203: Tcl_Interp *interp,
204: const char *zArg,
205: sqlite3_stmt **ppStmt
206: ){
207: *ppStmt = (sqlite3_stmt*)sqlite3TestTextToPtr(zArg);
208: return TCL_OK;
209: }
210:
211: /*
212: ** Generate a text representation of a pointer that can be understood
213: ** by the getDbPointer and getVmPointer routines above.
214: **
215: ** The problem is, on some machines (Solaris) if you do a printf with
216: ** "%p" you cannot turn around and do a scanf with the same "%p" and
217: ** get your pointer back. You have to prepend a "0x" before it will
218: ** work. Or at least that is what is reported to me (drh). But this
219: ** behavior varies from machine to machine. The solution used her is
220: ** to test the string right after it is generated to see if it can be
221: ** understood by scanf, and if not, try prepending an "0x" to see if
222: ** that helps. If nothing works, a fatal error is generated.
223: */
224: int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
225: sqlite3_snprintf(100, zPtr, "%p", p);
226: return TCL_OK;
227: }
228:
229: /*
230: ** The callback routine for sqlite3_exec_printf().
231: */
232: static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
233: Tcl_DString *str = (Tcl_DString*)pArg;
234: int i;
235:
236: if( Tcl_DStringLength(str)==0 ){
237: for(i=0; i<argc; i++){
238: Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
239: }
240: }
241: for(i=0; i<argc; i++){
242: Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
243: }
244: return 0;
245: }
246:
247: /*
248: ** The I/O tracing callback.
249: */
250: #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
251: static FILE *iotrace_file = 0;
252: static void io_trace_callback(const char *zFormat, ...){
253: va_list ap;
254: va_start(ap, zFormat);
255: vfprintf(iotrace_file, zFormat, ap);
256: va_end(ap);
257: fflush(iotrace_file);
258: }
259: #endif
260:
261: /*
262: ** Usage: io_trace FILENAME
263: **
264: ** Turn I/O tracing on or off. If FILENAME is not an empty string,
265: ** I/O tracing begins going into FILENAME. If FILENAME is an empty
266: ** string, I/O tracing is turned off.
267: */
268: static int test_io_trace(
269: void *NotUsed,
270: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
271: int argc, /* Number of arguments */
272: char **argv /* Text of each argument */
273: ){
274: #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
275: if( argc!=2 ){
276: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
277: " FILENAME\"", 0);
278: return TCL_ERROR;
279: }
280: if( iotrace_file ){
281: if( iotrace_file!=stdout && iotrace_file!=stderr ){
282: fclose(iotrace_file);
283: }
284: iotrace_file = 0;
285: sqlite3IoTrace = 0;
286: }
287: if( argv[1][0] ){
288: if( strcmp(argv[1],"stdout")==0 ){
289: iotrace_file = stdout;
290: }else if( strcmp(argv[1],"stderr")==0 ){
291: iotrace_file = stderr;
292: }else{
293: iotrace_file = fopen(argv[1], "w");
294: }
295: sqlite3IoTrace = io_trace_callback;
296: }
297: #endif
298: return TCL_OK;
299: }
300:
301:
302: /*
303: ** Usage: sqlite3_exec_printf DB FORMAT STRING
304: **
305: ** Invoke the sqlite3_exec_printf() interface using the open database
306: ** DB. The SQL is the string FORMAT. The format string should contain
307: ** one %s or %q. STRING is the value inserted into %s or %q.
308: */
309: static int test_exec_printf(
310: void *NotUsed,
311: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
312: int argc, /* Number of arguments */
313: char **argv /* Text of each argument */
314: ){
315: sqlite3 *db;
316: Tcl_DString str;
317: int rc;
318: char *zErr = 0;
319: char *zSql;
320: char zBuf[30];
321: if( argc!=4 ){
322: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
323: " DB FORMAT STRING", 0);
324: return TCL_ERROR;
325: }
326: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
327: Tcl_DStringInit(&str);
328: zSql = sqlite3_mprintf(argv[2], argv[3]);
329: rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
330: sqlite3_free(zSql);
331: sprintf(zBuf, "%d", rc);
332: Tcl_AppendElement(interp, zBuf);
333: Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
334: Tcl_DStringFree(&str);
335: if( zErr ) sqlite3_free(zErr);
336: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
337: return TCL_OK;
338: }
339:
340: /*
341: ** Usage: sqlite3_exec_hex DB HEX
342: **
343: ** Invoke the sqlite3_exec() on a string that is obtained by translating
344: ** HEX into ASCII. Most characters are translated as is. %HH becomes
345: ** a hex character.
346: */
347: static int test_exec_hex(
348: void *NotUsed,
349: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
350: int argc, /* Number of arguments */
351: char **argv /* Text of each argument */
352: ){
353: sqlite3 *db;
354: Tcl_DString str;
355: int rc, i, j;
356: char *zErr = 0;
357: char *zHex;
358: char zSql[500];
359: char zBuf[30];
360: if( argc!=3 ){
361: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
362: " DB HEX", 0);
363: return TCL_ERROR;
364: }
365: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
366: zHex = argv[2];
367: for(i=j=0; i<sizeof(zSql) && zHex[j]; i++, j++){
368: if( zHex[j]=='%' && zHex[j+2] && zHex[j+2] ){
369: zSql[i] = (testHexToInt(zHex[j+1])<<4) + testHexToInt(zHex[j+2]);
370: j += 2;
371: }else{
372: zSql[i] = zHex[j];
373: }
374: }
375: zSql[i] = 0;
376: Tcl_DStringInit(&str);
377: rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
378: sprintf(zBuf, "%d", rc);
379: Tcl_AppendElement(interp, zBuf);
380: Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
381: Tcl_DStringFree(&str);
382: if( zErr ) sqlite3_free(zErr);
383: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
384: return TCL_OK;
385: }
386:
387: /*
388: ** Usage: db_enter DB
389: ** db_leave DB
390: **
391: ** Enter or leave the mutex on a database connection.
392: */
393: static int db_enter(
394: void *NotUsed,
395: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
396: int argc, /* Number of arguments */
397: char **argv /* Text of each argument */
398: ){
399: sqlite3 *db;
400: if( argc!=2 ){
401: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
402: " DB", 0);
403: return TCL_ERROR;
404: }
405: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
406: sqlite3_mutex_enter(db->mutex);
407: return TCL_OK;
408: }
409: static int db_leave(
410: void *NotUsed,
411: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
412: int argc, /* Number of arguments */
413: char **argv /* Text of each argument */
414: ){
415: sqlite3 *db;
416: if( argc!=2 ){
417: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
418: " DB", 0);
419: return TCL_ERROR;
420: }
421: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
422: sqlite3_mutex_leave(db->mutex);
423: return TCL_OK;
424: }
425:
426: /*
427: ** Usage: sqlite3_exec DB SQL
428: **
429: ** Invoke the sqlite3_exec interface using the open database DB
430: */
431: static int test_exec(
432: void *NotUsed,
433: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
434: int argc, /* Number of arguments */
435: char **argv /* Text of each argument */
436: ){
437: sqlite3 *db;
438: Tcl_DString str;
439: int rc;
440: char *zErr = 0;
441: char *zSql;
442: int i, j;
443: char zBuf[30];
444: if( argc!=3 ){
445: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
446: " DB SQL", 0);
447: return TCL_ERROR;
448: }
449: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
450: Tcl_DStringInit(&str);
451: zSql = sqlite3_mprintf("%s", argv[2]);
452: for(i=j=0; zSql[i];){
453: if( zSql[i]=='%' ){
454: zSql[j++] = (testHexToInt(zSql[i+1])<<4) + testHexToInt(zSql[i+2]);
455: i += 3;
456: }else{
457: zSql[j++] = zSql[i++];
458: }
459: }
460: zSql[j] = 0;
461: rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
462: sqlite3_free(zSql);
463: sprintf(zBuf, "%d", rc);
464: Tcl_AppendElement(interp, zBuf);
465: Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
466: Tcl_DStringFree(&str);
467: if( zErr ) sqlite3_free(zErr);
468: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
469: return TCL_OK;
470: }
471:
472: /*
473: ** Usage: sqlite3_exec_nr DB SQL
474: **
475: ** Invoke the sqlite3_exec interface using the open database DB. Discard
476: ** all results
477: */
478: static int test_exec_nr(
479: void *NotUsed,
480: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
481: int argc, /* Number of arguments */
482: char **argv /* Text of each argument */
483: ){
484: sqlite3 *db;
485: int rc;
486: char *zErr = 0;
487: if( argc!=3 ){
488: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
489: " DB SQL", 0);
490: return TCL_ERROR;
491: }
492: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
493: rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
494: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
495: return TCL_OK;
496: }
497:
498: /*
499: ** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ...
500: **
501: ** Test the %z format of sqlite_mprintf(). Use multiple mprintf() calls to
502: ** concatenate arg0 through argn using separator as the separator.
503: ** Return the result.
504: */
505: static int test_mprintf_z(
506: void *NotUsed,
507: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
508: int argc, /* Number of arguments */
509: char **argv /* Text of each argument */
510: ){
511: char *zResult = 0;
512: int i;
513:
514: for(i=2; i<argc && (i==2 || zResult); i++){
515: zResult = sqlite3_mprintf("%z%s%s", zResult, argv[1], argv[i]);
516: }
517: Tcl_AppendResult(interp, zResult, 0);
518: sqlite3_free(zResult);
519: return TCL_OK;
520: }
521:
522: /*
523: ** Usage: sqlite3_mprintf_n_test STRING
524: **
525: ** Test the %n format of sqlite_mprintf(). Return the length of the
526: ** input string.
527: */
528: static int test_mprintf_n(
529: void *NotUsed,
530: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
531: int argc, /* Number of arguments */
532: char **argv /* Text of each argument */
533: ){
534: char *zStr;
535: int n = 0;
536: zStr = sqlite3_mprintf("%s%n", argv[1], &n);
537: sqlite3_free(zStr);
538: Tcl_SetObjResult(interp, Tcl_NewIntObj(n));
539: return TCL_OK;
540: }
541:
542: /*
543: ** Usage: sqlite3_snprintf_int SIZE FORMAT INT
544: **
545: ** Test the of sqlite3_snprintf() routine. SIZE is the size of the
546: ** output buffer in bytes. The maximum size is 100. FORMAT is the
547: ** format string. INT is a single integer argument. The FORMAT
548: ** string must require no more than this one integer argument. If
549: ** You pass in a format string that requires more than one argument,
550: ** bad things will happen.
551: */
552: static int test_snprintf_int(
553: void *NotUsed,
554: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
555: int argc, /* Number of arguments */
556: char **argv /* Text of each argument */
557: ){
558: char zStr[100];
559: int n = atoi(argv[1]);
560: const char *zFormat = argv[2];
561: int a1 = atoi(argv[3]);
562: if( n>sizeof(zStr) ) n = sizeof(zStr);
563: sqlite3_snprintf(sizeof(zStr), zStr, "abcdefghijklmnopqrstuvwxyz");
564: sqlite3_snprintf(n, zStr, zFormat, a1);
565: Tcl_AppendResult(interp, zStr, 0);
566: return TCL_OK;
567: }
568:
569: #ifndef SQLITE_OMIT_GET_TABLE
570:
571: /*
572: ** Usage: sqlite3_get_table_printf DB FORMAT STRING ?--no-counts?
573: **
574: ** Invoke the sqlite3_get_table_printf() interface using the open database
575: ** DB. The SQL is the string FORMAT. The format string should contain
576: ** one %s or %q. STRING is the value inserted into %s or %q.
577: */
578: static int test_get_table_printf(
579: void *NotUsed,
580: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
581: int argc, /* Number of arguments */
582: char **argv /* Text of each argument */
583: ){
584: sqlite3 *db;
585: Tcl_DString str;
586: int rc;
587: char *zErr = 0;
588: int nRow, nCol;
589: char **aResult;
590: int i;
591: char zBuf[30];
592: char *zSql;
593: int resCount = -1;
594: if( argc==5 ){
595: if( Tcl_GetInt(interp, argv[4], &resCount) ) return TCL_ERROR;
596: }
597: if( argc!=4 && argc!=5 ){
598: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
599: " DB FORMAT STRING ?COUNT?", 0);
600: return TCL_ERROR;
601: }
602: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
603: Tcl_DStringInit(&str);
604: zSql = sqlite3_mprintf(argv[2],argv[3]);
605: if( argc==5 ){
606: rc = sqlite3_get_table(db, zSql, &aResult, 0, 0, &zErr);
607: }else{
608: rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
609: resCount = (nRow+1)*nCol;
610: }
611: sqlite3_free(zSql);
612: sprintf(zBuf, "%d", rc);
613: Tcl_AppendElement(interp, zBuf);
614: if( rc==SQLITE_OK ){
615: if( argc==4 ){
616: sprintf(zBuf, "%d", nRow);
617: Tcl_AppendElement(interp, zBuf);
618: sprintf(zBuf, "%d", nCol);
619: Tcl_AppendElement(interp, zBuf);
620: }
621: for(i=0; i<resCount; i++){
622: Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
623: }
624: }else{
625: Tcl_AppendElement(interp, zErr);
626: }
627: sqlite3_free_table(aResult);
628: if( zErr ) sqlite3_free(zErr);
629: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
630: return TCL_OK;
631: }
632:
633: #endif /* SQLITE_OMIT_GET_TABLE */
634:
635:
636: /*
637: ** Usage: sqlite3_last_insert_rowid DB
638: **
639: ** Returns the integer ROWID of the most recent insert.
640: */
641: static int test_last_rowid(
642: void *NotUsed,
643: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
644: int argc, /* Number of arguments */
645: char **argv /* Text of each argument */
646: ){
647: sqlite3 *db;
648: char zBuf[30];
649:
650: if( argc!=2 ){
651: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
652: return TCL_ERROR;
653: }
654: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
655: sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db));
656: Tcl_AppendResult(interp, zBuf, 0);
657: return SQLITE_OK;
658: }
659:
660: /*
661: ** Usage: sqlite3_key DB KEY
662: **
663: ** Set the codec key.
664: */
665: static int test_key(
666: void *NotUsed,
667: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
668: int argc, /* Number of arguments */
669: char **argv /* Text of each argument */
670: ){
671: sqlite3 *db;
672: const char *zKey;
673: int nKey;
674: if( argc!=3 ){
675: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
676: " FILENAME\"", 0);
677: return TCL_ERROR;
678: }
679: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
680: zKey = argv[2];
681: nKey = strlen(zKey);
682: #ifdef SQLITE_HAS_CODEC
683: sqlite3_key(db, zKey, nKey);
684: #endif
685: return TCL_OK;
686: }
687:
688: /*
689: ** Usage: sqlite3_rekey DB KEY
690: **
691: ** Change the codec key.
692: */
693: static int test_rekey(
694: void *NotUsed,
695: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
696: int argc, /* Number of arguments */
697: char **argv /* Text of each argument */
698: ){
699: sqlite3 *db;
700: const char *zKey;
701: int nKey;
702: if( argc!=3 ){
703: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
704: " FILENAME\"", 0);
705: return TCL_ERROR;
706: }
707: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
708: zKey = argv[2];
709: nKey = strlen(zKey);
710: #ifdef SQLITE_HAS_CODEC
711: sqlite3_rekey(db, zKey, nKey);
712: #endif
713: return TCL_OK;
714: }
715:
716: /*
717: ** Usage: sqlite3_close DB
718: **
719: ** Closes the database opened by sqlite3_open.
720: */
721: static int sqlite_test_close(
722: void *NotUsed,
723: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
724: int argc, /* Number of arguments */
725: char **argv /* Text of each argument */
726: ){
727: sqlite3 *db;
728: int rc;
729: if( argc!=2 ){
730: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
731: " FILENAME\"", 0);
732: return TCL_ERROR;
733: }
734: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
735: rc = sqlite3_close(db);
736: Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
737: return TCL_OK;
738: }
739:
740: /*
741: ** Implementation of the x_coalesce() function.
742: ** Return the first argument non-NULL argument.
743: */
744: static void t1_ifnullFunc(
745: sqlite3_context *context,
746: int argc,
747: sqlite3_value **argv
748: ){
749: int i;
750: for(i=0; i<argc; i++){
751: if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
752: int n = sqlite3_value_bytes(argv[i]);
753: sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]),
754: n, SQLITE_TRANSIENT);
755: break;
756: }
757: }
758: }
759:
760: /*
761: ** These are test functions. hex8() interprets its argument as
762: ** UTF8 and returns a hex encoding. hex16le() interprets its argument
763: ** as UTF16le and returns a hex encoding.
764: */
765: static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){
766: const unsigned char *z;
767: int i;
768: char zBuf[200];
769: z = sqlite3_value_text(argv[0]);
770: for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){
771: sprintf(&zBuf[i*2], "%02x", z[i]&0xff);
772: }
773: zBuf[i*2] = 0;
774: sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
775: }
776: #ifndef SQLITE_OMIT_UTF16
777: static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){
778: const unsigned short int *z;
779: int i;
780: char zBuf[400];
781: z = sqlite3_value_text16(argv[0]);
782: for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){
783: sprintf(&zBuf[i*4], "%04x", z[i]&0xff);
784: }
785: zBuf[i*4] = 0;
786: sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
787: }
788: #endif
789:
790: /*
791: ** A structure into which to accumulate text.
792: */
793: struct dstr {
794: int nAlloc; /* Space allocated */
795: int nUsed; /* Space used */
796: char *z; /* The space */
797: };
798:
799: /*
800: ** Append text to a dstr
801: */
802: static void dstrAppend(struct dstr *p, const char *z, int divider){
803: int n = strlen(z);
804: if( p->nUsed + n + 2 > p->nAlloc ){
805: char *zNew;
806: p->nAlloc = p->nAlloc*2 + n + 200;
807: zNew = sqlite3_realloc(p->z, p->nAlloc);
808: if( zNew==0 ){
809: sqlite3_free(p->z);
810: memset(p, 0, sizeof(*p));
811: return;
812: }
813: p->z = zNew;
814: }
815: if( divider && p->nUsed>0 ){
816: p->z[p->nUsed++] = divider;
817: }
818: memcpy(&p->z[p->nUsed], z, n+1);
819: p->nUsed += n;
820: }
821:
822: /*
823: ** Invoked for each callback from sqlite3ExecFunc
824: */
825: static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
826: struct dstr *p = (struct dstr*)pData;
827: int i;
828: for(i=0; i<argc; i++){
829: if( argv[i]==0 ){
830: dstrAppend(p, "NULL", ' ');
831: }else{
832: dstrAppend(p, argv[i], ' ');
833: }
834: }
835: return 0;
836: }
837:
838: /*
839: ** Implementation of the x_sqlite_exec() function. This function takes
840: ** a single argument and attempts to execute that argument as SQL code.
841: ** This is illegal and should set the SQLITE_MISUSE flag on the database.
842: **
843: ** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec()
844: ** from within a function call.
845: **
846: ** This routine simulates the effect of having two threads attempt to
847: ** use the same database at the same time.
848: */
849: static void sqlite3ExecFunc(
850: sqlite3_context *context,
851: int argc,
852: sqlite3_value **argv
853: ){
854: struct dstr x;
855: memset(&x, 0, sizeof(x));
856: (void)sqlite3_exec((sqlite3*)sqlite3_user_data(context),
857: (char*)sqlite3_value_text(argv[0]),
858: execFuncCallback, &x, 0);
859: sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
860: sqlite3_free(x.z);
861: }
862:
863: /*
864: ** Implementation of tkt2213func(), a scalar function that takes exactly
865: ** one argument. It has two interesting features:
866: **
867: ** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*.
868: ** If the three pointers returned are not the same an SQL error is raised.
869: **
870: ** * Otherwise it returns a copy of the text representation of its
871: ** argument in such a way as the VDBE representation is a Mem* cell
872: ** with the MEM_Term flag clear.
873: **
874: ** Ticket #2213 can therefore be tested by evaluating the following
875: ** SQL expression:
876: **
877: ** tkt2213func(tkt2213func('a string'));
878: */
879: static void tkt2213Function(
880: sqlite3_context *context,
881: int argc,
882: sqlite3_value **argv
883: ){
884: int nText;
885: unsigned char const *zText1;
886: unsigned char const *zText2;
887: unsigned char const *zText3;
888:
889: nText = sqlite3_value_bytes(argv[0]);
890: zText1 = sqlite3_value_text(argv[0]);
891: zText2 = sqlite3_value_text(argv[0]);
892: zText3 = sqlite3_value_text(argv[0]);
893:
894: if( zText1!=zText2 || zText2!=zText3 ){
895: sqlite3_result_error(context, "tkt2213 is not fixed", -1);
896: }else{
897: char *zCopy = (char *)sqlite3_malloc(nText);
898: memcpy(zCopy, zText1, nText);
899: sqlite3_result_text(context, zCopy, nText, sqlite3_free);
900: }
901: }
902:
903: /*
904: ** The following SQL function takes 4 arguments. The 2nd and
905: ** 4th argument must be one of these strings: 'text', 'text16',
906: ** or 'blob' corresponding to API functions
907: **
908: ** sqlite3_value_text()
909: ** sqlite3_value_text16()
910: ** sqlite3_value_blob()
911: **
912: ** The third argument is a string, either 'bytes' or 'bytes16' or 'noop',
913: ** corresponding to APIs:
914: **
915: ** sqlite3_value_bytes()
916: ** sqlite3_value_bytes16()
917: ** noop
918: **
919: ** The APIs designated by the 2nd through 4th arguments are applied
920: ** to the first argument in order. If the pointers returned by the
921: ** second and fourth are different, this routine returns 1. Otherwise,
922: ** this routine returns 0.
923: **
924: ** This function is used to test to see when returned pointers from
925: ** the _text(), _text16() and _blob() APIs become invalidated.
926: */
927: static void ptrChngFunction(
928: sqlite3_context *context,
929: int argc,
930: sqlite3_value **argv
931: ){
932: const void *p1, *p2;
933: const char *zCmd;
934: if( argc!=4 ) return;
935: zCmd = (const char*)sqlite3_value_text(argv[1]);
936: if( zCmd==0 ) return;
937: if( strcmp(zCmd,"text")==0 ){
938: p1 = (const void*)sqlite3_value_text(argv[0]);
939: #ifndef SQLITE_OMIT_UTF16
940: }else if( strcmp(zCmd, "text16")==0 ){
941: p1 = (const void*)sqlite3_value_text16(argv[0]);
942: #endif
943: }else if( strcmp(zCmd, "blob")==0 ){
944: p1 = (const void*)sqlite3_value_blob(argv[0]);
945: }else{
946: return;
947: }
948: zCmd = (const char*)sqlite3_value_text(argv[2]);
949: if( zCmd==0 ) return;
950: if( strcmp(zCmd,"bytes")==0 ){
951: sqlite3_value_bytes(argv[0]);
952: #ifndef SQLITE_OMIT_UTF16
953: }else if( strcmp(zCmd, "bytes16")==0 ){
954: sqlite3_value_bytes16(argv[0]);
955: #endif
956: }else if( strcmp(zCmd, "noop")==0 ){
957: /* do nothing */
958: }else{
959: return;
960: }
961: zCmd = (const char*)sqlite3_value_text(argv[3]);
962: if( zCmd==0 ) return;
963: if( strcmp(zCmd,"text")==0 ){
964: p2 = (const void*)sqlite3_value_text(argv[0]);
965: #ifndef SQLITE_OMIT_UTF16
966: }else if( strcmp(zCmd, "text16")==0 ){
967: p2 = (const void*)sqlite3_value_text16(argv[0]);
968: #endif
969: }else if( strcmp(zCmd, "blob")==0 ){
970: p2 = (const void*)sqlite3_value_blob(argv[0]);
971: }else{
972: return;
973: }
974: sqlite3_result_int(context, p1!=p2);
975: }
976:
977:
978: /*
979: ** Usage: sqlite_test_create_function DB
980: **
981: ** Call the sqlite3_create_function API on the given database in order
982: ** to create a function named "x_coalesce". This function does the same thing
983: ** as the "coalesce" function. This function also registers an SQL function
984: ** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec()
985: ** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
986: ** The effect is similar to trying to use the same database connection from
987: ** two threads at the same time.
988: **
989: ** The original motivation for this routine was to be able to call the
990: ** sqlite3_create_function function while a query is in progress in order
991: ** to test the SQLITE_MISUSE detection logic.
992: */
993: static int test_create_function(
994: void *NotUsed,
995: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
996: int argc, /* Number of arguments */
997: char **argv /* Text of each argument */
998: ){
999: int rc;
1000: sqlite3 *db;
1001:
1002: if( argc!=2 ){
1003: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1004: " DB\"", 0);
1005: return TCL_ERROR;
1006: }
1007: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
1008: rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,
1009: t1_ifnullFunc, 0, 0);
1010: if( rc==SQLITE_OK ){
1011: rc = sqlite3_create_function(db, "hex8", 1, SQLITE_ANY, 0,
1012: hex8Func, 0, 0);
1013: }
1014: #ifndef SQLITE_OMIT_UTF16
1015: if( rc==SQLITE_OK ){
1016: rc = sqlite3_create_function(db, "hex16", 1, SQLITE_ANY, 0,
1017: hex16Func, 0, 0);
1018: }
1019: #endif
1020: if( rc==SQLITE_OK ){
1021: rc = sqlite3_create_function(db, "tkt2213func", 1, SQLITE_ANY, 0,
1022: tkt2213Function, 0, 0);
1023: }
1024: if( rc==SQLITE_OK ){
1025: rc = sqlite3_create_function(db, "pointer_change", 4, SQLITE_ANY, 0,
1026: ptrChngFunction, 0, 0);
1027: }
1028:
1029: #ifndef SQLITE_OMIT_UTF16
1030: /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
1031: ** because it is not tested anywhere else. */
1032: if( rc==SQLITE_OK ){
1033: const void *zUtf16;
1034: sqlite3_value *pVal;
1035: sqlite3_mutex_enter(db->mutex);
1036: pVal = sqlite3ValueNew(db);
1037: sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
1038: zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
1039: if( db->mallocFailed ){
1040: rc = SQLITE_NOMEM;
1041: }else{
1042: rc = sqlite3_create_function16(db, zUtf16,
1043: 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
1044: }
1045: sqlite3ValueFree(pVal);
1046: sqlite3_mutex_leave(db->mutex);
1047: }
1048: #endif
1049:
1050: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
1051: Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
1052: return TCL_OK;
1053: }
1054:
1055: /*
1056: ** Routines to implement the x_count() aggregate function.
1057: **
1058: ** x_count() counts the number of non-null arguments. But there are
1059: ** some twists for testing purposes.
1060: **
1061: ** If the argument to x_count() is 40 then a UTF-8 error is reported
1062: ** on the step function. If x_count(41) is seen, then a UTF-16 error
1063: ** is reported on the step function. If the total count is 42, then
1064: ** a UTF-8 error is reported on the finalize function.
1065: */
1066: typedef struct t1CountCtx t1CountCtx;
1067: struct t1CountCtx {
1068: int n;
1069: };
1070: static void t1CountStep(
1071: sqlite3_context *context,
1072: int argc,
1073: sqlite3_value **argv
1074: ){
1075: t1CountCtx *p;
1076: p = sqlite3_aggregate_context(context, sizeof(*p));
1077: if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
1078: p->n++;
1079: }
1080: if( argc>0 ){
1081: int v = sqlite3_value_int(argv[0]);
1082: if( v==40 ){
1083: sqlite3_result_error(context, "value of 40 handed to x_count", -1);
1084: #ifndef SQLITE_OMIT_UTF16
1085: }else if( v==41 ){
1086: const char zUtf16ErrMsg[] = { 0, 0x61, 0, 0x62, 0, 0x63, 0, 0, 0};
1087: sqlite3_result_error16(context, &zUtf16ErrMsg[1-SQLITE_BIGENDIAN], -1);
1088: #endif
1089: }
1090: }
1091: }
1092: static void t1CountFinalize(sqlite3_context *context){
1093: t1CountCtx *p;
1094: p = sqlite3_aggregate_context(context, sizeof(*p));
1095: if( p ){
1096: if( p->n==42 ){
1097: sqlite3_result_error(context, "x_count totals to 42", -1);
1098: }else{
1099: sqlite3_result_int(context, p ? p->n : 0);
1100: }
1101: }
1102: }
1103:
1104: #ifndef SQLITE_OMIT_DEPRECATED
1105: static void legacyCountStep(
1106: sqlite3_context *context,
1107: int argc,
1108: sqlite3_value **argv
1109: ){
1110: /* no-op */
1111: }
1112:
1113: static void legacyCountFinalize(sqlite3_context *context){
1114: sqlite3_result_int(context, sqlite3_aggregate_count(context));
1115: }
1116: #endif
1117:
1118: /*
1119: ** Usage: sqlite3_create_aggregate DB
1120: **
1121: ** Call the sqlite3_create_function API on the given database in order
1122: ** to create a function named "x_count". This function is similar
1123: ** to the built-in count() function, with a few special quirks
1124: ** for testing the sqlite3_result_error() APIs.
1125: **
1126: ** The original motivation for this routine was to be able to call the
1127: ** sqlite3_create_aggregate function while a query is in progress in order
1128: ** to test the SQLITE_MISUSE detection logic. See misuse.test.
1129: **
1130: ** This routine was later extended to test the use of sqlite3_result_error()
1131: ** within aggregate functions.
1132: **
1133: ** Later: It is now also extended to register the aggregate function
1134: ** "legacy_count()" with the supplied database handle. This is used
1135: ** to test the deprecated sqlite3_aggregate_count() API.
1136: */
1137: static int test_create_aggregate(
1138: void *NotUsed,
1139: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1140: int argc, /* Number of arguments */
1141: char **argv /* Text of each argument */
1142: ){
1143: sqlite3 *db;
1144: int rc;
1145: if( argc!=2 ){
1146: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1147: " FILENAME\"", 0);
1148: return TCL_ERROR;
1149: }
1150: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
1151: rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
1152: t1CountStep,t1CountFinalize);
1153: if( rc==SQLITE_OK ){
1154: rc = sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
1155: t1CountStep,t1CountFinalize);
1156: }
1157: #ifndef SQLITE_OMIT_DEPRECATED
1158: if( rc==SQLITE_OK ){
1159: rc = sqlite3_create_function(db, "legacy_count", 0, SQLITE_ANY, 0, 0,
1160: legacyCountStep, legacyCountFinalize
1161: );
1162: }
1163: #endif
1164: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
1165: Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
1166: return TCL_OK;
1167: }
1168:
1169:
1170: /*
1171: ** Usage: printf TEXT
1172: **
1173: ** Send output to printf. Use this rather than puts to merge the output
1174: ** in the correct sequence with debugging printfs inserted into C code.
1175: ** Puts uses a separate buffer and debugging statements will be out of
1176: ** sequence if it is used.
1177: */
1178: static int test_printf(
1179: void *NotUsed,
1180: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1181: int argc, /* Number of arguments */
1182: char **argv /* Text of each argument */
1183: ){
1184: if( argc!=2 ){
1185: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1186: " TEXT\"", 0);
1187: return TCL_ERROR;
1188: }
1189: printf("%s\n", argv[1]);
1190: return TCL_OK;
1191: }
1192:
1193:
1194:
1195: /*
1196: ** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
1197: **
1198: ** Call mprintf with three integer arguments
1199: */
1200: static int sqlite3_mprintf_int(
1201: void *NotUsed,
1202: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1203: int argc, /* Number of arguments */
1204: char **argv /* Text of each argument */
1205: ){
1206: int a[3], i;
1207: char *z;
1208: if( argc!=5 ){
1209: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1210: " FORMAT INT INT INT\"", 0);
1211: return TCL_ERROR;
1212: }
1213: for(i=2; i<5; i++){
1214: if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
1215: }
1216: z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
1217: Tcl_AppendResult(interp, z, 0);
1218: sqlite3_free(z);
1219: return TCL_OK;
1220: }
1221:
1222: /*
1223: ** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
1224: **
1225: ** Call mprintf with three 64-bit integer arguments
1226: */
1227: static int sqlite3_mprintf_int64(
1228: void *NotUsed,
1229: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1230: int argc, /* Number of arguments */
1231: char **argv /* Text of each argument */
1232: ){
1233: int i;
1234: sqlite_int64 a[3];
1235: char *z;
1236: if( argc!=5 ){
1237: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1238: " FORMAT INT INT INT\"", 0);
1239: return TCL_ERROR;
1240: }
1241: for(i=2; i<5; i++){
1242: if( sqlite3Atoi64(argv[i], &a[i-2], 1000000, SQLITE_UTF8) ){
1243: Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
1244: return TCL_ERROR;
1245: }
1246: }
1247: z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
1248: Tcl_AppendResult(interp, z, 0);
1249: sqlite3_free(z);
1250: return TCL_OK;
1251: }
1252:
1253: /*
1254: ** Usage: sqlite3_mprintf_long FORMAT INTEGER INTEGER INTEGER
1255: **
1256: ** Call mprintf with three long integer arguments. This might be the
1257: ** same as sqlite3_mprintf_int or sqlite3_mprintf_int64, depending on
1258: ** platform.
1259: */
1260: static int sqlite3_mprintf_long(
1261: void *NotUsed,
1262: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1263: int argc, /* Number of arguments */
1264: char **argv /* Text of each argument */
1265: ){
1266: int i;
1267: long int a[3];
1268: int b[3];
1269: char *z;
1270: if( argc!=5 ){
1271: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1272: " FORMAT INT INT INT\"", 0);
1273: return TCL_ERROR;
1274: }
1275: for(i=2; i<5; i++){
1276: if( Tcl_GetInt(interp, argv[i], &b[i-2]) ) return TCL_ERROR;
1277: a[i-2] = (long int)b[i-2];
1278: a[i-2] &= (((u64)1)<<(sizeof(int)*8))-1;
1279: }
1280: z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
1281: Tcl_AppendResult(interp, z, 0);
1282: sqlite3_free(z);
1283: return TCL_OK;
1284: }
1285:
1286: /*
1287: ** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
1288: **
1289: ** Call mprintf with two integer arguments and one string argument
1290: */
1291: static int sqlite3_mprintf_str(
1292: void *NotUsed,
1293: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1294: int argc, /* Number of arguments */
1295: char **argv /* Text of each argument */
1296: ){
1297: int a[3], i;
1298: char *z;
1299: if( argc<4 || argc>5 ){
1300: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1301: " FORMAT INT INT ?STRING?\"", 0);
1302: return TCL_ERROR;
1303: }
1304: for(i=2; i<4; i++){
1305: if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
1306: }
1307: z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
1308: Tcl_AppendResult(interp, z, 0);
1309: sqlite3_free(z);
1310: return TCL_OK;
1311: }
1312:
1313: /*
1314: ** Usage: sqlite3_snprintf_str INTEGER FORMAT INTEGER INTEGER STRING
1315: **
1316: ** Call mprintf with two integer arguments and one string argument
1317: */
1318: static int sqlite3_snprintf_str(
1319: void *NotUsed,
1320: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1321: int argc, /* Number of arguments */
1322: char **argv /* Text of each argument */
1323: ){
1324: int a[3], i;
1325: int n;
1326: char *z;
1327: if( argc<5 || argc>6 ){
1328: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1329: " INT FORMAT INT INT ?STRING?\"", 0);
1330: return TCL_ERROR;
1331: }
1332: if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
1333: if( n<0 ){
1334: Tcl_AppendResult(interp, "N must be non-negative", 0);
1335: return TCL_ERROR;
1336: }
1337: for(i=3; i<5; i++){
1338: if( Tcl_GetInt(interp, argv[i], &a[i-3]) ) return TCL_ERROR;
1339: }
1340: z = sqlite3_malloc( n+1 );
1341: sqlite3_snprintf(n, z, argv[2], a[0], a[1], argc>4 ? argv[5] : NULL);
1342: Tcl_AppendResult(interp, z, 0);
1343: sqlite3_free(z);
1344: return TCL_OK;
1345: }
1346:
1347: /*
1348: ** Usage: sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE
1349: **
1350: ** Call mprintf with two integer arguments and one double argument
1351: */
1352: static int sqlite3_mprintf_double(
1353: void *NotUsed,
1354: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1355: int argc, /* Number of arguments */
1356: char **argv /* Text of each argument */
1357: ){
1358: int a[3], i;
1359: double r;
1360: char *z;
1361: if( argc!=5 ){
1362: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1363: " FORMAT INT INT DOUBLE\"", 0);
1364: return TCL_ERROR;
1365: }
1366: for(i=2; i<4; i++){
1367: if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
1368: }
1369: if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
1370: z = sqlite3_mprintf(argv[1], a[0], a[1], r);
1371: Tcl_AppendResult(interp, z, 0);
1372: sqlite3_free(z);
1373: return TCL_OK;
1374: }
1375:
1376: /*
1377: ** Usage: sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE
1378: **
1379: ** Call mprintf with a single double argument which is the product of the
1380: ** two arguments given above. This is used to generate overflow and underflow
1381: ** doubles to test that they are converted properly.
1382: */
1383: static int sqlite3_mprintf_scaled(
1384: void *NotUsed,
1385: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1386: int argc, /* Number of arguments */
1387: char **argv /* Text of each argument */
1388: ){
1389: int i;
1390: double r[2];
1391: char *z;
1392: if( argc!=4 ){
1393: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1394: " FORMAT DOUBLE DOUBLE\"", 0);
1395: return TCL_ERROR;
1396: }
1397: for(i=2; i<4; i++){
1398: if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
1399: }
1400: z = sqlite3_mprintf(argv[1], r[0]*r[1]);
1401: Tcl_AppendResult(interp, z, 0);
1402: sqlite3_free(z);
1403: return TCL_OK;
1404: }
1405:
1406: /*
1407: ** Usage: sqlite3_mprintf_stronly FORMAT STRING
1408: **
1409: ** Call mprintf with a single double argument which is the product of the
1410: ** two arguments given above. This is used to generate overflow and underflow
1411: ** doubles to test that they are converted properly.
1412: */
1413: static int sqlite3_mprintf_stronly(
1414: void *NotUsed,
1415: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1416: int argc, /* Number of arguments */
1417: char **argv /* Text of each argument */
1418: ){
1419: char *z;
1420: if( argc!=3 ){
1421: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1422: " FORMAT STRING\"", 0);
1423: return TCL_ERROR;
1424: }
1425: z = sqlite3_mprintf(argv[1], argv[2]);
1426: Tcl_AppendResult(interp, z, 0);
1427: sqlite3_free(z);
1428: return TCL_OK;
1429: }
1430:
1431: /*
1432: ** Usage: sqlite3_mprintf_hexdouble FORMAT HEX
1433: **
1434: ** Call mprintf with a single double argument which is derived from the
1435: ** hexadecimal encoding of an IEEE double.
1436: */
1437: static int sqlite3_mprintf_hexdouble(
1438: void *NotUsed,
1439: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1440: int argc, /* Number of arguments */
1441: char **argv /* Text of each argument */
1442: ){
1443: char *z;
1444: double r;
1445: unsigned int x1, x2;
1446: sqlite_uint64 d;
1447: if( argc!=3 ){
1448: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1449: " FORMAT STRING\"", 0);
1450: return TCL_ERROR;
1451: }
1452: if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){
1453: Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0);
1454: return TCL_ERROR;
1455: }
1456: d = x2;
1457: d = (d<<32) + x1;
1458: memcpy(&r, &d, sizeof(r));
1459: z = sqlite3_mprintf(argv[1], r);
1460: Tcl_AppendResult(interp, z, 0);
1461: sqlite3_free(z);
1462: return TCL_OK;
1463: }
1464:
1465: /*
1466: ** Usage: sqlite3_enable_shared_cache ?BOOLEAN?
1467: **
1468: */
1469: #if !defined(SQLITE_OMIT_SHARED_CACHE)
1470: static int test_enable_shared(
1471: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1472: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1473: int objc, /* Number of arguments */
1474: Tcl_Obj *CONST objv[] /* Command arguments */
1475: ){
1476: int rc;
1477: int enable;
1478: int ret = 0;
1479:
1480: if( objc!=2 && objc!=1 ){
1481: Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?");
1482: return TCL_ERROR;
1483: }
1484: ret = sqlite3GlobalConfig.sharedCacheEnabled;
1485:
1486: if( objc==2 ){
1487: if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){
1488: return TCL_ERROR;
1489: }
1490: rc = sqlite3_enable_shared_cache(enable);
1491: if( rc!=SQLITE_OK ){
1492: Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
1493: return TCL_ERROR;
1494: }
1495: }
1496: Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret));
1497: return TCL_OK;
1498: }
1499: #endif
1500:
1501:
1502:
1503: /*
1504: ** Usage: sqlite3_extended_result_codes DB BOOLEAN
1505: **
1506: */
1507: static int test_extended_result_codes(
1508: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1509: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1510: int objc, /* Number of arguments */
1511: Tcl_Obj *CONST objv[] /* Command arguments */
1512: ){
1513: int enable;
1514: sqlite3 *db;
1515:
1516: if( objc!=3 ){
1517: Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN");
1518: return TCL_ERROR;
1519: }
1520: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1521: if( Tcl_GetBooleanFromObj(interp, objv[2], &enable) ) return TCL_ERROR;
1522: sqlite3_extended_result_codes(db, enable);
1523: return TCL_OK;
1524: }
1525:
1526: /*
1527: ** Usage: sqlite3_libversion_number
1528: **
1529: */
1530: static int test_libversion_number(
1531: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1532: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1533: int objc, /* Number of arguments */
1534: Tcl_Obj *CONST objv[] /* Command arguments */
1535: ){
1536: Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_libversion_number()));
1537: return TCL_OK;
1538: }
1539:
1540: /*
1541: ** Usage: sqlite3_table_column_metadata DB dbname tblname colname
1542: **
1543: */
1544: #ifdef SQLITE_ENABLE_COLUMN_METADATA
1545: static int test_table_column_metadata(
1546: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1547: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1548: int objc, /* Number of arguments */
1549: Tcl_Obj *CONST objv[] /* Command arguments */
1550: ){
1551: sqlite3 *db;
1552: const char *zDb;
1553: const char *zTbl;
1554: const char *zCol;
1555: int rc;
1556: Tcl_Obj *pRet;
1557:
1558: const char *zDatatype;
1559: const char *zCollseq;
1560: int notnull;
1561: int primarykey;
1562: int autoincrement;
1563:
1564: if( objc!=5 ){
1565: Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname");
1566: return TCL_ERROR;
1567: }
1568: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1569: zDb = Tcl_GetString(objv[2]);
1570: zTbl = Tcl_GetString(objv[3]);
1571: zCol = Tcl_GetString(objv[4]);
1572:
1573: if( strlen(zDb)==0 ) zDb = 0;
1574:
1575: rc = sqlite3_table_column_metadata(db, zDb, zTbl, zCol,
1576: &zDatatype, &zCollseq, ¬null, &primarykey, &autoincrement);
1577:
1578: if( rc!=SQLITE_OK ){
1579: Tcl_AppendResult(interp, sqlite3_errmsg(db), 0);
1580: return TCL_ERROR;
1581: }
1582:
1583: pRet = Tcl_NewObj();
1584: Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zDatatype, -1));
1585: Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zCollseq, -1));
1586: Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(notnull));
1587: Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(primarykey));
1588: Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(autoincrement));
1589: Tcl_SetObjResult(interp, pRet);
1590:
1591: return TCL_OK;
1592: }
1593: #endif
1594:
1595: #ifndef SQLITE_OMIT_INCRBLOB
1596:
1597: static int blobHandleFromObj(
1598: Tcl_Interp *interp,
1599: Tcl_Obj *pObj,
1600: sqlite3_blob **ppBlob
1601: ){
1602: char *z;
1603: int n;
1604:
1605: z = Tcl_GetStringFromObj(pObj, &n);
1606: if( n==0 ){
1607: *ppBlob = 0;
1608: }else{
1609: int notUsed;
1610: Tcl_Channel channel;
1611: ClientData instanceData;
1612:
1613: channel = Tcl_GetChannel(interp, z, ¬Used);
1614: if( !channel ) return TCL_ERROR;
1615:
1616: Tcl_Flush(channel);
1617: Tcl_Seek(channel, 0, SEEK_SET);
1618:
1619: instanceData = Tcl_GetChannelInstanceData(channel);
1620: *ppBlob = *((sqlite3_blob **)instanceData);
1621: }
1622:
1623: return TCL_OK;
1624: }
1625:
1626: /*
1627: ** sqlite3_blob_bytes CHANNEL
1628: */
1629: static int test_blob_bytes(
1630: ClientData clientData, /* Not used */
1631: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1632: int objc, /* Number of arguments */
1633: Tcl_Obj *CONST objv[] /* Command arguments */
1634: ){
1635: sqlite3_blob *pBlob;
1636: int nByte;
1637:
1638: if( objc!=2 ){
1639: Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL");
1640: return TCL_ERROR;
1641: }
1642:
1643: if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
1644: nByte = sqlite3_blob_bytes(pBlob);
1645: Tcl_SetObjResult(interp, Tcl_NewIntObj(nByte));
1646:
1647: return TCL_OK;
1648: }
1649:
1650: /*
1651: ** sqlite3_blob_close CHANNEL
1652: */
1653: static int test_blob_close(
1654: ClientData clientData, /* Not used */
1655: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1656: int objc, /* Number of arguments */
1657: Tcl_Obj *CONST objv[] /* Command arguments */
1658: ){
1659: sqlite3_blob *pBlob;
1660:
1661: if( objc!=2 ){
1662: Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL");
1663: return TCL_ERROR;
1664: }
1665:
1666: if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
1667: sqlite3_blob_close(pBlob);
1668:
1669: return TCL_OK;
1670: }
1671:
1672: /*
1673: ** sqlite3_blob_read CHANNEL OFFSET N
1674: **
1675: ** This command is used to test the sqlite3_blob_read() in ways that
1676: ** the Tcl channel interface does not. The first argument should
1677: ** be the name of a valid channel created by the [incrblob] method
1678: ** of a database handle. This function calls sqlite3_blob_read()
1679: ** to read N bytes from offset OFFSET from the underlying SQLite
1680: ** blob handle.
1681: **
1682: ** On success, a byte-array object containing the read data is
1683: ** returned. On failure, the interpreter result is set to the
1684: ** text representation of the returned error code (i.e. "SQLITE_NOMEM")
1685: ** and a Tcl exception is thrown.
1686: */
1687: static int test_blob_read(
1688: ClientData clientData, /* Not used */
1689: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1690: int objc, /* Number of arguments */
1691: Tcl_Obj *CONST objv[] /* Command arguments */
1692: ){
1693: sqlite3_blob *pBlob;
1694: int nByte;
1695: int iOffset;
1696: unsigned char *zBuf = 0;
1697: int rc;
1698:
1699: if( objc!=4 ){
1700: Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET N");
1701: return TCL_ERROR;
1702: }
1703:
1704: if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
1705: if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset)
1706: || TCL_OK!=Tcl_GetIntFromObj(interp, objv[3], &nByte)
1707: ){
1708: return TCL_ERROR;
1709: }
1710:
1711: if( nByte>0 ){
1712: zBuf = (unsigned char *)Tcl_Alloc(nByte);
1713: }
1714: rc = sqlite3_blob_read(pBlob, zBuf, nByte, iOffset);
1715: if( rc==SQLITE_OK ){
1716: Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zBuf, nByte));
1717: }else{
1718: Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
1719: }
1720: Tcl_Free((char *)zBuf);
1721:
1722: return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
1723: }
1724:
1725: /*
1726: ** sqlite3_blob_write CHANNEL OFFSET DATA ?NDATA?
1727: **
1728: ** This command is used to test the sqlite3_blob_write() in ways that
1729: ** the Tcl channel interface does not. The first argument should
1730: ** be the name of a valid channel created by the [incrblob] method
1731: ** of a database handle. This function calls sqlite3_blob_write()
1732: ** to write the DATA byte-array to the underlying SQLite blob handle.
1733: ** at offset OFFSET.
1734: **
1735: ** On success, an empty string is returned. On failure, the interpreter
1736: ** result is set to the text representation of the returned error code
1737: ** (i.e. "SQLITE_NOMEM") and a Tcl exception is thrown.
1738: */
1739: static int test_blob_write(
1740: ClientData clientData, /* Not used */
1741: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1742: int objc, /* Number of arguments */
1743: Tcl_Obj *CONST objv[] /* Command arguments */
1744: ){
1745: sqlite3_blob *pBlob;
1746: int iOffset;
1747: int rc;
1748:
1749: unsigned char *zBuf;
1750: int nBuf;
1751:
1752: if( objc!=4 && objc!=5 ){
1753: Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET DATA ?NDATA?");
1754: return TCL_ERROR;
1755: }
1756:
1757: if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
1758: if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) ){
1759: return TCL_ERROR;
1760: }
1761:
1762: zBuf = Tcl_GetByteArrayFromObj(objv[3], &nBuf);
1763: if( objc==5 && Tcl_GetIntFromObj(interp, objv[4], &nBuf) ){
1764: return TCL_ERROR;
1765: }
1766: rc = sqlite3_blob_write(pBlob, zBuf, nBuf, iOffset);
1767: if( rc!=SQLITE_OK ){
1768: Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
1769: }
1770:
1771: return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
1772: }
1773:
1774: static int test_blob_reopen(
1775: ClientData clientData, /* Not used */
1776: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1777: int objc, /* Number of arguments */
1778: Tcl_Obj *CONST objv[] /* Command arguments */
1779: ){
1780: Tcl_WideInt iRowid;
1781: sqlite3_blob *pBlob;
1782: int rc;
1783:
1784: if( objc!=3 ){
1785: Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL ROWID");
1786: return TCL_ERROR;
1787: }
1788:
1789: if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
1790: if( Tcl_GetWideIntFromObj(interp, objv[2], &iRowid) ) return TCL_ERROR;
1791:
1792: rc = sqlite3_blob_reopen(pBlob, iRowid);
1793: if( rc!=SQLITE_OK ){
1794: Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
1795: }
1796:
1797: return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
1798: }
1799:
1800: #endif
1801:
1802: /*
1803: ** Usage: sqlite3_create_collation_v2 DB-HANDLE NAME CMP-PROC DEL-PROC
1804: **
1805: ** This Tcl proc is used for testing the experimental
1806: ** sqlite3_create_collation_v2() interface.
1807: */
1808: struct TestCollationX {
1809: Tcl_Interp *interp;
1810: Tcl_Obj *pCmp;
1811: Tcl_Obj *pDel;
1812: };
1813: typedef struct TestCollationX TestCollationX;
1814: static void testCreateCollationDel(void *pCtx){
1815: TestCollationX *p = (TestCollationX *)pCtx;
1816:
1817: int rc = Tcl_EvalObjEx(p->interp, p->pDel, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL);
1818: if( rc!=TCL_OK ){
1819: Tcl_BackgroundError(p->interp);
1820: }
1821:
1822: Tcl_DecrRefCount(p->pCmp);
1823: Tcl_DecrRefCount(p->pDel);
1824: sqlite3_free((void *)p);
1825: }
1826: static int testCreateCollationCmp(
1827: void *pCtx,
1828: int nLeft,
1829: const void *zLeft,
1830: int nRight,
1831: const void *zRight
1832: ){
1833: TestCollationX *p = (TestCollationX *)pCtx;
1834: Tcl_Obj *pScript = Tcl_DuplicateObj(p->pCmp);
1835: int iRes = 0;
1836:
1837: Tcl_IncrRefCount(pScript);
1838: Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zLeft, nLeft));
1839: Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zRight,nRight));
1840:
1841: if( TCL_OK!=Tcl_EvalObjEx(p->interp, pScript, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL)
1842: || TCL_OK!=Tcl_GetIntFromObj(p->interp, Tcl_GetObjResult(p->interp), &iRes)
1843: ){
1844: Tcl_BackgroundError(p->interp);
1845: }
1846: Tcl_DecrRefCount(pScript);
1847:
1848: return iRes;
1849: }
1850: static int test_create_collation_v2(
1851: ClientData clientData, /* Not used */
1852: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1853: int objc, /* Number of arguments */
1854: Tcl_Obj *CONST objv[] /* Command arguments */
1855: ){
1856: TestCollationX *p;
1857: sqlite3 *db;
1858: int rc;
1859:
1860: if( objc!=5 ){
1861: Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE NAME CMP-PROC DEL-PROC");
1862: return TCL_ERROR;
1863: }
1864: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1865:
1866: p = (TestCollationX *)sqlite3_malloc(sizeof(TestCollationX));
1867: p->pCmp = objv[3];
1868: p->pDel = objv[4];
1869: p->interp = interp;
1870: Tcl_IncrRefCount(p->pCmp);
1871: Tcl_IncrRefCount(p->pDel);
1872:
1873: rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), 16,
1874: (void *)p, testCreateCollationCmp, testCreateCollationDel
1875: );
1876: if( rc!=SQLITE_MISUSE ){
1877: Tcl_AppendResult(interp, "sqlite3_create_collate_v2() failed to detect "
1878: "an invalid encoding", (char*)0);
1879: return TCL_ERROR;
1880: }
1881: rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), SQLITE_UTF8,
1882: (void *)p, testCreateCollationCmp, testCreateCollationDel
1883: );
1884: return TCL_OK;
1885: }
1886:
1887: /*
1888: ** USAGE: sqlite3_create_function_v2 DB NAME NARG ENC ?SWITCHES?
1889: **
1890: ** Available switches are:
1891: **
1892: ** -func SCRIPT
1893: ** -step SCRIPT
1894: ** -final SCRIPT
1895: ** -destroy SCRIPT
1896: */
1897: typedef struct CreateFunctionV2 CreateFunctionV2;
1898: struct CreateFunctionV2 {
1899: Tcl_Interp *interp;
1900: Tcl_Obj *pFunc; /* Script for function invocation */
1901: Tcl_Obj *pStep; /* Script for agg. step invocation */
1902: Tcl_Obj *pFinal; /* Script for agg. finalization invocation */
1903: Tcl_Obj *pDestroy; /* Destructor script */
1904: };
1905: static void cf2Func(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
1906: }
1907: static void cf2Step(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
1908: }
1909: static void cf2Final(sqlite3_context *ctx){
1910: }
1911: static void cf2Destroy(void *pUser){
1912: CreateFunctionV2 *p = (CreateFunctionV2 *)pUser;
1913:
1914: if( p->interp && p->pDestroy ){
1915: int rc = Tcl_EvalObjEx(p->interp, p->pDestroy, 0);
1916: if( rc!=TCL_OK ) Tcl_BackgroundError(p->interp);
1917: }
1918:
1919: if( p->pFunc ) Tcl_DecrRefCount(p->pFunc);
1920: if( p->pStep ) Tcl_DecrRefCount(p->pStep);
1921: if( p->pFinal ) Tcl_DecrRefCount(p->pFinal);
1922: if( p->pDestroy ) Tcl_DecrRefCount(p->pDestroy);
1923: sqlite3_free(p);
1924: }
1925: static int test_create_function_v2(
1926: ClientData clientData, /* Not used */
1927: Tcl_Interp *interp, /* The invoking TCL interpreter */
1928: int objc, /* Number of arguments */
1929: Tcl_Obj *CONST objv[] /* Command arguments */
1930: ){
1931: sqlite3 *db;
1932: const char *zFunc;
1933: int nArg;
1934: int enc;
1935: CreateFunctionV2 *p;
1936: int i;
1937: int rc;
1938:
1939: struct EncTable {
1940: const char *zEnc;
1941: int enc;
1942: } aEnc[] = {
1943: {"utf8", SQLITE_UTF8 },
1944: {"utf16", SQLITE_UTF16 },
1945: {"utf16le", SQLITE_UTF16LE },
1946: {"utf16be", SQLITE_UTF16BE },
1947: {"any", SQLITE_ANY },
1948: {"0", 0 }
1949: };
1950:
1951: if( objc<5 || (objc%2)==0 ){
1952: Tcl_WrongNumArgs(interp, 1, objv, "DB NAME NARG ENC SWITCHES...");
1953: return TCL_ERROR;
1954: }
1955:
1956: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1957: zFunc = Tcl_GetString(objv[2]);
1958: if( Tcl_GetIntFromObj(interp, objv[3], &nArg) ) return TCL_ERROR;
1959: if( Tcl_GetIndexFromObjStruct(interp, objv[4], aEnc, sizeof(aEnc[0]),
1960: "encoding", 0, &enc)
1961: ){
1962: return TCL_ERROR;
1963: }
1964: enc = aEnc[enc].enc;
1965:
1966: p = sqlite3_malloc(sizeof(CreateFunctionV2));
1967: assert( p );
1968: memset(p, 0, sizeof(CreateFunctionV2));
1969: p->interp = interp;
1970:
1971: for(i=5; i<objc; i+=2){
1972: int iSwitch;
1973: const char *azSwitch[] = {"-func", "-step", "-final", "-destroy", 0};
1974: if( Tcl_GetIndexFromObj(interp, objv[i], azSwitch, "switch", 0, &iSwitch) ){
1975: sqlite3_free(p);
1976: return TCL_ERROR;
1977: }
1978:
1979: switch( iSwitch ){
1980: case 0: p->pFunc = objv[i+1]; break;
1981: case 1: p->pStep = objv[i+1]; break;
1982: case 2: p->pFinal = objv[i+1]; break;
1983: case 3: p->pDestroy = objv[i+1]; break;
1984: }
1985: }
1986: if( p->pFunc ) p->pFunc = Tcl_DuplicateObj(p->pFunc);
1987: if( p->pStep ) p->pStep = Tcl_DuplicateObj(p->pStep);
1988: if( p->pFinal ) p->pFinal = Tcl_DuplicateObj(p->pFinal);
1989: if( p->pDestroy ) p->pDestroy = Tcl_DuplicateObj(p->pDestroy);
1990:
1991: if( p->pFunc ) Tcl_IncrRefCount(p->pFunc);
1992: if( p->pStep ) Tcl_IncrRefCount(p->pStep);
1993: if( p->pFinal ) Tcl_IncrRefCount(p->pFinal);
1994: if( p->pDestroy ) Tcl_IncrRefCount(p->pDestroy);
1995:
1996: rc = sqlite3_create_function_v2(db, zFunc, nArg, enc, (void *)p,
1997: (p->pFunc ? cf2Func : 0),
1998: (p->pStep ? cf2Step : 0),
1999: (p->pFinal ? cf2Final : 0),
2000: cf2Destroy
2001: );
2002: if( rc!=SQLITE_OK ){
2003: Tcl_ResetResult(interp);
2004: Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
2005: return TCL_ERROR;
2006: }
2007: return TCL_OK;
2008: }
2009:
2010: /*
2011: ** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC?
2012: */
2013: static int test_load_extension(
2014: ClientData clientData, /* Not used */
2015: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
2016: int objc, /* Number of arguments */
2017: Tcl_Obj *CONST objv[] /* Command arguments */
2018: ){
2019: Tcl_CmdInfo cmdInfo;
2020: sqlite3 *db;
2021: int rc;
2022: char *zDb;
2023: char *zFile;
2024: char *zProc = 0;
2025: char *zErr = 0;
2026:
2027: if( objc!=4 && objc!=3 ){
2028: Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?");
2029: return TCL_ERROR;
2030: }
2031: zDb = Tcl_GetString(objv[1]);
2032: zFile = Tcl_GetString(objv[2]);
2033: if( objc==4 ){
2034: zProc = Tcl_GetString(objv[3]);
2035: }
2036:
2037: /* Extract the C database handle from the Tcl command name */
2038: if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
2039: Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
2040: return TCL_ERROR;
2041: }
2042: db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
2043: assert(db);
2044:
2045: /* Call the underlying C function. If an error occurs, set rc to
2046: ** TCL_ERROR and load any error string into the interpreter. If no
2047: ** error occurs, set rc to TCL_OK.
2048: */
2049: #ifdef SQLITE_OMIT_LOAD_EXTENSION
2050: rc = SQLITE_ERROR;
2051: zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()");
2052: #else
2053: rc = sqlite3_load_extension(db, zFile, zProc, &zErr);
2054: #endif
2055: if( rc!=SQLITE_OK ){
2056: Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE);
2057: rc = TCL_ERROR;
2058: }else{
2059: rc = TCL_OK;
2060: }
2061: sqlite3_free(zErr);
2062:
2063: return rc;
2064: }
2065:
2066: /*
2067: ** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF
2068: */
2069: static int test_enable_load(
2070: ClientData clientData, /* Not used */
2071: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
2072: int objc, /* Number of arguments */
2073: Tcl_Obj *CONST objv[] /* Command arguments */
2074: ){
2075: Tcl_CmdInfo cmdInfo;
2076: sqlite3 *db;
2077: char *zDb;
2078: int onoff;
2079:
2080: if( objc!=3 ){
2081: Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF");
2082: return TCL_ERROR;
2083: }
2084: zDb = Tcl_GetString(objv[1]);
2085:
2086: /* Extract the C database handle from the Tcl command name */
2087: if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
2088: Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
2089: return TCL_ERROR;
2090: }
2091: db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
2092: assert(db);
2093:
2094: /* Get the onoff parameter */
2095: if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){
2096: return TCL_ERROR;
2097: }
2098:
2099: #ifdef SQLITE_OMIT_LOAD_EXTENSION
2100: Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()");
2101: return TCL_ERROR;
2102: #else
2103: sqlite3_enable_load_extension(db, onoff);
2104: return TCL_OK;
2105: #endif
2106: }
2107:
2108: /*
2109: ** Usage: sqlite_abort
2110: **
2111: ** Shutdown the process immediately. This is not a clean shutdown.
2112: ** This command is used to test the recoverability of a database in
2113: ** the event of a program crash.
2114: */
2115: static int sqlite_abort(
2116: void *NotUsed,
2117: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
2118: int argc, /* Number of arguments */
2119: char **argv /* Text of each argument */
2120: ){
2121: #if defined(_MSC_VER)
2122: /* We do this, otherwise the test will halt with a popup message
2123: * that we have to click away before the test will continue.
2124: */
2125: _set_abort_behavior( 0, _CALL_REPORTFAULT );
2126: #endif
2127: exit(255);
2128: assert( interp==0 ); /* This will always fail */
2129: return TCL_OK;
2130: }
2131:
2132: /*
2133: ** The following routine is a user-defined SQL function whose purpose
2134: ** is to test the sqlite_set_result() API.
2135: */
2136: static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
2137: while( argc>=2 ){
2138: const char *zArg0 = (char*)sqlite3_value_text(argv[0]);
2139: if( zArg0 ){
2140: if( 0==sqlite3StrICmp(zArg0, "int") ){
2141: sqlite3_result_int(context, sqlite3_value_int(argv[1]));
2142: }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
2143: sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
2144: }else if( sqlite3StrICmp(zArg0,"string")==0 ){
2145: sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1,
2146: SQLITE_TRANSIENT);
2147: }else if( sqlite3StrICmp(zArg0,"double")==0 ){
2148: sqlite3_result_double(context, sqlite3_value_double(argv[1]));
2149: }else if( sqlite3StrICmp(zArg0,"null")==0 ){
2150: sqlite3_result_null(context);
2151: }else if( sqlite3StrICmp(zArg0,"value")==0 ){
2152: sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
2153: }else{
2154: goto error_out;
2155: }
2156: }else{
2157: goto error_out;
2158: }
2159: argc -= 2;
2160: argv += 2;
2161: }
2162: return;
2163:
2164: error_out:
2165: sqlite3_result_error(context,"first argument should be one of: "
2166: "int int64 string double null value", -1);
2167: }
2168:
2169: /*
2170: ** Usage: sqlite_register_test_function DB NAME
2171: **
2172: ** Register the test SQL function on the database DB under the name NAME.
2173: */
2174: static int test_register_func(
2175: void *NotUsed,
2176: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
2177: int argc, /* Number of arguments */
2178: char **argv /* Text of each argument */
2179: ){
2180: sqlite3 *db;
2181: int rc;
2182: if( argc!=3 ){
2183: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2184: " DB FUNCTION-NAME", 0);
2185: return TCL_ERROR;
2186: }
2187: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2188: rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
2189: testFunc, 0, 0);
2190: if( rc!=0 ){
2191: Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
2192: return TCL_ERROR;
2193: }
2194: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
2195: return TCL_OK;
2196: }
2197:
2198: /*
2199: ** Usage: sqlite3_finalize STMT
2200: **
2201: ** Finalize a statement handle.
2202: */
2203: static int test_finalize(
2204: void * clientData,
2205: Tcl_Interp *interp,
2206: int objc,
2207: Tcl_Obj *CONST objv[]
2208: ){
2209: sqlite3_stmt *pStmt;
2210: int rc;
2211: sqlite3 *db = 0;
2212:
2213: if( objc!=2 ){
2214: Tcl_AppendResult(interp, "wrong # args: should be \"",
2215: Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
2216: return TCL_ERROR;
2217: }
2218:
2219: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2220:
2221: if( pStmt ){
2222: db = StmtToDb(pStmt);
2223: }
2224: rc = sqlite3_finalize(pStmt);
2225: Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
2226: if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
2227: return TCL_OK;
2228: }
2229:
2230: /*
2231: ** Usage: sqlite3_stmt_status STMT CODE RESETFLAG
2232: **
2233: ** Get the value of a status counter from a statement.
2234: */
2235: static int test_stmt_status(
2236: void * clientData,
2237: Tcl_Interp *interp,
2238: int objc,
2239: Tcl_Obj *CONST objv[]
2240: ){
2241: int iValue;
2242: int i, op, resetFlag;
2243: const char *zOpName;
2244: sqlite3_stmt *pStmt;
2245:
2246: static const struct {
2247: const char *zName;
2248: int op;
2249: } aOp[] = {
2250: { "SQLITE_STMTSTATUS_FULLSCAN_STEP", SQLITE_STMTSTATUS_FULLSCAN_STEP },
2251: { "SQLITE_STMTSTATUS_SORT", SQLITE_STMTSTATUS_SORT },
2252: { "SQLITE_STMTSTATUS_AUTOINDEX", SQLITE_STMTSTATUS_AUTOINDEX },
2253: };
2254: if( objc!=4 ){
2255: Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG");
2256: return TCL_ERROR;
2257: }
2258: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2259: zOpName = Tcl_GetString(objv[2]);
2260: for(i=0; i<ArraySize(aOp); i++){
2261: if( strcmp(aOp[i].zName, zOpName)==0 ){
2262: op = aOp[i].op;
2263: break;
2264: }
2265: }
2266: if( i>=ArraySize(aOp) ){
2267: if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR;
2268: }
2269: if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR;
2270: iValue = sqlite3_stmt_status(pStmt, op, resetFlag);
2271: Tcl_SetObjResult(interp, Tcl_NewIntObj(iValue));
2272: return TCL_OK;
2273: }
2274:
2275: /*
2276: ** Usage: sqlite3_next_stmt DB STMT
2277: **
2278: ** Return the next statment in sequence after STMT.
2279: */
2280: static int test_next_stmt(
2281: void * clientData,
2282: Tcl_Interp *interp,
2283: int objc,
2284: Tcl_Obj *CONST objv[]
2285: ){
2286: sqlite3_stmt *pStmt;
2287: sqlite3 *db = 0;
2288: char zBuf[50];
2289:
2290: if( objc!=3 ){
2291: Tcl_AppendResult(interp, "wrong # args: should be \"",
2292: Tcl_GetStringFromObj(objv[0], 0), " DB STMT", 0);
2293: return TCL_ERROR;
2294: }
2295:
2296: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2297: if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt) ) return TCL_ERROR;
2298: pStmt = sqlite3_next_stmt(db, pStmt);
2299: if( pStmt ){
2300: if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
2301: Tcl_AppendResult(interp, zBuf, 0);
2302: }
2303: return TCL_OK;
2304: }
2305:
2306: /*
2307: ** Usage: sqlite3_stmt_readonly STMT
2308: **
2309: ** Return true if STMT is a NULL pointer or a pointer to a statement
2310: ** that is guaranteed to leave the database unmodified.
2311: */
2312: static int test_stmt_readonly(
2313: void * clientData,
2314: Tcl_Interp *interp,
2315: int objc,
2316: Tcl_Obj *CONST objv[]
2317: ){
2318: sqlite3_stmt *pStmt;
2319: int rc;
2320:
2321: if( objc!=2 ){
2322: Tcl_AppendResult(interp, "wrong # args: should be \"",
2323: Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
2324: return TCL_ERROR;
2325: }
2326:
2327: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2328: rc = sqlite3_stmt_readonly(pStmt);
2329: Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
2330: return TCL_OK;
2331: }
2332:
2333: /*
2334: ** Usage: sqlite3_stmt_busy STMT
2335: **
2336: ** Return true if STMT is a non-NULL pointer to a statement
2337: ** that has been stepped but not to completion.
2338: */
2339: static int test_stmt_busy(
2340: void * clientData,
2341: Tcl_Interp *interp,
2342: int objc,
2343: Tcl_Obj *CONST objv[]
2344: ){
2345: sqlite3_stmt *pStmt;
2346: int rc;
2347:
2348: if( objc!=2 ){
2349: Tcl_AppendResult(interp, "wrong # args: should be \"",
2350: Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
2351: return TCL_ERROR;
2352: }
2353:
2354: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2355: rc = sqlite3_stmt_busy(pStmt);
2356: Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
2357: return TCL_OK;
2358: }
2359:
2360: /*
2361: ** Usage: uses_stmt_journal STMT
2362: **
2363: ** Return true if STMT uses a statement journal.
2364: */
2365: static int uses_stmt_journal(
2366: void * clientData,
2367: Tcl_Interp *interp,
2368: int objc,
2369: Tcl_Obj *CONST objv[]
2370: ){
2371: sqlite3_stmt *pStmt;
2372: int rc;
2373:
2374: if( objc!=2 ){
2375: Tcl_AppendResult(interp, "wrong # args: should be \"",
2376: Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
2377: return TCL_ERROR;
2378: }
2379:
2380: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2381: rc = sqlite3_stmt_readonly(pStmt);
2382: Tcl_SetObjResult(interp, Tcl_NewBooleanObj(((Vdbe *)pStmt)->usesStmtJournal));
2383: return TCL_OK;
2384: }
2385:
2386:
2387: /*
2388: ** Usage: sqlite3_reset STMT
2389: **
2390: ** Reset a statement handle.
2391: */
2392: static int test_reset(
2393: void * clientData,
2394: Tcl_Interp *interp,
2395: int objc,
2396: Tcl_Obj *CONST objv[]
2397: ){
2398: sqlite3_stmt *pStmt;
2399: int rc;
2400:
2401: if( objc!=2 ){
2402: Tcl_AppendResult(interp, "wrong # args: should be \"",
2403: Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
2404: return TCL_ERROR;
2405: }
2406:
2407: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2408:
2409: rc = sqlite3_reset(pStmt);
2410: if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){
2411: return TCL_ERROR;
2412: }
2413: Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
2414: /*
2415: if( rc ){
2416: return TCL_ERROR;
2417: }
2418: */
2419: return TCL_OK;
2420: }
2421:
2422: /*
2423: ** Usage: sqlite3_expired STMT
2424: **
2425: ** Return TRUE if a recompilation of the statement is recommended.
2426: */
2427: static int test_expired(
2428: void * clientData,
2429: Tcl_Interp *interp,
2430: int objc,
2431: Tcl_Obj *CONST objv[]
2432: ){
2433: #ifndef SQLITE_OMIT_DEPRECATED
2434: sqlite3_stmt *pStmt;
2435: if( objc!=2 ){
2436: Tcl_AppendResult(interp, "wrong # args: should be \"",
2437: Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
2438: return TCL_ERROR;
2439: }
2440: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2441: Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt)));
2442: #endif
2443: return TCL_OK;
2444: }
2445:
2446: /*
2447: ** Usage: sqlite3_transfer_bindings FROMSTMT TOSTMT
2448: **
2449: ** Transfer all bindings from FROMSTMT over to TOSTMT
2450: */
2451: static int test_transfer_bind(
2452: void * clientData,
2453: Tcl_Interp *interp,
2454: int objc,
2455: Tcl_Obj *CONST objv[]
2456: ){
2457: #ifndef SQLITE_OMIT_DEPRECATED
2458: sqlite3_stmt *pStmt1, *pStmt2;
2459: if( objc!=3 ){
2460: Tcl_AppendResult(interp, "wrong # args: should be \"",
2461: Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0);
2462: return TCL_ERROR;
2463: }
2464: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR;
2465: if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR;
2466: Tcl_SetObjResult(interp,
2467: Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2)));
2468: #endif
2469: return TCL_OK;
2470: }
2471:
2472: /*
2473: ** Usage: sqlite3_changes DB
2474: **
2475: ** Return the number of changes made to the database by the last SQL
2476: ** execution.
2477: */
2478: static int test_changes(
2479: void * clientData,
2480: Tcl_Interp *interp,
2481: int objc,
2482: Tcl_Obj *CONST objv[]
2483: ){
2484: sqlite3 *db;
2485: if( objc!=2 ){
2486: Tcl_AppendResult(interp, "wrong # args: should be \"",
2487: Tcl_GetString(objv[0]), " DB", 0);
2488: return TCL_ERROR;
2489: }
2490: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2491: Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
2492: return TCL_OK;
2493: }
2494:
2495: /*
2496: ** This is the "static_bind_value" that variables are bound to when
2497: ** the FLAG option of sqlite3_bind is "static"
2498: */
2499: static char *sqlite_static_bind_value = 0;
2500: static int sqlite_static_bind_nbyte = 0;
2501:
2502: /*
2503: ** Usage: sqlite3_bind VM IDX VALUE FLAGS
2504: **
2505: ** Sets the value of the IDX-th occurance of "?" in the original SQL
2506: ** string. VALUE is the new value. If FLAGS=="null" then VALUE is
2507: ** ignored and the value is set to NULL. If FLAGS=="static" then
2508: ** the value is set to the value of a static variable named
2509: ** "sqlite_static_bind_value". If FLAGS=="normal" then a copy
2510: ** of the VALUE is made. If FLAGS=="blob10" then a VALUE is ignored
2511: ** an a 10-byte blob "abc\000xyz\000pq" is inserted.
2512: */
2513: static int test_bind(
2514: void *NotUsed,
2515: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
2516: int argc, /* Number of arguments */
2517: char **argv /* Text of each argument */
2518: ){
2519: sqlite3_stmt *pStmt;
2520: int rc;
2521: int idx;
2522: if( argc!=5 ){
2523: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2524: " VM IDX VALUE (null|static|normal)\"", 0);
2525: return TCL_ERROR;
2526: }
2527: if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
2528: if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
2529: if( strcmp(argv[4],"null")==0 ){
2530: rc = sqlite3_bind_null(pStmt, idx);
2531: }else if( strcmp(argv[4],"static")==0 ){
2532: rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
2533: }else if( strcmp(argv[4],"static-nbytes")==0 ){
2534: rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value,
2535: sqlite_static_bind_nbyte, 0);
2536: }else if( strcmp(argv[4],"normal")==0 ){
2537: rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
2538: }else if( strcmp(argv[4],"blob10")==0 ){
2539: rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC);
2540: }else{
2541: Tcl_AppendResult(interp, "4th argument should be "
2542: "\"null\" or \"static\" or \"normal\"", 0);
2543: return TCL_ERROR;
2544: }
2545: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
2546: if( rc ){
2547: char zBuf[50];
2548: sprintf(zBuf, "(%d) ", rc);
2549: Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
2550: return TCL_ERROR;
2551: }
2552: return TCL_OK;
2553: }
2554:
2555: #ifndef SQLITE_OMIT_UTF16
2556: /*
2557: ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
2558: **
2559: ** This function is used to test that SQLite selects the correct collation
2560: ** sequence callback when multiple versions (for different text encodings)
2561: ** are available.
2562: **
2563: ** Calling this routine registers the collation sequence "test_collate"
2564: ** with database handle <db>. The second argument must be a list of three
2565: ** boolean values. If the first is true, then a version of test_collate is
2566: ** registered for UTF-8, if the second is true, a version is registered for
2567: ** UTF-16le, if the third is true, a UTF-16be version is available.
2568: ** Previous versions of test_collate are deleted.
2569: **
2570: ** The collation sequence test_collate is implemented by calling the
2571: ** following TCL script:
2572: **
2573: ** "test_collate <enc> <lhs> <rhs>"
2574: **
2575: ** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
2576: ** The <enc> parameter is the encoding of the collation function that
2577: ** SQLite selected to call. The TCL test script implements the
2578: ** "test_collate" proc.
2579: **
2580: ** Note that this will only work with one intepreter at a time, as the
2581: ** interp pointer to use when evaluating the TCL script is stored in
2582: ** pTestCollateInterp.
2583: */
2584: static Tcl_Interp* pTestCollateInterp;
2585: static int test_collate_func(
2586: void *pCtx,
2587: int nA, const void *zA,
2588: int nB, const void *zB
2589: ){
2590: Tcl_Interp *i = pTestCollateInterp;
2591: int encin = SQLITE_PTR_TO_INT(pCtx);
2592: int res;
2593: int n;
2594:
2595: sqlite3_value *pVal;
2596: Tcl_Obj *pX;
2597:
2598: pX = Tcl_NewStringObj("test_collate", -1);
2599: Tcl_IncrRefCount(pX);
2600:
2601: switch( encin ){
2602: case SQLITE_UTF8:
2603: Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
2604: break;
2605: case SQLITE_UTF16LE:
2606: Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
2607: break;
2608: case SQLITE_UTF16BE:
2609: Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
2610: break;
2611: default:
2612: assert(0);
2613: }
2614:
2615: sqlite3BeginBenignMalloc();
2616: pVal = sqlite3ValueNew(0);
2617: if( pVal ){
2618: sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
2619: n = sqlite3_value_bytes(pVal);
2620: Tcl_ListObjAppendElement(i,pX,
2621: Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
2622: sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
2623: n = sqlite3_value_bytes(pVal);
2624: Tcl_ListObjAppendElement(i,pX,
2625: Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
2626: sqlite3ValueFree(pVal);
2627: }
2628: sqlite3EndBenignMalloc();
2629:
2630: Tcl_EvalObjEx(i, pX, 0);
2631: Tcl_DecrRefCount(pX);
2632: Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
2633: return res;
2634: }
2635: static int test_collate(
2636: void * clientData,
2637: Tcl_Interp *interp,
2638: int objc,
2639: Tcl_Obj *CONST objv[]
2640: ){
2641: sqlite3 *db;
2642: int val;
2643: sqlite3_value *pVal;
2644: int rc;
2645:
2646: if( objc!=5 ) goto bad_args;
2647: pTestCollateInterp = interp;
2648: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2649:
2650: if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
2651: rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
2652: (void *)SQLITE_UTF8, val?test_collate_func:0);
2653: if( rc==SQLITE_OK ){
2654: const void *zUtf16;
2655: if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
2656: rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
2657: (void *)SQLITE_UTF16LE, val?test_collate_func:0);
2658: if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
2659:
2660: #if 0
2661: if( sqlite3_iMallocFail>0 ){
2662: sqlite3_iMallocFail++;
2663: }
2664: #endif
2665: sqlite3_mutex_enter(db->mutex);
2666: pVal = sqlite3ValueNew(db);
2667: sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
2668: zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
2669: if( db->mallocFailed ){
2670: rc = SQLITE_NOMEM;
2671: }else{
2672: rc = sqlite3_create_collation16(db, zUtf16, SQLITE_UTF16BE,
2673: (void *)SQLITE_UTF16BE, val?test_collate_func:0);
2674: }
2675: sqlite3ValueFree(pVal);
2676: sqlite3_mutex_leave(db->mutex);
2677: }
2678: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
2679:
2680: if( rc!=SQLITE_OK ){
2681: Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
2682: return TCL_ERROR;
2683: }
2684: return TCL_OK;
2685:
2686: bad_args:
2687: Tcl_AppendResult(interp, "wrong # args: should be \"",
2688: Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
2689: return TCL_ERROR;
2690: }
2691:
2692: /*
2693: ** When the collation needed callback is invoked, record the name of
2694: ** the requested collating function here. The recorded name is linked
2695: ** to a TCL variable and used to make sure that the requested collation
2696: ** name is correct.
2697: */
2698: static char zNeededCollation[200];
2699: static char *pzNeededCollation = zNeededCollation;
2700:
2701:
2702: /*
2703: ** Called when a collating sequence is needed. Registered using
2704: ** sqlite3_collation_needed16().
2705: */
2706: static void test_collate_needed_cb(
2707: void *pCtx,
2708: sqlite3 *db,
2709: int eTextRep,
2710: const void *pName
2711: ){
2712: int enc = ENC(db);
2713: int i;
2714: char *z;
2715: for(z = (char*)pName, i=0; *z || z[1]; z++){
2716: if( *z ) zNeededCollation[i++] = *z;
2717: }
2718: zNeededCollation[i] = 0;
2719: sqlite3_create_collation(
2720: db, "test_collate", ENC(db), SQLITE_INT_TO_PTR(enc), test_collate_func);
2721: }
2722:
2723: /*
2724: ** Usage: add_test_collate_needed DB
2725: */
2726: static int test_collate_needed(
2727: void * clientData,
2728: Tcl_Interp *interp,
2729: int objc,
2730: Tcl_Obj *CONST objv[]
2731: ){
2732: sqlite3 *db;
2733: int rc;
2734:
2735: if( objc!=2 ) goto bad_args;
2736: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2737: rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
2738: zNeededCollation[0] = 0;
2739: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
2740: return TCL_OK;
2741:
2742: bad_args:
2743: Tcl_WrongNumArgs(interp, 1, objv, "DB");
2744: return TCL_ERROR;
2745: }
2746:
2747: /*
2748: ** tclcmd: add_alignment_test_collations DB
2749: **
2750: ** Add two new collating sequences to the database DB
2751: **
2752: ** utf16_aligned
2753: ** utf16_unaligned
2754: **
2755: ** Both collating sequences use the same sort order as BINARY.
2756: ** The only difference is that the utf16_aligned collating
2757: ** sequence is declared with the SQLITE_UTF16_ALIGNED flag.
2758: ** Both collating functions increment the unaligned utf16 counter
2759: ** whenever they see a string that begins on an odd byte boundary.
2760: */
2761: static int unaligned_string_counter = 0;
2762: static int alignmentCollFunc(
2763: void *NotUsed,
2764: int nKey1, const void *pKey1,
2765: int nKey2, const void *pKey2
2766: ){
2767: int rc, n;
2768: n = nKey1<nKey2 ? nKey1 : nKey2;
2769: if( nKey1>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey1))) ) unaligned_string_counter++;
2770: if( nKey2>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey2))) ) unaligned_string_counter++;
2771: rc = memcmp(pKey1, pKey2, n);
2772: if( rc==0 ){
2773: rc = nKey1 - nKey2;
2774: }
2775: return rc;
2776: }
2777: static int add_alignment_test_collations(
2778: void * clientData,
2779: Tcl_Interp *interp,
2780: int objc,
2781: Tcl_Obj *CONST objv[]
2782: ){
2783: sqlite3 *db;
2784: if( objc>=2 ){
2785: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2786: sqlite3_create_collation(db, "utf16_unaligned", SQLITE_UTF16,
2787: 0, alignmentCollFunc);
2788: sqlite3_create_collation(db, "utf16_aligned", SQLITE_UTF16_ALIGNED,
2789: 0, alignmentCollFunc);
2790: }
2791: return SQLITE_OK;
2792: }
2793: #endif /* !defined(SQLITE_OMIT_UTF16) */
2794:
2795: /*
2796: ** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
2797: **
2798: ** This function is used to test that SQLite selects the correct user
2799: ** function callback when multiple versions (for different text encodings)
2800: ** are available.
2801: **
2802: ** Calling this routine registers up to three versions of the user function
2803: ** "test_function" with database handle <db>. If the second argument is
2804: ** true, then a version of test_function is registered for UTF-8, if the
2805: ** third is true, a version is registered for UTF-16le, if the fourth is
2806: ** true, a UTF-16be version is available. Previous versions of
2807: ** test_function are deleted.
2808: **
2809: ** The user function is implemented by calling the following TCL script:
2810: **
2811: ** "test_function <enc> <arg>"
2812: **
2813: ** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
2814: ** single argument passed to the SQL function. The value returned by
2815: ** the TCL script is used as the return value of the SQL function. It
2816: ** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
2817: ** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
2818: ** prefers UTF-16BE.
2819: */
2820: #ifndef SQLITE_OMIT_UTF16
2821: static void test_function_utf8(
2822: sqlite3_context *pCtx,
2823: int nArg,
2824: sqlite3_value **argv
2825: ){
2826: Tcl_Interp *interp;
2827: Tcl_Obj *pX;
2828: sqlite3_value *pVal;
2829: interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
2830: pX = Tcl_NewStringObj("test_function", -1);
2831: Tcl_IncrRefCount(pX);
2832: Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
2833: Tcl_ListObjAppendElement(interp, pX,
2834: Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
2835: Tcl_EvalObjEx(interp, pX, 0);
2836: Tcl_DecrRefCount(pX);
2837: sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
2838: pVal = sqlite3ValueNew(0);
2839: sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
2840: SQLITE_UTF8, SQLITE_STATIC);
2841: sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
2842: -1, SQLITE_TRANSIENT);
2843: sqlite3ValueFree(pVal);
2844: }
2845: static void test_function_utf16le(
2846: sqlite3_context *pCtx,
2847: int nArg,
2848: sqlite3_value **argv
2849: ){
2850: Tcl_Interp *interp;
2851: Tcl_Obj *pX;
2852: sqlite3_value *pVal;
2853: interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
2854: pX = Tcl_NewStringObj("test_function", -1);
2855: Tcl_IncrRefCount(pX);
2856: Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
2857: Tcl_ListObjAppendElement(interp, pX,
2858: Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
2859: Tcl_EvalObjEx(interp, pX, 0);
2860: Tcl_DecrRefCount(pX);
2861: pVal = sqlite3ValueNew(0);
2862: sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
2863: SQLITE_UTF8, SQLITE_STATIC);
2864: sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
2865: sqlite3ValueFree(pVal);
2866: }
2867: static void test_function_utf16be(
2868: sqlite3_context *pCtx,
2869: int nArg,
2870: sqlite3_value **argv
2871: ){
2872: Tcl_Interp *interp;
2873: Tcl_Obj *pX;
2874: sqlite3_value *pVal;
2875: interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
2876: pX = Tcl_NewStringObj("test_function", -1);
2877: Tcl_IncrRefCount(pX);
2878: Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
2879: Tcl_ListObjAppendElement(interp, pX,
2880: Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
2881: Tcl_EvalObjEx(interp, pX, 0);
2882: Tcl_DecrRefCount(pX);
2883: pVal = sqlite3ValueNew(0);
2884: sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
2885: SQLITE_UTF8, SQLITE_STATIC);
2886: sqlite3_result_text16(pCtx, sqlite3_value_text16le(pVal),
2887: -1, SQLITE_TRANSIENT);
2888: sqlite3_result_text16be(pCtx, sqlite3_value_text16le(pVal),
2889: -1, SQLITE_TRANSIENT);
2890: sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
2891: -1, SQLITE_TRANSIENT);
2892: sqlite3ValueFree(pVal);
2893: }
2894: #endif /* SQLITE_OMIT_UTF16 */
2895: static int test_function(
2896: void * clientData,
2897: Tcl_Interp *interp,
2898: int objc,
2899: Tcl_Obj *CONST objv[]
2900: ){
2901: #ifndef SQLITE_OMIT_UTF16
2902: sqlite3 *db;
2903: int val;
2904:
2905: if( objc!=5 ) goto bad_args;
2906: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2907:
2908: if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
2909: if( val ){
2910: sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
2911: interp, test_function_utf8, 0, 0);
2912: }
2913: if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
2914: if( val ){
2915: sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
2916: interp, test_function_utf16le, 0, 0);
2917: }
2918: if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
2919: if( val ){
2920: sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
2921: interp, test_function_utf16be, 0, 0);
2922: }
2923:
2924: return TCL_OK;
2925: bad_args:
2926: Tcl_AppendResult(interp, "wrong # args: should be \"",
2927: Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
2928: #endif /* SQLITE_OMIT_UTF16 */
2929: return TCL_ERROR;
2930: }
2931:
2932: /*
2933: ** Usage: sqlite3_test_errstr <err code>
2934: **
2935: ** Test that the english language string equivalents for sqlite error codes
2936: ** are sane. The parameter is an integer representing an sqlite error code.
2937: ** The result is a list of two elements, the string representation of the
2938: ** error code and the english language explanation.
2939: */
2940: static int test_errstr(
2941: void * clientData,
2942: Tcl_Interp *interp,
2943: int objc,
2944: Tcl_Obj *CONST objv[]
2945: ){
2946: char *zCode;
2947: int i;
2948: if( objc!=1 ){
2949: Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
2950: }
2951:
2952: zCode = Tcl_GetString(objv[1]);
2953: for(i=0; i<200; i++){
2954: if( 0==strcmp(t1ErrorName(i), zCode) ) break;
2955: }
2956: Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
2957: return TCL_OK;
2958: }
2959:
2960: /*
2961: ** Usage: breakpoint
2962: **
2963: ** This routine exists for one purpose - to provide a place to put a
2964: ** breakpoint with GDB that can be triggered using TCL code. The use
2965: ** for this is when a particular test fails on (say) the 1485th iteration.
2966: ** In the TCL test script, we can add code like this:
2967: **
2968: ** if {$i==1485} breakpoint
2969: **
2970: ** Then run testfixture in the debugger and wait for the breakpoint to
2971: ** fire. Then additional breakpoints can be set to trace down the bug.
2972: */
2973: static int test_breakpoint(
2974: void *NotUsed,
2975: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
2976: int argc, /* Number of arguments */
2977: char **argv /* Text of each argument */
2978: ){
2979: return TCL_OK; /* Do nothing */
2980: }
2981:
2982: /*
2983: ** Usage: sqlite3_bind_zeroblob STMT IDX N
2984: **
2985: ** Test the sqlite3_bind_zeroblob interface. STMT is a prepared statement.
2986: ** IDX is the index of a wildcard in the prepared statement. This command
2987: ** binds a N-byte zero-filled BLOB to the wildcard.
2988: */
2989: static int test_bind_zeroblob(
2990: void * clientData,
2991: Tcl_Interp *interp,
2992: int objc,
2993: Tcl_Obj *CONST objv[]
2994: ){
2995: sqlite3_stmt *pStmt;
2996: int idx;
2997: int n;
2998: int rc;
2999:
3000: if( objc!=4 ){
3001: Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N");
3002: return TCL_ERROR;
3003: }
3004:
3005: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3006: if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3007: if( Tcl_GetIntFromObj(interp, objv[3], &n) ) return TCL_ERROR;
3008:
3009: rc = sqlite3_bind_zeroblob(pStmt, idx, n);
3010: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3011: if( rc!=SQLITE_OK ){
3012: return TCL_ERROR;
3013: }
3014:
3015: return TCL_OK;
3016: }
3017:
3018: /*
3019: ** Usage: sqlite3_bind_int STMT N VALUE
3020: **
3021: ** Test the sqlite3_bind_int interface. STMT is a prepared statement.
3022: ** N is the index of a wildcard in the prepared statement. This command
3023: ** binds a 32-bit integer VALUE to that wildcard.
3024: */
3025: static int test_bind_int(
3026: void * clientData,
3027: Tcl_Interp *interp,
3028: int objc,
3029: Tcl_Obj *CONST objv[]
3030: ){
3031: sqlite3_stmt *pStmt;
3032: int idx;
3033: int value;
3034: int rc;
3035:
3036: if( objc!=4 ){
3037: Tcl_AppendResult(interp, "wrong # args: should be \"",
3038: Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
3039: return TCL_ERROR;
3040: }
3041:
3042: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3043: if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3044: if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
3045:
3046: rc = sqlite3_bind_int(pStmt, idx, value);
3047: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3048: if( rc!=SQLITE_OK ){
3049: return TCL_ERROR;
3050: }
3051:
3052: return TCL_OK;
3053: }
3054:
3055:
3056: /*
3057: ** Usage: sqlite3_bind_int64 STMT N VALUE
3058: **
3059: ** Test the sqlite3_bind_int64 interface. STMT is a prepared statement.
3060: ** N is the index of a wildcard in the prepared statement. This command
3061: ** binds a 64-bit integer VALUE to that wildcard.
3062: */
3063: static int test_bind_int64(
3064: void * clientData,
3065: Tcl_Interp *interp,
3066: int objc,
3067: Tcl_Obj *CONST objv[]
3068: ){
3069: sqlite3_stmt *pStmt;
3070: int idx;
3071: i64 value;
3072: int rc;
3073:
3074: if( objc!=4 ){
3075: Tcl_AppendResult(interp, "wrong # args: should be \"",
3076: Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
3077: return TCL_ERROR;
3078: }
3079:
3080: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3081: if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3082: if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
3083:
3084: rc = sqlite3_bind_int64(pStmt, idx, value);
3085: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3086: if( rc!=SQLITE_OK ){
3087: return TCL_ERROR;
3088: }
3089:
3090: return TCL_OK;
3091: }
3092:
3093:
3094: /*
3095: ** Usage: sqlite3_bind_double STMT N VALUE
3096: **
3097: ** Test the sqlite3_bind_double interface. STMT is a prepared statement.
3098: ** N is the index of a wildcard in the prepared statement. This command
3099: ** binds a 64-bit integer VALUE to that wildcard.
3100: */
3101: static int test_bind_double(
3102: void * clientData,
3103: Tcl_Interp *interp,
3104: int objc,
3105: Tcl_Obj *CONST objv[]
3106: ){
3107: sqlite3_stmt *pStmt;
3108: int idx;
3109: double value;
3110: int rc;
3111: const char *zVal;
3112: int i;
3113: static const struct {
3114: const char *zName; /* Name of the special floating point value */
3115: unsigned int iUpper; /* Upper 32 bits */
3116: unsigned int iLower; /* Lower 32 bits */
3117: } aSpecialFp[] = {
3118: { "NaN", 0x7fffffff, 0xffffffff },
3119: { "SNaN", 0x7ff7ffff, 0xffffffff },
3120: { "-NaN", 0xffffffff, 0xffffffff },
3121: { "-SNaN", 0xfff7ffff, 0xffffffff },
3122: { "+Inf", 0x7ff00000, 0x00000000 },
3123: { "-Inf", 0xfff00000, 0x00000000 },
3124: { "Epsilon", 0x00000000, 0x00000001 },
3125: { "-Epsilon", 0x80000000, 0x00000001 },
3126: { "NaN0", 0x7ff80000, 0x00000000 },
3127: { "-NaN0", 0xfff80000, 0x00000000 },
3128: };
3129:
3130: if( objc!=4 ){
3131: Tcl_AppendResult(interp, "wrong # args: should be \"",
3132: Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
3133: return TCL_ERROR;
3134: }
3135:
3136: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3137: if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3138:
3139: /* Intercept the string "NaN" and generate a NaN value for it.
3140: ** All other strings are passed through to Tcl_GetDoubleFromObj().
3141: ** Tcl_GetDoubleFromObj() should understand "NaN" but some versions
3142: ** contain a bug.
3143: */
3144: zVal = Tcl_GetString(objv[3]);
3145: for(i=0; i<sizeof(aSpecialFp)/sizeof(aSpecialFp[0]); i++){
3146: if( strcmp(aSpecialFp[i].zName, zVal)==0 ){
3147: sqlite3_uint64 x;
3148: x = aSpecialFp[i].iUpper;
3149: x <<= 32;
3150: x |= aSpecialFp[i].iLower;
3151: assert( sizeof(value)==8 );
3152: assert( sizeof(x)==8 );
3153: memcpy(&value, &x, 8);
3154: break;
3155: }
3156: }
3157: if( i>=sizeof(aSpecialFp)/sizeof(aSpecialFp[0]) &&
3158: Tcl_GetDoubleFromObj(interp, objv[3], &value) ){
3159: return TCL_ERROR;
3160: }
3161: rc = sqlite3_bind_double(pStmt, idx, value);
3162: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3163: if( rc!=SQLITE_OK ){
3164: return TCL_ERROR;
3165: }
3166:
3167: return TCL_OK;
3168: }
3169:
3170: /*
3171: ** Usage: sqlite3_bind_null STMT N
3172: **
3173: ** Test the sqlite3_bind_null interface. STMT is a prepared statement.
3174: ** N is the index of a wildcard in the prepared statement. This command
3175: ** binds a NULL to the wildcard.
3176: */
3177: static int test_bind_null(
3178: void * clientData,
3179: Tcl_Interp *interp,
3180: int objc,
3181: Tcl_Obj *CONST objv[]
3182: ){
3183: sqlite3_stmt *pStmt;
3184: int idx;
3185: int rc;
3186:
3187: if( objc!=3 ){
3188: Tcl_AppendResult(interp, "wrong # args: should be \"",
3189: Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
3190: return TCL_ERROR;
3191: }
3192:
3193: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3194: if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3195:
3196: rc = sqlite3_bind_null(pStmt, idx);
3197: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3198: if( rc!=SQLITE_OK ){
3199: return TCL_ERROR;
3200: }
3201:
3202: return TCL_OK;
3203: }
3204:
3205: /*
3206: ** Usage: sqlite3_bind_text STMT N STRING BYTES
3207: **
3208: ** Test the sqlite3_bind_text interface. STMT is a prepared statement.
3209: ** N is the index of a wildcard in the prepared statement. This command
3210: ** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes
3211: ** long.
3212: */
3213: static int test_bind_text(
3214: void * clientData,
3215: Tcl_Interp *interp,
3216: int objc,
3217: Tcl_Obj *CONST objv[]
3218: ){
3219: sqlite3_stmt *pStmt;
3220: int idx;
3221: int bytes;
3222: char *value;
3223: int rc;
3224:
3225: if( objc!=5 ){
3226: Tcl_AppendResult(interp, "wrong # args: should be \"",
3227: Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
3228: return TCL_ERROR;
3229: }
3230:
3231: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3232: if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3233: value = (char*)Tcl_GetByteArrayFromObj(objv[3], &bytes);
3234: if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
3235:
3236: rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
3237: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3238: if( rc!=SQLITE_OK ){
3239: Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
3240: return TCL_ERROR;
3241: }
3242:
3243: return TCL_OK;
3244: }
3245:
3246: /*
3247: ** Usage: sqlite3_bind_text16 ?-static? STMT N STRING BYTES
3248: **
3249: ** Test the sqlite3_bind_text16 interface. STMT is a prepared statement.
3250: ** N is the index of a wildcard in the prepared statement. This command
3251: ** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes
3252: ** long.
3253: */
3254: static int test_bind_text16(
3255: void * clientData,
3256: Tcl_Interp *interp,
3257: int objc,
3258: Tcl_Obj *CONST objv[]
3259: ){
3260: #ifndef SQLITE_OMIT_UTF16
3261: sqlite3_stmt *pStmt;
3262: int idx;
3263: int bytes;
3264: char *value;
3265: int rc;
3266:
3267: void (*xDel)() = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
3268: Tcl_Obj *oStmt = objv[objc-4];
3269: Tcl_Obj *oN = objv[objc-3];
3270: Tcl_Obj *oString = objv[objc-2];
3271: Tcl_Obj *oBytes = objv[objc-1];
3272:
3273: if( objc!=5 && objc!=6){
3274: Tcl_AppendResult(interp, "wrong # args: should be \"",
3275: Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
3276: return TCL_ERROR;
3277: }
3278:
3279: if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR;
3280: if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR;
3281: value = (char*)Tcl_GetByteArrayFromObj(oString, 0);
3282: if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR;
3283:
3284: rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel);
3285: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3286: if( rc!=SQLITE_OK ){
3287: Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
3288: return TCL_ERROR;
3289: }
3290:
3291: #endif /* SQLITE_OMIT_UTF16 */
3292: return TCL_OK;
3293: }
3294:
3295: /*
3296: ** Usage: sqlite3_bind_blob ?-static? STMT N DATA BYTES
3297: **
3298: ** Test the sqlite3_bind_blob interface. STMT is a prepared statement.
3299: ** N is the index of a wildcard in the prepared statement. This command
3300: ** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size.
3301: */
3302: static int test_bind_blob(
3303: void * clientData,
3304: Tcl_Interp *interp,
3305: int objc,
3306: Tcl_Obj *CONST objv[]
3307: ){
3308: sqlite3_stmt *pStmt;
3309: int idx;
3310: int bytes;
3311: char *value;
3312: int rc;
3313: sqlite3_destructor_type xDestructor = SQLITE_TRANSIENT;
3314:
3315: if( objc!=5 && objc!=6 ){
3316: Tcl_AppendResult(interp, "wrong # args: should be \"",
3317: Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
3318: return TCL_ERROR;
3319: }
3320:
3321: if( objc==6 ){
3322: xDestructor = SQLITE_STATIC;
3323: objv++;
3324: }
3325:
3326: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3327: if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
3328: value = Tcl_GetString(objv[3]);
3329: if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
3330:
3331: rc = sqlite3_bind_blob(pStmt, idx, value, bytes, xDestructor);
3332: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
3333: if( rc!=SQLITE_OK ){
3334: return TCL_ERROR;
3335: }
3336:
3337: return TCL_OK;
3338: }
3339:
3340: /*
3341: ** Usage: sqlite3_bind_parameter_count STMT
3342: **
3343: ** Return the number of wildcards in the given statement.
3344: */
3345: static int test_bind_parameter_count(
3346: void * clientData,
3347: Tcl_Interp *interp,
3348: int objc,
3349: Tcl_Obj *CONST objv[]
3350: ){
3351: sqlite3_stmt *pStmt;
3352:
3353: if( objc!=2 ){
3354: Tcl_WrongNumArgs(interp, 1, objv, "STMT");
3355: return TCL_ERROR;
3356: }
3357: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3358: Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
3359: return TCL_OK;
3360: }
3361:
3362: /*
3363: ** Usage: sqlite3_bind_parameter_name STMT N
3364: **
3365: ** Return the name of the Nth wildcard. The first wildcard is 1.
3366: ** An empty string is returned if N is out of range or if the wildcard
3367: ** is nameless.
3368: */
3369: static int test_bind_parameter_name(
3370: void * clientData,
3371: Tcl_Interp *interp,
3372: int objc,
3373: Tcl_Obj *CONST objv[]
3374: ){
3375: sqlite3_stmt *pStmt;
3376: int i;
3377:
3378: if( objc!=3 ){
3379: Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
3380: return TCL_ERROR;
3381: }
3382: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3383: if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
3384: Tcl_SetObjResult(interp,
3385: Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
3386: );
3387: return TCL_OK;
3388: }
3389:
3390: /*
3391: ** Usage: sqlite3_bind_parameter_index STMT NAME
3392: **
3393: ** Return the index of the wildcard called NAME. Return 0 if there is
3394: ** no such wildcard.
3395: */
3396: static int test_bind_parameter_index(
3397: void * clientData,
3398: Tcl_Interp *interp,
3399: int objc,
3400: Tcl_Obj *CONST objv[]
3401: ){
3402: sqlite3_stmt *pStmt;
3403:
3404: if( objc!=3 ){
3405: Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
3406: return TCL_ERROR;
3407: }
3408: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3409: Tcl_SetObjResult(interp,
3410: Tcl_NewIntObj(
3411: sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
3412: )
3413: );
3414: return TCL_OK;
3415: }
3416:
3417: /*
3418: ** Usage: sqlite3_clear_bindings STMT
3419: **
3420: */
3421: static int test_clear_bindings(
3422: void * clientData,
3423: Tcl_Interp *interp,
3424: int objc,
3425: Tcl_Obj *CONST objv[]
3426: ){
3427: sqlite3_stmt *pStmt;
3428:
3429: if( objc!=2 ){
3430: Tcl_WrongNumArgs(interp, 1, objv, "STMT");
3431: return TCL_ERROR;
3432: }
3433: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3434: Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
3435: return TCL_OK;
3436: }
3437:
3438: /*
3439: ** Usage: sqlite3_sleep MILLISECONDS
3440: */
3441: static int test_sleep(
3442: void * clientData,
3443: Tcl_Interp *interp,
3444: int objc,
3445: Tcl_Obj *CONST objv[]
3446: ){
3447: int ms;
3448:
3449: if( objc!=2 ){
3450: Tcl_WrongNumArgs(interp, 1, objv, "MILLISECONDS");
3451: return TCL_ERROR;
3452: }
3453: if( Tcl_GetIntFromObj(interp, objv[1], &ms) ){
3454: return TCL_ERROR;
3455: }
3456: Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(ms)));
3457: return TCL_OK;
3458: }
3459:
3460: /*
3461: ** Usage: sqlite3_extended_errcode DB
3462: **
3463: ** Return the string representation of the most recent sqlite3_* API
3464: ** error code. e.g. "SQLITE_ERROR".
3465: */
3466: static int test_ex_errcode(
3467: void * clientData,
3468: Tcl_Interp *interp,
3469: int objc,
3470: Tcl_Obj *CONST objv[]
3471: ){
3472: sqlite3 *db;
3473: int rc;
3474:
3475: if( objc!=2 ){
3476: Tcl_AppendResult(interp, "wrong # args: should be \"",
3477: Tcl_GetString(objv[0]), " DB", 0);
3478: return TCL_ERROR;
3479: }
3480: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3481: rc = sqlite3_extended_errcode(db);
3482: Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0);
3483: return TCL_OK;
3484: }
3485:
3486:
3487: /*
3488: ** Usage: sqlite3_errcode DB
3489: **
3490: ** Return the string representation of the most recent sqlite3_* API
3491: ** error code. e.g. "SQLITE_ERROR".
3492: */
3493: static int test_errcode(
3494: void * clientData,
3495: Tcl_Interp *interp,
3496: int objc,
3497: Tcl_Obj *CONST objv[]
3498: ){
3499: sqlite3 *db;
3500: int rc;
3501:
3502: if( objc!=2 ){
3503: Tcl_AppendResult(interp, "wrong # args: should be \"",
3504: Tcl_GetString(objv[0]), " DB", 0);
3505: return TCL_ERROR;
3506: }
3507: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3508: rc = sqlite3_errcode(db);
3509: Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0);
3510: return TCL_OK;
3511: }
3512:
3513: /*
3514: ** Usage: sqlite3_errmsg DB
3515: **
3516: ** Returns the UTF-8 representation of the error message string for the
3517: ** most recent sqlite3_* API call.
3518: */
3519: static int test_errmsg(
3520: void * clientData,
3521: Tcl_Interp *interp,
3522: int objc,
3523: Tcl_Obj *CONST objv[]
3524: ){
3525: sqlite3 *db;
3526: const char *zErr;
3527:
3528: if( objc!=2 ){
3529: Tcl_AppendResult(interp, "wrong # args: should be \"",
3530: Tcl_GetString(objv[0]), " DB", 0);
3531: return TCL_ERROR;
3532: }
3533: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3534:
3535: zErr = sqlite3_errmsg(db);
3536: Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
3537: return TCL_OK;
3538: }
3539:
3540: /*
3541: ** Usage: test_errmsg16 DB
3542: **
3543: ** Returns the UTF-16 representation of the error message string for the
3544: ** most recent sqlite3_* API call. This is a byte array object at the TCL
3545: ** level, and it includes the 0x00 0x00 terminator bytes at the end of the
3546: ** UTF-16 string.
3547: */
3548: static int test_errmsg16(
3549: void * clientData,
3550: Tcl_Interp *interp,
3551: int objc,
3552: Tcl_Obj *CONST objv[]
3553: ){
3554: #ifndef SQLITE_OMIT_UTF16
3555: sqlite3 *db;
3556: const void *zErr;
3557: const char *z;
3558: int bytes = 0;
3559:
3560: if( objc!=2 ){
3561: Tcl_AppendResult(interp, "wrong # args: should be \"",
3562: Tcl_GetString(objv[0]), " DB", 0);
3563: return TCL_ERROR;
3564: }
3565: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3566:
3567: zErr = sqlite3_errmsg16(db);
3568: if( zErr ){
3569: z = zErr;
3570: for(bytes=0; z[bytes] || z[bytes+1]; bytes+=2){}
3571: }
3572: Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
3573: #endif /* SQLITE_OMIT_UTF16 */
3574: return TCL_OK;
3575: }
3576:
3577: /*
3578: ** Usage: sqlite3_prepare DB sql bytes ?tailvar?
3579: **
3580: ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
3581: ** database handle <DB>. The parameter <tailval> is the name of a global
3582: ** variable that is set to the unused portion of <sql> (if any). A
3583: ** STMT handle is returned.
3584: */
3585: static int test_prepare(
3586: void * clientData,
3587: Tcl_Interp *interp,
3588: int objc,
3589: Tcl_Obj *CONST objv[]
3590: ){
3591: sqlite3 *db;
3592: const char *zSql;
3593: int bytes;
3594: const char *zTail = 0;
3595: sqlite3_stmt *pStmt = 0;
3596: char zBuf[50];
3597: int rc;
3598:
3599: if( objc!=5 && objc!=4 ){
3600: Tcl_AppendResult(interp, "wrong # args: should be \"",
3601: Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
3602: return TCL_ERROR;
3603: }
3604: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3605: zSql = Tcl_GetString(objv[2]);
3606: if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
3607:
3608: rc = sqlite3_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
3609: Tcl_ResetResult(interp);
3610: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
3611: if( zTail && objc>=5 ){
3612: if( bytes>=0 ){
3613: bytes = bytes - (zTail-zSql);
3614: }
3615: if( strlen(zTail)<bytes ){
3616: bytes = strlen(zTail);
3617: }
3618: Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
3619: }
3620: if( rc!=SQLITE_OK ){
3621: assert( pStmt==0 );
3622: sprintf(zBuf, "(%d) ", rc);
3623: Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
3624: return TCL_ERROR;
3625: }
3626:
3627: if( pStmt ){
3628: if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
3629: Tcl_AppendResult(interp, zBuf, 0);
3630: }
3631: return TCL_OK;
3632: }
3633:
3634: /*
3635: ** Usage: sqlite3_prepare_v2 DB sql bytes ?tailvar?
3636: **
3637: ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
3638: ** database handle <DB>. The parameter <tailval> is the name of a global
3639: ** variable that is set to the unused portion of <sql> (if any). A
3640: ** STMT handle is returned.
3641: */
3642: static int test_prepare_v2(
3643: void * clientData,
3644: Tcl_Interp *interp,
3645: int objc,
3646: Tcl_Obj *CONST objv[]
3647: ){
3648: sqlite3 *db;
3649: const char *zSql;
3650: int bytes;
3651: const char *zTail = 0;
3652: sqlite3_stmt *pStmt = 0;
3653: char zBuf[50];
3654: int rc;
3655:
3656: if( objc!=5 && objc!=4 ){
3657: Tcl_AppendResult(interp, "wrong # args: should be \"",
3658: Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
3659: return TCL_ERROR;
3660: }
3661: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3662: zSql = Tcl_GetString(objv[2]);
3663: if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
3664:
3665: rc = sqlite3_prepare_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
3666: assert(rc==SQLITE_OK || pStmt==0);
3667: Tcl_ResetResult(interp);
3668: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
3669: if( zTail && objc>=5 ){
3670: if( bytes>=0 ){
3671: bytes = bytes - (zTail-zSql);
3672: }
3673: Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
3674: }
3675: if( rc!=SQLITE_OK ){
3676: assert( pStmt==0 );
3677: sprintf(zBuf, "(%d) ", rc);
3678: Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
3679: return TCL_ERROR;
3680: }
3681:
3682: if( pStmt ){
3683: if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
3684: Tcl_AppendResult(interp, zBuf, 0);
3685: }
3686: return TCL_OK;
3687: }
3688:
3689: /*
3690: ** Usage: sqlite3_prepare_tkt3134 DB
3691: **
3692: ** Generate a prepared statement for a zero-byte string as a test
3693: ** for ticket #3134. The string should be preceeded by a zero byte.
3694: */
3695: static int test_prepare_tkt3134(
3696: void * clientData,
3697: Tcl_Interp *interp,
3698: int objc,
3699: Tcl_Obj *CONST objv[]
3700: ){
3701: sqlite3 *db;
3702: static const char zSql[] = "\000SELECT 1";
3703: sqlite3_stmt *pStmt = 0;
3704: char zBuf[50];
3705: int rc;
3706:
3707: if( objc!=2 ){
3708: Tcl_AppendResult(interp, "wrong # args: should be \"",
3709: Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
3710: return TCL_ERROR;
3711: }
3712: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3713: rc = sqlite3_prepare_v2(db, &zSql[1], 0, &pStmt, 0);
3714: assert(rc==SQLITE_OK || pStmt==0);
3715: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
3716: if( rc!=SQLITE_OK ){
3717: assert( pStmt==0 );
3718: sprintf(zBuf, "(%d) ", rc);
3719: Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
3720: return TCL_ERROR;
3721: }
3722:
3723: if( pStmt ){
3724: if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
3725: Tcl_AppendResult(interp, zBuf, 0);
3726: }
3727: return TCL_OK;
3728: }
3729:
3730: /*
3731: ** Usage: sqlite3_prepare16 DB sql bytes tailvar
3732: **
3733: ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
3734: ** database handle <DB>. The parameter <tailval> is the name of a global
3735: ** variable that is set to the unused portion of <sql> (if any). A
3736: ** STMT handle is returned.
3737: */
3738: static int test_prepare16(
3739: void * clientData,
3740: Tcl_Interp *interp,
3741: int objc,
3742: Tcl_Obj *CONST objv[]
3743: ){
3744: #ifndef SQLITE_OMIT_UTF16
3745: sqlite3 *db;
3746: const void *zSql;
3747: const void *zTail = 0;
3748: Tcl_Obj *pTail = 0;
3749: sqlite3_stmt *pStmt = 0;
3750: char zBuf[50];
3751: int rc;
3752: int bytes; /* The integer specified as arg 3 */
3753: int objlen; /* The byte-array length of arg 2 */
3754:
3755: if( objc!=5 && objc!=4 ){
3756: Tcl_AppendResult(interp, "wrong # args: should be \"",
3757: Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
3758: return TCL_ERROR;
3759: }
3760: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3761: zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
3762: if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
3763:
3764: rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
3765: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
3766: if( rc ){
3767: return TCL_ERROR;
3768: }
3769:
3770: if( objc>=5 ){
3771: if( zTail ){
3772: objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
3773: }else{
3774: objlen = 0;
3775: }
3776: pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
3777: Tcl_IncrRefCount(pTail);
3778: Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
3779: Tcl_DecrRefCount(pTail);
3780: }
3781:
3782: if( pStmt ){
3783: if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
3784: }
3785: Tcl_AppendResult(interp, zBuf, 0);
3786: #endif /* SQLITE_OMIT_UTF16 */
3787: return TCL_OK;
3788: }
3789:
3790: /*
3791: ** Usage: sqlite3_prepare16_v2 DB sql bytes ?tailvar?
3792: **
3793: ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
3794: ** database handle <DB>. The parameter <tailval> is the name of a global
3795: ** variable that is set to the unused portion of <sql> (if any). A
3796: ** STMT handle is returned.
3797: */
3798: static int test_prepare16_v2(
3799: void * clientData,
3800: Tcl_Interp *interp,
3801: int objc,
3802: Tcl_Obj *CONST objv[]
3803: ){
3804: #ifndef SQLITE_OMIT_UTF16
3805: sqlite3 *db;
3806: const void *zSql;
3807: const void *zTail = 0;
3808: Tcl_Obj *pTail = 0;
3809: sqlite3_stmt *pStmt = 0;
3810: char zBuf[50];
3811: int rc;
3812: int bytes; /* The integer specified as arg 3 */
3813: int objlen; /* The byte-array length of arg 2 */
3814:
3815: if( objc!=5 && objc!=4 ){
3816: Tcl_AppendResult(interp, "wrong # args: should be \"",
3817: Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
3818: return TCL_ERROR;
3819: }
3820: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3821: zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
3822: if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
3823:
3824: rc = sqlite3_prepare16_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
3825: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
3826: if( rc ){
3827: return TCL_ERROR;
3828: }
3829:
3830: if( objc>=5 ){
3831: if( zTail ){
3832: objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
3833: }else{
3834: objlen = 0;
3835: }
3836: pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
3837: Tcl_IncrRefCount(pTail);
3838: Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
3839: Tcl_DecrRefCount(pTail);
3840: }
3841:
3842: if( pStmt ){
3843: if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
3844: }
3845: Tcl_AppendResult(interp, zBuf, 0);
3846: #endif /* SQLITE_OMIT_UTF16 */
3847: return TCL_OK;
3848: }
3849:
3850: /*
3851: ** Usage: sqlite3_open filename ?options-list?
3852: */
3853: static int test_open(
3854: void * clientData,
3855: Tcl_Interp *interp,
3856: int objc,
3857: Tcl_Obj *CONST objv[]
3858: ){
3859: const char *zFilename;
3860: sqlite3 *db;
3861: int rc;
3862: char zBuf[100];
3863:
3864: if( objc!=3 && objc!=2 && objc!=1 ){
3865: Tcl_AppendResult(interp, "wrong # args: should be \"",
3866: Tcl_GetString(objv[0]), " filename options-list", 0);
3867: return TCL_ERROR;
3868: }
3869:
3870: zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0;
3871: rc = sqlite3_open(zFilename, &db);
3872:
3873: if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
3874: Tcl_AppendResult(interp, zBuf, 0);
3875: return TCL_OK;
3876: }
3877:
3878: /*
3879: ** Usage: sqlite3_open_v2 FILENAME FLAGS VFS
3880: */
3881: static int test_open_v2(
3882: void * clientData,
3883: Tcl_Interp *interp,
3884: int objc,
3885: Tcl_Obj *CONST objv[]
3886: ){
3887: const char *zFilename;
3888: const char *zVfs;
3889: int flags = 0;
3890: sqlite3 *db;
3891: int rc;
3892: char zBuf[100];
3893:
3894: int nFlag;
3895: Tcl_Obj **apFlag;
3896: int i;
3897:
3898: if( objc!=4 ){
3899: Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS");
3900: return TCL_ERROR;
3901: }
3902: zFilename = Tcl_GetString(objv[1]);
3903: zVfs = Tcl_GetString(objv[3]);
3904: if( zVfs[0]==0x00 ) zVfs = 0;
3905:
3906: rc = Tcl_ListObjGetElements(interp, objv[2], &nFlag, &apFlag);
3907: if( rc!=TCL_OK ) return rc;
3908: for(i=0; i<nFlag; i++){
3909: int iFlag;
3910: struct OpenFlag {
3911: const char *zFlag;
3912: int flag;
3913: } aFlag[] = {
3914: { "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY },
3915: { "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE },
3916: { "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE },
3917: { "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE },
3918: { "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE },
3919: { "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY },
3920: { "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB },
3921: { "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB },
3922: { "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB },
3923: { "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL },
3924: { "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL },
3925: { "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL },
3926: { "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL },
3927: { "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX },
3928: { "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX },
3929: { "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE },
3930: { "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE },
3931: { "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL },
3932: { "SQLITE_OPEN_URI", SQLITE_OPEN_URI },
3933: { 0, 0 }
3934: };
3935: rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]),
3936: "flag", 0, &iFlag
3937: );
3938: if( rc!=TCL_OK ) return rc;
3939: flags |= aFlag[iFlag].flag;
3940: }
3941:
3942: rc = sqlite3_open_v2(zFilename, &db, flags, zVfs);
3943: if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
3944: Tcl_AppendResult(interp, zBuf, 0);
3945: return TCL_OK;
3946: }
3947:
3948: /*
3949: ** Usage: sqlite3_open16 filename options
3950: */
3951: static int test_open16(
3952: void * clientData,
3953: Tcl_Interp *interp,
3954: int objc,
3955: Tcl_Obj *CONST objv[]
3956: ){
3957: #ifndef SQLITE_OMIT_UTF16
3958: const void *zFilename;
3959: sqlite3 *db;
3960: int rc;
3961: char zBuf[100];
3962:
3963: if( objc!=3 ){
3964: Tcl_AppendResult(interp, "wrong # args: should be \"",
3965: Tcl_GetString(objv[0]), " filename options-list", 0);
3966: return TCL_ERROR;
3967: }
3968:
3969: zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
3970: rc = sqlite3_open16(zFilename, &db);
3971:
3972: if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
3973: Tcl_AppendResult(interp, zBuf, 0);
3974: #endif /* SQLITE_OMIT_UTF16 */
3975: return TCL_OK;
3976: }
3977:
3978: /*
3979: ** Usage: sqlite3_complete16 <UTF-16 string>
3980: **
3981: ** Return 1 if the supplied argument is a complete SQL statement, or zero
3982: ** otherwise.
3983: */
3984: static int test_complete16(
3985: void * clientData,
3986: Tcl_Interp *interp,
3987: int objc,
3988: Tcl_Obj *CONST objv[]
3989: ){
3990: #if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16)
3991: char *zBuf;
3992:
3993: if( objc!=2 ){
3994: Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
3995: return TCL_ERROR;
3996: }
3997:
3998: zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0);
3999: Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
4000: #endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */
4001: return TCL_OK;
4002: }
4003:
4004: /*
4005: ** Usage: sqlite3_step STMT
4006: **
4007: ** Advance the statement to the next row.
4008: */
4009: static int test_step(
4010: void * clientData,
4011: Tcl_Interp *interp,
4012: int objc,
4013: Tcl_Obj *CONST objv[]
4014: ){
4015: sqlite3_stmt *pStmt;
4016: int rc;
4017:
4018: if( objc!=2 ){
4019: Tcl_AppendResult(interp, "wrong # args: should be \"",
4020: Tcl_GetString(objv[0]), " STMT", 0);
4021: return TCL_ERROR;
4022: }
4023:
4024: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4025: rc = sqlite3_step(pStmt);
4026:
4027: /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
4028: Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
4029: return TCL_OK;
4030: }
4031:
4032: static int test_sql(
4033: void * clientData,
4034: Tcl_Interp *interp,
4035: int objc,
4036: Tcl_Obj *CONST objv[]
4037: ){
4038: sqlite3_stmt *pStmt;
4039:
4040: if( objc!=2 ){
4041: Tcl_WrongNumArgs(interp, 1, objv, "STMT");
4042: return TCL_ERROR;
4043: }
4044:
4045: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4046: Tcl_SetResult(interp, (char *)sqlite3_sql(pStmt), TCL_VOLATILE);
4047: return TCL_OK;
4048: }
4049:
4050: /*
4051: ** Usage: sqlite3_column_count STMT
4052: **
4053: ** Return the number of columns returned by the sql statement STMT.
4054: */
4055: static int test_column_count(
4056: void * clientData,
4057: Tcl_Interp *interp,
4058: int objc,
4059: Tcl_Obj *CONST objv[]
4060: ){
4061: sqlite3_stmt *pStmt;
4062:
4063: if( objc!=2 ){
4064: Tcl_AppendResult(interp, "wrong # args: should be \"",
4065: Tcl_GetString(objv[0]), " STMT column", 0);
4066: return TCL_ERROR;
4067: }
4068:
4069: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4070:
4071: Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
4072: return TCL_OK;
4073: }
4074:
4075: /*
4076: ** Usage: sqlite3_column_type STMT column
4077: **
4078: ** Return the type of the data in column 'column' of the current row.
4079: */
4080: static int test_column_type(
4081: void * clientData,
4082: Tcl_Interp *interp,
4083: int objc,
4084: Tcl_Obj *CONST objv[]
4085: ){
4086: sqlite3_stmt *pStmt;
4087: int col;
4088: int tp;
4089:
4090: if( objc!=3 ){
4091: Tcl_AppendResult(interp, "wrong # args: should be \"",
4092: Tcl_GetString(objv[0]), " STMT column", 0);
4093: return TCL_ERROR;
4094: }
4095:
4096: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4097: if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4098:
4099: tp = sqlite3_column_type(pStmt, col);
4100: switch( tp ){
4101: case SQLITE_INTEGER:
4102: Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
4103: break;
4104: case SQLITE_NULL:
4105: Tcl_SetResult(interp, "NULL", TCL_STATIC);
4106: break;
4107: case SQLITE_FLOAT:
4108: Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
4109: break;
4110: case SQLITE_TEXT:
4111: Tcl_SetResult(interp, "TEXT", TCL_STATIC);
4112: break;
4113: case SQLITE_BLOB:
4114: Tcl_SetResult(interp, "BLOB", TCL_STATIC);
4115: break;
4116: default:
4117: assert(0);
4118: }
4119:
4120: return TCL_OK;
4121: }
4122:
4123: /*
4124: ** Usage: sqlite3_column_int64 STMT column
4125: **
4126: ** Return the data in column 'column' of the current row cast as an
4127: ** wide (64-bit) integer.
4128: */
4129: static int test_column_int64(
4130: void * clientData,
4131: Tcl_Interp *interp,
4132: int objc,
4133: Tcl_Obj *CONST objv[]
4134: ){
4135: sqlite3_stmt *pStmt;
4136: int col;
4137: i64 iVal;
4138:
4139: if( objc!=3 ){
4140: Tcl_AppendResult(interp, "wrong # args: should be \"",
4141: Tcl_GetString(objv[0]), " STMT column", 0);
4142: return TCL_ERROR;
4143: }
4144:
4145: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4146: if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4147:
4148: iVal = sqlite3_column_int64(pStmt, col);
4149: Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
4150: return TCL_OK;
4151: }
4152:
4153: /*
4154: ** Usage: sqlite3_column_blob STMT column
4155: */
4156: static int test_column_blob(
4157: void * clientData,
4158: Tcl_Interp *interp,
4159: int objc,
4160: Tcl_Obj *CONST objv[]
4161: ){
4162: sqlite3_stmt *pStmt;
4163: int col;
4164:
4165: int len;
4166: const void *pBlob;
4167:
4168: if( objc!=3 ){
4169: Tcl_AppendResult(interp, "wrong # args: should be \"",
4170: Tcl_GetString(objv[0]), " STMT column", 0);
4171: return TCL_ERROR;
4172: }
4173:
4174: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4175: if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4176:
4177: len = sqlite3_column_bytes(pStmt, col);
4178: pBlob = sqlite3_column_blob(pStmt, col);
4179: Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
4180: return TCL_OK;
4181: }
4182:
4183: /*
4184: ** Usage: sqlite3_column_double STMT column
4185: **
4186: ** Return the data in column 'column' of the current row cast as a double.
4187: */
4188: static int test_column_double(
4189: void * clientData,
4190: Tcl_Interp *interp,
4191: int objc,
4192: Tcl_Obj *CONST objv[]
4193: ){
4194: sqlite3_stmt *pStmt;
4195: int col;
4196: double rVal;
4197:
4198: if( objc!=3 ){
4199: Tcl_AppendResult(interp, "wrong # args: should be \"",
4200: Tcl_GetString(objv[0]), " STMT column", 0);
4201: return TCL_ERROR;
4202: }
4203:
4204: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4205: if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4206:
4207: rVal = sqlite3_column_double(pStmt, col);
4208: Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
4209: return TCL_OK;
4210: }
4211:
4212: /*
4213: ** Usage: sqlite3_data_count STMT
4214: **
4215: ** Return the number of columns returned by the sql statement STMT.
4216: */
4217: static int test_data_count(
4218: void * clientData,
4219: Tcl_Interp *interp,
4220: int objc,
4221: Tcl_Obj *CONST objv[]
4222: ){
4223: sqlite3_stmt *pStmt;
4224:
4225: if( objc!=2 ){
4226: Tcl_AppendResult(interp, "wrong # args: should be \"",
4227: Tcl_GetString(objv[0]), " STMT column", 0);
4228: return TCL_ERROR;
4229: }
4230:
4231: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4232:
4233: Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
4234: return TCL_OK;
4235: }
4236:
4237: /*
4238: ** Usage: sqlite3_column_text STMT column
4239: **
4240: ** Usage: sqlite3_column_decltype STMT column
4241: **
4242: ** Usage: sqlite3_column_name STMT column
4243: */
4244: static int test_stmt_utf8(
4245: void * clientData, /* Pointer to SQLite API function to be invoke */
4246: Tcl_Interp *interp,
4247: int objc,
4248: Tcl_Obj *CONST objv[]
4249: ){
4250: sqlite3_stmt *pStmt;
4251: int col;
4252: const char *(*xFunc)(sqlite3_stmt*, int);
4253: const char *zRet;
4254:
4255: xFunc = (const char *(*)(sqlite3_stmt*, int))clientData;
4256: if( objc!=3 ){
4257: Tcl_AppendResult(interp, "wrong # args: should be \"",
4258: Tcl_GetString(objv[0]), " STMT column", 0);
4259: return TCL_ERROR;
4260: }
4261:
4262: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4263: if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4264: zRet = xFunc(pStmt, col);
4265: if( zRet ){
4266: Tcl_SetResult(interp, (char *)zRet, 0);
4267: }
4268: return TCL_OK;
4269: }
4270:
4271: static int test_global_recover(
4272: void * clientData,
4273: Tcl_Interp *interp,
4274: int objc,
4275: Tcl_Obj *CONST objv[]
4276: ){
4277: #ifndef SQLITE_OMIT_DEPRECATED
4278: int rc;
4279: if( objc!=1 ){
4280: Tcl_WrongNumArgs(interp, 1, objv, "");
4281: return TCL_ERROR;
4282: }
4283: rc = sqlite3_global_recover();
4284: Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
4285: #endif
4286: return TCL_OK;
4287: }
4288:
4289: /*
4290: ** Usage: sqlite3_column_text STMT column
4291: **
4292: ** Usage: sqlite3_column_decltype STMT column
4293: **
4294: ** Usage: sqlite3_column_name STMT column
4295: */
4296: static int test_stmt_utf16(
4297: void * clientData, /* Pointer to SQLite API function to be invoked */
4298: Tcl_Interp *interp,
4299: int objc,
4300: Tcl_Obj *CONST objv[]
4301: ){
4302: #ifndef SQLITE_OMIT_UTF16
4303: sqlite3_stmt *pStmt;
4304: int col;
4305: Tcl_Obj *pRet;
4306: const void *zName16;
4307: const void *(*xFunc)(sqlite3_stmt*, int);
4308:
4309: xFunc = (const void *(*)(sqlite3_stmt*, int))clientData;
4310: if( objc!=3 ){
4311: Tcl_AppendResult(interp, "wrong # args: should be \"",
4312: Tcl_GetString(objv[0]), " STMT column", 0);
4313: return TCL_ERROR;
4314: }
4315:
4316: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4317: if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4318:
4319: zName16 = xFunc(pStmt, col);
4320: if( zName16 ){
4321: int n;
4322: const char *z = zName16;
4323: for(n=0; z[n] || z[n+1]; n+=2){}
4324: pRet = Tcl_NewByteArrayObj(zName16, n+2);
4325: Tcl_SetObjResult(interp, pRet);
4326: }
4327: #endif /* SQLITE_OMIT_UTF16 */
4328:
4329: return TCL_OK;
4330: }
4331:
4332: /*
4333: ** Usage: sqlite3_column_int STMT column
4334: **
4335: ** Usage: sqlite3_column_bytes STMT column
4336: **
4337: ** Usage: sqlite3_column_bytes16 STMT column
4338: **
4339: */
4340: static int test_stmt_int(
4341: void * clientData, /* Pointer to SQLite API function to be invoked */
4342: Tcl_Interp *interp,
4343: int objc,
4344: Tcl_Obj *CONST objv[]
4345: ){
4346: sqlite3_stmt *pStmt;
4347: int col;
4348: int (*xFunc)(sqlite3_stmt*, int);
4349:
4350: xFunc = (int (*)(sqlite3_stmt*, int))clientData;
4351: if( objc!=3 ){
4352: Tcl_AppendResult(interp, "wrong # args: should be \"",
4353: Tcl_GetString(objv[0]), " STMT column", 0);
4354: return TCL_ERROR;
4355: }
4356:
4357: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
4358: if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
4359:
4360: Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
4361: return TCL_OK;
4362: }
4363:
4364: /*
4365: ** Usage: sqlite_set_magic DB MAGIC-NUMBER
4366: **
4367: ** Set the db->magic value. This is used to test error recovery logic.
4368: */
4369: static int sqlite_set_magic(
4370: void * clientData,
4371: Tcl_Interp *interp,
4372: int argc,
4373: char **argv
4374: ){
4375: sqlite3 *db;
4376: if( argc!=3 ){
4377: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4378: " DB MAGIC", 0);
4379: return TCL_ERROR;
4380: }
4381: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4382: if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
4383: db->magic = SQLITE_MAGIC_OPEN;
4384: }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
4385: db->magic = SQLITE_MAGIC_CLOSED;
4386: }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
4387: db->magic = SQLITE_MAGIC_BUSY;
4388: }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
4389: db->magic = SQLITE_MAGIC_ERROR;
4390: }else if( Tcl_GetInt(interp, argv[2], (int*)&db->magic) ){
4391: return TCL_ERROR;
4392: }
4393: return TCL_OK;
4394: }
4395:
4396: /*
4397: ** Usage: sqlite3_interrupt DB
4398: **
4399: ** Trigger an interrupt on DB
4400: */
4401: static int test_interrupt(
4402: void * clientData,
4403: Tcl_Interp *interp,
4404: int argc,
4405: char **argv
4406: ){
4407: sqlite3 *db;
4408: if( argc!=2 ){
4409: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
4410: return TCL_ERROR;
4411: }
4412: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4413: sqlite3_interrupt(db);
4414: return TCL_OK;
4415: }
4416:
4417: static u8 *sqlite3_stack_baseline = 0;
4418:
4419: /*
4420: ** Fill the stack with a known bitpattern.
4421: */
4422: static void prepStack(void){
4423: int i;
4424: u32 bigBuf[65536];
4425: for(i=0; i<sizeof(bigBuf)/sizeof(bigBuf[0]); i++) bigBuf[i] = 0xdeadbeef;
4426: sqlite3_stack_baseline = (u8*)&bigBuf[65536];
4427: }
4428:
4429: /*
4430: ** Get the current stack depth. Used for debugging only.
4431: */
4432: u64 sqlite3StackDepth(void){
4433: u8 x;
4434: return (u64)(sqlite3_stack_baseline - &x);
4435: }
4436:
4437: /*
4438: ** Usage: sqlite3_stack_used DB SQL
4439: **
4440: ** Try to measure the amount of stack space used by a call to sqlite3_exec
4441: */
4442: static int test_stack_used(
4443: void * clientData,
4444: Tcl_Interp *interp,
4445: int argc,
4446: char **argv
4447: ){
4448: sqlite3 *db;
4449: int i;
4450: if( argc!=3 ){
4451: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4452: " DB SQL", 0);
4453: return TCL_ERROR;
4454: }
4455: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4456: prepStack();
4457: (void)sqlite3_exec(db, argv[2], 0, 0, 0);
4458: for(i=65535; i>=0 && ((u32*)sqlite3_stack_baseline)[-i]==0xdeadbeef; i--){}
4459: Tcl_SetObjResult(interp, Tcl_NewIntObj(i*4));
4460: return TCL_OK;
4461: }
4462:
4463: /*
4464: ** Usage: sqlite_delete_function DB function-name
4465: **
4466: ** Delete the user function 'function-name' from database handle DB. It
4467: ** is assumed that the user function was created as UTF8, any number of
4468: ** arguments (the way the TCL interface does it).
4469: */
4470: static int delete_function(
4471: void * clientData,
4472: Tcl_Interp *interp,
4473: int argc,
4474: char **argv
4475: ){
4476: int rc;
4477: sqlite3 *db;
4478: if( argc!=3 ){
4479: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4480: " DB function-name", 0);
4481: return TCL_ERROR;
4482: }
4483: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4484: rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
4485: Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
4486: return TCL_OK;
4487: }
4488:
4489: /*
4490: ** Usage: sqlite_delete_collation DB collation-name
4491: **
4492: ** Delete the collation sequence 'collation-name' from database handle
4493: ** DB. It is assumed that the collation sequence was created as UTF8 (the
4494: ** way the TCL interface does it).
4495: */
4496: static int delete_collation(
4497: void * clientData,
4498: Tcl_Interp *interp,
4499: int argc,
4500: char **argv
4501: ){
4502: int rc;
4503: sqlite3 *db;
4504: if( argc!=3 ){
4505: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4506: " DB function-name", 0);
4507: return TCL_ERROR;
4508: }
4509: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4510: rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
4511: Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
4512: return TCL_OK;
4513: }
4514:
4515: /*
4516: ** Usage: sqlite3_get_autocommit DB
4517: **
4518: ** Return true if the database DB is currently in auto-commit mode.
4519: ** Return false if not.
4520: */
4521: static int get_autocommit(
4522: void * clientData,
4523: Tcl_Interp *interp,
4524: int argc,
4525: char **argv
4526: ){
4527: char zBuf[30];
4528: sqlite3 *db;
4529: if( argc!=2 ){
4530: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4531: " DB", 0);
4532: return TCL_ERROR;
4533: }
4534: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4535: sprintf(zBuf, "%d", sqlite3_get_autocommit(db));
4536: Tcl_AppendResult(interp, zBuf, 0);
4537: return TCL_OK;
4538: }
4539:
4540: /*
4541: ** Usage: sqlite3_busy_timeout DB MS
4542: **
4543: ** Set the busy timeout. This is more easily done using the timeout
4544: ** method of the TCL interface. But we need a way to test the case
4545: ** where it returns SQLITE_MISUSE.
4546: */
4547: static int test_busy_timeout(
4548: void * clientData,
4549: Tcl_Interp *interp,
4550: int argc,
4551: char **argv
4552: ){
4553: int rc, ms;
4554: sqlite3 *db;
4555: if( argc!=3 ){
4556: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4557: " DB", 0);
4558: return TCL_ERROR;
4559: }
4560: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
4561: if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR;
4562: rc = sqlite3_busy_timeout(db, ms);
4563: Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
4564: return TCL_OK;
4565: }
4566:
4567: /*
4568: ** Usage: tcl_variable_type VARIABLENAME
4569: **
4570: ** Return the name of the internal representation for the
4571: ** value of the given variable.
4572: */
4573: static int tcl_variable_type(
4574: void * clientData,
4575: Tcl_Interp *interp,
4576: int objc,
4577: Tcl_Obj *CONST objv[]
4578: ){
4579: Tcl_Obj *pVar;
4580: if( objc!=2 ){
4581: Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
4582: return TCL_ERROR;
4583: }
4584: pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
4585: if( pVar==0 ) return TCL_ERROR;
4586: if( pVar->typePtr ){
4587: Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
4588: }
4589: return TCL_OK;
4590: }
4591:
4592: /*
4593: ** Usage: sqlite3_release_memory ?N?
4594: **
4595: ** Attempt to release memory currently held but not actually required.
4596: ** The integer N is the number of bytes we are trying to release. The
4597: ** return value is the amount of memory actually released.
4598: */
4599: static int test_release_memory(
4600: void * clientData,
4601: Tcl_Interp *interp,
4602: int objc,
4603: Tcl_Obj *CONST objv[]
4604: ){
4605: #if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
4606: int N;
4607: int amt;
4608: if( objc!=1 && objc!=2 ){
4609: Tcl_WrongNumArgs(interp, 1, objv, "?N?");
4610: return TCL_ERROR;
4611: }
4612: if( objc==2 ){
4613: if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
4614: }else{
4615: N = -1;
4616: }
4617: amt = sqlite3_release_memory(N);
4618: Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
4619: #endif
4620: return TCL_OK;
4621: }
4622:
4623:
4624: /*
4625: ** Usage: sqlite3_db_release_memory DB
4626: **
4627: ** Attempt to release memory currently held by database DB. Return the
4628: ** result code (which in the current implementation is always zero).
4629: */
4630: static int test_db_release_memory(
4631: void * clientData,
4632: Tcl_Interp *interp,
4633: int objc,
4634: Tcl_Obj *CONST objv[]
4635: ){
4636: sqlite3 *db;
4637: int rc;
4638: if( objc!=2 ){
4639: Tcl_WrongNumArgs(interp, 1, objv, "DB");
4640: return TCL_ERROR;
4641: }
4642: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4643: rc = sqlite3_db_release_memory(db);
4644: Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
4645: return TCL_OK;
4646: }
4647:
4648: /*
4649: ** Usage: sqlite3_db_filename DB DBNAME
4650: **
4651: ** Return the name of a file associated with a database.
4652: */
4653: static int test_db_filename(
4654: void * clientData,
4655: Tcl_Interp *interp,
4656: int objc,
4657: Tcl_Obj *CONST objv[]
4658: ){
4659: sqlite3 *db;
4660: const char *zDbName;
4661: if( objc!=3 ){
4662: Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
4663: return TCL_ERROR;
4664: }
4665: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4666: zDbName = Tcl_GetString(objv[2]);
4667: Tcl_AppendResult(interp, sqlite3_db_filename(db, zDbName), (void*)0);
4668: return TCL_OK;
4669: }
4670:
4671: /*
4672: ** Usage: sqlite3_soft_heap_limit ?N?
4673: **
4674: ** Query or set the soft heap limit for the current thread. The
4675: ** limit is only changed if the N is present. The previous limit
4676: ** is returned.
4677: */
4678: static int test_soft_heap_limit(
4679: void * clientData,
4680: Tcl_Interp *interp,
4681: int objc,
4682: Tcl_Obj *CONST objv[]
4683: ){
4684: sqlite3_int64 amt;
4685: sqlite3_int64 N = -1;
4686: if( objc!=1 && objc!=2 ){
4687: Tcl_WrongNumArgs(interp, 1, objv, "?N?");
4688: return TCL_ERROR;
4689: }
4690: if( objc==2 ){
4691: if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
4692: }
4693: amt = sqlite3_soft_heap_limit64(N);
4694: Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt));
4695: return TCL_OK;
4696: }
4697:
4698: /*
4699: ** Usage: sqlite3_thread_cleanup
4700: **
4701: ** Call the sqlite3_thread_cleanup API.
4702: */
4703: static int test_thread_cleanup(
4704: void * clientData,
4705: Tcl_Interp *interp,
4706: int objc,
4707: Tcl_Obj *CONST objv[]
4708: ){
4709: #ifndef SQLITE_OMIT_DEPRECATED
4710: sqlite3_thread_cleanup();
4711: #endif
4712: return TCL_OK;
4713: }
4714:
4715: /*
4716: ** Usage: sqlite3_pager_refcounts DB
4717: **
4718: ** Return a list of numbers which are the PagerRefcount for all
4719: ** pagers on each database connection.
4720: */
4721: static int test_pager_refcounts(
4722: void * clientData,
4723: Tcl_Interp *interp,
4724: int objc,
4725: Tcl_Obj *CONST objv[]
4726: ){
4727: sqlite3 *db;
4728: int i;
4729: int v, *a;
4730: Tcl_Obj *pResult;
4731:
4732: if( objc!=2 ){
4733: Tcl_AppendResult(interp, "wrong # args: should be \"",
4734: Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
4735: return TCL_ERROR;
4736: }
4737: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4738: pResult = Tcl_NewObj();
4739: for(i=0; i<db->nDb; i++){
4740: if( db->aDb[i].pBt==0 ){
4741: v = -1;
4742: }else{
4743: sqlite3_mutex_enter(db->mutex);
4744: a = sqlite3PagerStats(sqlite3BtreePager(db->aDb[i].pBt));
4745: v = a[0];
4746: sqlite3_mutex_leave(db->mutex);
4747: }
4748: Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(v));
4749: }
4750: Tcl_SetObjResult(interp, pResult);
4751: return TCL_OK;
4752: }
4753:
4754:
4755: /*
4756: ** tclcmd: working_64bit_int
4757: **
4758: ** Some TCL builds (ex: cygwin) do not support 64-bit integers. This
4759: ** leads to a number of test failures. The present command checks the
4760: ** TCL build to see whether or not it supports 64-bit integers. It
4761: ** returns TRUE if it does and FALSE if not.
4762: **
4763: ** This command is used to warn users that their TCL build is defective
4764: ** and that the errors they are seeing in the test scripts might be
4765: ** a result of their defective TCL rather than problems in SQLite.
4766: */
4767: static int working_64bit_int(
4768: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4769: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4770: int objc, /* Number of arguments */
4771: Tcl_Obj *CONST objv[] /* Command arguments */
4772: ){
4773: Tcl_Obj *pTestObj;
4774: int working = 0;
4775:
4776: pTestObj = Tcl_NewWideIntObj(1000000*(i64)1234567890);
4777: working = strcmp(Tcl_GetString(pTestObj), "1234567890000000")==0;
4778: Tcl_DecrRefCount(pTestObj);
4779: Tcl_SetObjResult(interp, Tcl_NewBooleanObj(working));
4780: return TCL_OK;
4781: }
4782:
4783:
4784: /*
4785: ** tclcmd: vfs_unlink_test
4786: **
4787: ** This TCL command unregisters the primary VFS and then registers
4788: ** it back again. This is used to test the ability to register a
4789: ** VFS when none are previously registered, and the ability to
4790: ** unregister the only available VFS. Ticket #2738
4791: */
4792: static int vfs_unlink_test(
4793: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4794: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4795: int objc, /* Number of arguments */
4796: Tcl_Obj *CONST objv[] /* Command arguments */
4797: ){
4798: int i;
4799: sqlite3_vfs *pMain;
4800: sqlite3_vfs *apVfs[20];
4801: sqlite3_vfs one, two;
4802:
4803: sqlite3_vfs_unregister(0); /* Unregister of NULL is harmless */
4804: one.zName = "__one";
4805: two.zName = "__two";
4806:
4807: /* Calling sqlite3_vfs_register with 2nd argument of 0 does not
4808: ** change the default VFS
4809: */
4810: pMain = sqlite3_vfs_find(0);
4811: sqlite3_vfs_register(&one, 0);
4812: assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
4813: sqlite3_vfs_register(&two, 0);
4814: assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
4815:
4816: /* We can find a VFS by its name */
4817: assert( sqlite3_vfs_find("__one")==&one );
4818: assert( sqlite3_vfs_find("__two")==&two );
4819:
4820: /* Calling sqlite_vfs_register with non-zero second parameter changes the
4821: ** default VFS, even if the 1st parameter is an existig VFS that is
4822: ** previously registered as the non-default.
4823: */
4824: sqlite3_vfs_register(&one, 1);
4825: assert( sqlite3_vfs_find("__one")==&one );
4826: assert( sqlite3_vfs_find("__two")==&two );
4827: assert( sqlite3_vfs_find(0)==&one );
4828: sqlite3_vfs_register(&two, 1);
4829: assert( sqlite3_vfs_find("__one")==&one );
4830: assert( sqlite3_vfs_find("__two")==&two );
4831: assert( sqlite3_vfs_find(0)==&two );
4832: if( pMain ){
4833: sqlite3_vfs_register(pMain, 1);
4834: assert( sqlite3_vfs_find("__one")==&one );
4835: assert( sqlite3_vfs_find("__two")==&two );
4836: assert( sqlite3_vfs_find(0)==pMain );
4837: }
4838:
4839: /* Unlink the default VFS. Repeat until there are no more VFSes
4840: ** registered.
4841: */
4842: for(i=0; i<sizeof(apVfs)/sizeof(apVfs[0]); i++){
4843: apVfs[i] = sqlite3_vfs_find(0);
4844: if( apVfs[i] ){
4845: assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
4846: sqlite3_vfs_unregister(apVfs[i]);
4847: assert( 0==sqlite3_vfs_find(apVfs[i]->zName) );
4848: }
4849: }
4850: assert( 0==sqlite3_vfs_find(0) );
4851:
4852: /* Register the main VFS as non-default (will be made default, since
4853: ** it'll be the only one in existence).
4854: */
4855: sqlite3_vfs_register(pMain, 0);
4856: assert( sqlite3_vfs_find(0)==pMain );
4857:
4858: /* Un-register the main VFS again to restore an empty VFS list */
4859: sqlite3_vfs_unregister(pMain);
4860: assert( 0==sqlite3_vfs_find(0) );
4861:
4862: /* Relink all VFSes in reverse order. */
4863: for(i=sizeof(apVfs)/sizeof(apVfs[0])-1; i>=0; i--){
4864: if( apVfs[i] ){
4865: sqlite3_vfs_register(apVfs[i], 1);
4866: assert( apVfs[i]==sqlite3_vfs_find(0) );
4867: assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
4868: }
4869: }
4870:
4871: /* Unregister out sample VFSes. */
4872: sqlite3_vfs_unregister(&one);
4873: sqlite3_vfs_unregister(&two);
4874:
4875: /* Unregistering a VFS that is not currently registered is harmless */
4876: sqlite3_vfs_unregister(&one);
4877: sqlite3_vfs_unregister(&two);
4878: assert( sqlite3_vfs_find("__one")==0 );
4879: assert( sqlite3_vfs_find("__two")==0 );
4880:
4881: /* We should be left with the original default VFS back as the
4882: ** original */
4883: assert( sqlite3_vfs_find(0)==pMain );
4884:
4885: return TCL_OK;
4886: }
4887:
4888: /*
4889: ** tclcmd: vfs_initfail_test
4890: **
4891: ** This TCL command attempts to vfs_find and vfs_register when the
4892: ** sqlite3_initialize() interface is failing. All calls should fail.
4893: */
4894: static int vfs_initfail_test(
4895: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4896: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4897: int objc, /* Number of arguments */
4898: Tcl_Obj *CONST objv[] /* Command arguments */
4899: ){
4900: sqlite3_vfs one;
4901: one.zName = "__one";
4902:
4903: if( sqlite3_vfs_find(0) ) return TCL_ERROR;
4904: sqlite3_vfs_register(&one, 0);
4905: if( sqlite3_vfs_find(0) ) return TCL_ERROR;
4906: sqlite3_vfs_register(&one, 1);
4907: if( sqlite3_vfs_find(0) ) return TCL_ERROR;
4908: return TCL_OK;
4909: }
4910:
4911: /*
4912: ** Saved VFSes
4913: */
4914: static sqlite3_vfs *apVfs[20];
4915: static int nVfs = 0;
4916:
4917: /*
4918: ** tclcmd: vfs_unregister_all
4919: **
4920: ** Unregister all VFSes.
4921: */
4922: static int vfs_unregister_all(
4923: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4924: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4925: int objc, /* Number of arguments */
4926: Tcl_Obj *CONST objv[] /* Command arguments */
4927: ){
4928: int i;
4929: for(i=0; i<ArraySize(apVfs); i++){
4930: apVfs[i] = sqlite3_vfs_find(0);
4931: if( apVfs[i]==0 ) break;
4932: sqlite3_vfs_unregister(apVfs[i]);
4933: }
4934: nVfs = i;
4935: return TCL_OK;
4936: }
4937: /*
4938: ** tclcmd: vfs_reregister_all
4939: **
4940: ** Restore all VFSes that were removed using vfs_unregister_all
4941: */
4942: static int vfs_reregister_all(
4943: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4944: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4945: int objc, /* Number of arguments */
4946: Tcl_Obj *CONST objv[] /* Command arguments */
4947: ){
4948: int i;
4949: for(i=0; i<nVfs; i++){
4950: sqlite3_vfs_register(apVfs[i], i==0);
4951: }
4952: return TCL_OK;
4953: }
4954:
4955:
4956: /*
4957: ** tclcmd: file_control_test DB
4958: **
4959: ** This TCL command runs the sqlite3_file_control interface and
4960: ** verifies correct operation of the same.
4961: */
4962: static int file_control_test(
4963: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4964: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4965: int objc, /* Number of arguments */
4966: Tcl_Obj *CONST objv[] /* Command arguments */
4967: ){
4968: int iArg = 0;
4969: sqlite3 *db;
4970: int rc;
4971:
4972: if( objc!=2 ){
4973: Tcl_AppendResult(interp, "wrong # args: should be \"",
4974: Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
4975: return TCL_ERROR;
4976: }
4977: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
4978: rc = sqlite3_file_control(db, 0, 0, &iArg);
4979: assert( rc==SQLITE_NOTFOUND );
4980: rc = sqlite3_file_control(db, "notadatabase", SQLITE_FCNTL_LOCKSTATE, &iArg);
4981: assert( rc==SQLITE_ERROR );
4982: rc = sqlite3_file_control(db, "main", -1, &iArg);
4983: assert( rc==SQLITE_NOTFOUND );
4984: rc = sqlite3_file_control(db, "temp", -1, &iArg);
4985: assert( rc==SQLITE_NOTFOUND || rc==SQLITE_ERROR );
4986:
4987: return TCL_OK;
4988: }
4989:
4990:
4991: /*
4992: ** tclcmd: file_control_lasterrno_test DB
4993: **
4994: ** This TCL command runs the sqlite3_file_control interface and
4995: ** verifies correct operation of the SQLITE_LAST_ERRNO verb.
4996: */
4997: static int file_control_lasterrno_test(
4998: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4999: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5000: int objc, /* Number of arguments */
5001: Tcl_Obj *CONST objv[] /* Command arguments */
5002: ){
5003: int iArg = 0;
5004: sqlite3 *db;
5005: int rc;
5006:
5007: if( objc!=2 ){
5008: Tcl_AppendResult(interp, "wrong # args: should be \"",
5009: Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
5010: return TCL_ERROR;
5011: }
5012: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5013: return TCL_ERROR;
5014: }
5015: rc = sqlite3_file_control(db, NULL, SQLITE_LAST_ERRNO, &iArg);
5016: if( rc ){
5017: Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5018: return TCL_ERROR;
5019: }
5020: if( iArg!=0 ) {
5021: Tcl_AppendResult(interp, "Unexpected non-zero errno: ",
5022: Tcl_GetStringFromObj(Tcl_NewIntObj(iArg), 0), " ", 0);
5023: return TCL_ERROR;
5024: }
5025: return TCL_OK;
5026: }
5027:
5028: /*
5029: ** tclcmd: file_control_chunksize_test DB DBNAME SIZE
5030: **
5031: ** This TCL command runs the sqlite3_file_control interface and
5032: ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
5033: ** SQLITE_SET_LOCKPROXYFILE verbs.
5034: */
5035: static int file_control_chunksize_test(
5036: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5037: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5038: int objc, /* Number of arguments */
5039: Tcl_Obj *CONST objv[] /* Command arguments */
5040: ){
5041: int nSize; /* New chunk size */
5042: char *zDb; /* Db name ("main", "temp" etc.) */
5043: sqlite3 *db; /* Database handle */
5044: int rc; /* file_control() return code */
5045:
5046: if( objc!=4 ){
5047: Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
5048: return TCL_ERROR;
5049: }
5050: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
5051: || Tcl_GetIntFromObj(interp, objv[3], &nSize)
5052: ){
5053: return TCL_ERROR;
5054: }
5055: zDb = Tcl_GetString(objv[2]);
5056: if( zDb[0]=='\0' ) zDb = NULL;
5057:
5058: rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_CHUNK_SIZE, (void *)&nSize);
5059: if( rc ){
5060: Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC);
5061: return TCL_ERROR;
5062: }
5063: return TCL_OK;
5064: }
5065:
5066: /*
5067: ** tclcmd: file_control_sizehint_test DB DBNAME SIZE
5068: **
5069: ** This TCL command runs the sqlite3_file_control interface
5070: ** with SQLITE_FCNTL_SIZE_HINT
5071: */
5072: static int file_control_sizehint_test(
5073: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5074: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5075: int objc, /* Number of arguments */
5076: Tcl_Obj *CONST objv[] /* Command arguments */
5077: ){
5078: sqlite3_int64 nSize; /* Hinted size */
5079: char *zDb; /* Db name ("main", "temp" etc.) */
5080: sqlite3 *db; /* Database handle */
5081: int rc; /* file_control() return code */
5082:
5083: if( objc!=4 ){
5084: Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
5085: return TCL_ERROR;
5086: }
5087: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
5088: || Tcl_GetWideIntFromObj(interp, objv[3], &nSize)
5089: ){
5090: return TCL_ERROR;
5091: }
5092: zDb = Tcl_GetString(objv[2]);
5093: if( zDb[0]=='\0' ) zDb = NULL;
5094:
5095: rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_SIZE_HINT, (void *)&nSize);
5096: if( rc ){
5097: Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC);
5098: return TCL_ERROR;
5099: }
5100: return TCL_OK;
5101: }
5102:
5103: /*
5104: ** tclcmd: file_control_lockproxy_test DB PWD
5105: **
5106: ** This TCL command runs the sqlite3_file_control interface and
5107: ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
5108: ** SQLITE_SET_LOCKPROXYFILE verbs.
5109: */
5110: static int file_control_lockproxy_test(
5111: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5112: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5113: int objc, /* Number of arguments */
5114: Tcl_Obj *CONST objv[] /* Command arguments */
5115: ){
5116: sqlite3 *db;
5117: const char *zPwd;
5118: int nPwd;
5119:
5120: if( objc!=3 ){
5121: Tcl_AppendResult(interp, "wrong # args: should be \"",
5122: Tcl_GetStringFromObj(objv[0], 0), " DB PWD", 0);
5123: return TCL_ERROR;
5124: }
5125: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5126: return TCL_ERROR;
5127: }
5128: zPwd = Tcl_GetStringFromObj(objv[2], &nPwd);
5129:
5130: #if !defined(SQLITE_ENABLE_LOCKING_STYLE)
5131: # if defined(__APPLE__)
5132: # define SQLITE_ENABLE_LOCKING_STYLE 1
5133: # else
5134: # define SQLITE_ENABLE_LOCKING_STYLE 0
5135: # endif
5136: #endif
5137: #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
5138: {
5139: char *testPath;
5140: int rc;
5141: char proxyPath[400];
5142:
5143: if( sizeof(proxyPath)<nPwd+20 ){
5144: Tcl_AppendResult(interp, "PWD too big", (void*)0);
5145: return TCL_ERROR;
5146: }
5147: sprintf(proxyPath, "%s/test.proxy", zPwd);
5148: rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
5149: if( rc ){
5150: Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5151: return TCL_ERROR;
5152: }
5153: rc = sqlite3_file_control(db, NULL, SQLITE_GET_LOCKPROXYFILE, &testPath);
5154: if( strncmp(proxyPath,testPath,11) ){
5155: Tcl_AppendResult(interp, "Lock proxy file did not match the "
5156: "previously assigned value", 0);
5157: return TCL_ERROR;
5158: }
5159: if( rc ){
5160: Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5161: return TCL_ERROR;
5162: }
5163: rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
5164: if( rc ){
5165: Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5166: return TCL_ERROR;
5167: }
5168: }
5169: #endif
5170: return TCL_OK;
5171: }
5172:
5173: /*
5174: ** tclcmd: file_control_win32_av_retry DB NRETRY DELAY
5175: **
5176: ** This TCL command runs the sqlite3_file_control interface with
5177: ** the SQLITE_FCNTL_WIN32_AV_RETRY opcode.
5178: */
5179: static int file_control_win32_av_retry(
5180: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5181: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5182: int objc, /* Number of arguments */
5183: Tcl_Obj *CONST objv[] /* Command arguments */
5184: ){
5185: sqlite3 *db;
5186: int rc;
5187: int a[2];
5188: char z[100];
5189:
5190: if( objc!=4 ){
5191: Tcl_AppendResult(interp, "wrong # args: should be \"",
5192: Tcl_GetStringFromObj(objv[0], 0), " DB NRETRY DELAY", 0);
5193: return TCL_ERROR;
5194: }
5195: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5196: return TCL_ERROR;
5197: }
5198: if( Tcl_GetIntFromObj(interp, objv[2], &a[0]) ) return TCL_ERROR;
5199: if( Tcl_GetIntFromObj(interp, objv[3], &a[1]) ) return TCL_ERROR;
5200: rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a);
5201: sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]);
5202: Tcl_AppendResult(interp, z, (char*)0);
5203: return TCL_OK;
5204: }
5205:
5206: /*
5207: ** tclcmd: file_control_persist_wal DB PERSIST-FLAG
5208: **
5209: ** This TCL command runs the sqlite3_file_control interface with
5210: ** the SQLITE_FCNTL_PERSIST_WAL opcode.
5211: */
5212: static int file_control_persist_wal(
5213: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5214: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5215: int objc, /* Number of arguments */
5216: Tcl_Obj *CONST objv[] /* Command arguments */
5217: ){
5218: sqlite3 *db;
5219: int rc;
5220: int bPersist;
5221: char z[100];
5222:
5223: if( objc!=3 ){
5224: Tcl_AppendResult(interp, "wrong # args: should be \"",
5225: Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
5226: return TCL_ERROR;
5227: }
5228: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5229: return TCL_ERROR;
5230: }
5231: if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR;
5232: rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist);
5233: sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist);
5234: Tcl_AppendResult(interp, z, (char*)0);
5235: return TCL_OK;
5236: }
5237:
5238: /*
5239: ** tclcmd: file_control_powersafe_overwrite DB PSOW-FLAG
5240: **
5241: ** This TCL command runs the sqlite3_file_control interface with
5242: ** the SQLITE_FCNTL_POWERSAFE_OVERWRITE opcode.
5243: */
5244: static int file_control_powersafe_overwrite(
5245: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5246: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5247: int objc, /* Number of arguments */
5248: Tcl_Obj *CONST objv[] /* Command arguments */
5249: ){
5250: sqlite3 *db;
5251: int rc;
5252: int b;
5253: char z[100];
5254:
5255: if( objc!=3 ){
5256: Tcl_AppendResult(interp, "wrong # args: should be \"",
5257: Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
5258: return TCL_ERROR;
5259: }
5260: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5261: return TCL_ERROR;
5262: }
5263: if( Tcl_GetIntFromObj(interp, objv[2], &b) ) return TCL_ERROR;
5264: rc = sqlite3_file_control(db,NULL,SQLITE_FCNTL_POWERSAFE_OVERWRITE,(void*)&b);
5265: sqlite3_snprintf(sizeof(z), z, "%d %d", rc, b);
5266: Tcl_AppendResult(interp, z, (char*)0);
5267: return TCL_OK;
5268: }
5269:
5270:
5271: /*
5272: ** tclcmd: file_control_vfsname DB ?AUXDB?
5273: **
5274: ** Return a string that describes the stack of VFSes.
5275: */
5276: static int file_control_vfsname(
5277: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5278: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5279: int objc, /* Number of arguments */
5280: Tcl_Obj *CONST objv[] /* Command arguments */
5281: ){
5282: sqlite3 *db;
5283: const char *zDbName = "main";
5284: char *zVfsName = 0;
5285:
5286: if( objc!=2 && objc!=3 ){
5287: Tcl_AppendResult(interp, "wrong # args: should be \"",
5288: Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
5289: return TCL_ERROR;
5290: }
5291: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5292: return TCL_ERROR;
5293: }
5294: if( objc==3 ){
5295: zDbName = Tcl_GetString(objv[2]);
5296: }
5297: sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName);
5298: Tcl_AppendResult(interp, zVfsName, (char*)0);
5299: sqlite3_free(zVfsName);
5300: return TCL_OK;
5301: }
5302:
5303:
5304: /*
5305: ** tclcmd: sqlite3_vfs_list
5306: **
5307: ** Return a tcl list containing the names of all registered vfs's.
5308: */
5309: static int vfs_list(
5310: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5311: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5312: int objc, /* Number of arguments */
5313: Tcl_Obj *CONST objv[] /* Command arguments */
5314: ){
5315: sqlite3_vfs *pVfs;
5316: Tcl_Obj *pRet = Tcl_NewObj();
5317: if( objc!=1 ){
5318: Tcl_WrongNumArgs(interp, 1, objv, "");
5319: return TCL_ERROR;
5320: }
5321: for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
5322: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(pVfs->zName, -1));
5323: }
5324: Tcl_SetObjResult(interp, pRet);
5325: return TCL_OK;
5326: }
5327:
5328: /*
5329: ** tclcmd: sqlite3_limit DB ID VALUE
5330: **
5331: ** This TCL command runs the sqlite3_limit interface and
5332: ** verifies correct operation of the same.
5333: */
5334: static int test_limit(
5335: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5336: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5337: int objc, /* Number of arguments */
5338: Tcl_Obj *CONST objv[] /* Command arguments */
5339: ){
5340: sqlite3 *db;
5341: int rc;
5342: static const struct {
5343: char *zName;
5344: int id;
5345: } aId[] = {
5346: { "SQLITE_LIMIT_LENGTH", SQLITE_LIMIT_LENGTH },
5347: { "SQLITE_LIMIT_SQL_LENGTH", SQLITE_LIMIT_SQL_LENGTH },
5348: { "SQLITE_LIMIT_COLUMN", SQLITE_LIMIT_COLUMN },
5349: { "SQLITE_LIMIT_EXPR_DEPTH", SQLITE_LIMIT_EXPR_DEPTH },
5350: { "SQLITE_LIMIT_COMPOUND_SELECT", SQLITE_LIMIT_COMPOUND_SELECT },
5351: { "SQLITE_LIMIT_VDBE_OP", SQLITE_LIMIT_VDBE_OP },
5352: { "SQLITE_LIMIT_FUNCTION_ARG", SQLITE_LIMIT_FUNCTION_ARG },
5353: { "SQLITE_LIMIT_ATTACHED", SQLITE_LIMIT_ATTACHED },
5354: { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
5355: { "SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER },
5356: { "SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH },
5357:
5358: /* Out of range test cases */
5359: { "SQLITE_LIMIT_TOOSMALL", -1, },
5360: { "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_TRIGGER_DEPTH+1 },
5361: };
5362: int i, id;
5363: int val;
5364: const char *zId;
5365:
5366: if( objc!=4 ){
5367: Tcl_AppendResult(interp, "wrong # args: should be \"",
5368: Tcl_GetStringFromObj(objv[0], 0), " DB ID VALUE", 0);
5369: return TCL_ERROR;
5370: }
5371: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
5372: zId = Tcl_GetString(objv[2]);
5373: for(i=0; i<sizeof(aId)/sizeof(aId[0]); i++){
5374: if( strcmp(zId, aId[i].zName)==0 ){
5375: id = aId[i].id;
5376: break;
5377: }
5378: }
5379: if( i>=sizeof(aId)/sizeof(aId[0]) ){
5380: Tcl_AppendResult(interp, "unknown limit type: ", zId, (char*)0);
5381: return TCL_ERROR;
5382: }
5383: if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
5384: rc = sqlite3_limit(db, id, val);
5385: Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
5386: return TCL_OK;
5387: }
5388:
5389: /*
5390: ** tclcmd: save_prng_state
5391: **
5392: ** Save the state of the pseudo-random number generator.
5393: ** At the same time, verify that sqlite3_test_control works even when
5394: ** called with an out-of-range opcode.
5395: */
5396: static int save_prng_state(
5397: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5398: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5399: int objc, /* Number of arguments */
5400: Tcl_Obj *CONST objv[] /* Command arguments */
5401: ){
5402: int rc = sqlite3_test_control(9999);
5403: assert( rc==0 );
5404: rc = sqlite3_test_control(-1);
5405: assert( rc==0 );
5406: sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SAVE);
5407: return TCL_OK;
5408: }
5409: /*
5410: ** tclcmd: restore_prng_state
5411: */
5412: static int restore_prng_state(
5413: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5414: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5415: int objc, /* Number of arguments */
5416: Tcl_Obj *CONST objv[] /* Command arguments */
5417: ){
5418: sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESTORE);
5419: return TCL_OK;
5420: }
5421: /*
5422: ** tclcmd: reset_prng_state
5423: */
5424: static int reset_prng_state(
5425: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5426: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5427: int objc, /* Number of arguments */
5428: Tcl_Obj *CONST objv[] /* Command arguments */
5429: ){
5430: sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESET);
5431: return TCL_OK;
5432: }
5433:
5434: /*
5435: ** tclcmd: pcache_stats
5436: */
5437: static int test_pcache_stats(
5438: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
5439: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5440: int objc, /* Number of arguments */
5441: Tcl_Obj *CONST objv[] /* Command arguments */
5442: ){
5443: int nMin;
5444: int nMax;
5445: int nCurrent;
5446: int nRecyclable;
5447: Tcl_Obj *pRet;
5448:
5449: sqlite3PcacheStats(&nCurrent, &nMax, &nMin, &nRecyclable);
5450:
5451: pRet = Tcl_NewObj();
5452: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("current", -1));
5453: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCurrent));
5454: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("max", -1));
5455: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMax));
5456: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("min", -1));
5457: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMin));
5458: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("recyclable", -1));
5459: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nRecyclable));
5460:
5461: Tcl_SetObjResult(interp, pRet);
5462:
5463: return TCL_OK;
5464: }
5465:
5466: #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
5467: static void test_unlock_notify_cb(void **aArg, int nArg){
5468: int ii;
5469: for(ii=0; ii<nArg; ii++){
5470: Tcl_EvalEx((Tcl_Interp *)aArg[ii], "unlock_notify", -1, TCL_EVAL_GLOBAL);
5471: }
5472: }
5473: #endif /* SQLITE_ENABLE_UNLOCK_NOTIFY */
5474:
5475: /*
5476: ** tclcmd: sqlite3_unlock_notify db
5477: */
5478: #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
5479: static int test_unlock_notify(
5480: ClientData clientData, /* Unused */
5481: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5482: int objc, /* Number of arguments */
5483: Tcl_Obj *CONST objv[] /* Command arguments */
5484: ){
5485: sqlite3 *db;
5486: int rc;
5487:
5488: if( objc!=2 ){
5489: Tcl_WrongNumArgs(interp, 1, objv, "DB");
5490: return TCL_ERROR;
5491: }
5492:
5493: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5494: return TCL_ERROR;
5495: }
5496: rc = sqlite3_unlock_notify(db, test_unlock_notify_cb, (void *)interp);
5497: Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
5498: return TCL_OK;
5499: }
5500: #endif
5501:
5502: /*
5503: ** tclcmd: sqlite3_wal_checkpoint db ?NAME?
5504: */
5505: static int test_wal_checkpoint(
5506: ClientData clientData, /* Unused */
5507: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5508: int objc, /* Number of arguments */
5509: Tcl_Obj *CONST objv[] /* Command arguments */
5510: ){
5511: char *zDb = 0;
5512: sqlite3 *db;
5513: int rc;
5514:
5515: if( objc!=3 && objc!=2 ){
5516: Tcl_WrongNumArgs(interp, 1, objv, "DB ?NAME?");
5517: return TCL_ERROR;
5518: }
5519:
5520: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
5521: return TCL_ERROR;
5522: }
5523: if( objc==3 ){
5524: zDb = Tcl_GetString(objv[2]);
5525: }
5526: rc = sqlite3_wal_checkpoint(db, zDb);
5527: Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
5528: return TCL_OK;
5529: }
5530:
5531: /*
5532: ** tclcmd: sqlite3_wal_checkpoint_v2 db MODE ?NAME?
5533: **
5534: ** This command calls the wal_checkpoint_v2() function with the specified
5535: ** mode argument (passive, full or restart). If present, the database name
5536: ** NAME is passed as the second argument to wal_checkpoint_v2(). If it the
5537: ** NAME argument is not present, a NULL pointer is passed instead.
5538: **
5539: ** If wal_checkpoint_v2() returns any value other than SQLITE_BUSY or
5540: ** SQLITE_OK, then this command returns TCL_ERROR. The Tcl result is set
5541: ** to the error message obtained from sqlite3_errmsg().
5542: **
5543: ** Otherwise, this command returns a list of three integers. The first integer
5544: ** is 1 if SQLITE_BUSY was returned, or 0 otherwise. The following two integers
5545: ** are the values returned via the output paramaters by wal_checkpoint_v2() -
5546: ** the number of frames in the log and the number of frames in the log
5547: ** that have been checkpointed.
5548: */
5549: static int test_wal_checkpoint_v2(
5550: ClientData clientData, /* Unused */
5551: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5552: int objc, /* Number of arguments */
5553: Tcl_Obj *CONST objv[] /* Command arguments */
5554: ){
5555: char *zDb = 0;
5556: sqlite3 *db;
5557: int rc;
5558:
5559: int eMode;
5560: int nLog = -555;
5561: int nCkpt = -555;
5562: Tcl_Obj *pRet;
5563:
5564: const char * aMode[] = { "passive", "full", "restart", 0 };
5565: assert( SQLITE_CHECKPOINT_PASSIVE==0 );
5566: assert( SQLITE_CHECKPOINT_FULL==1 );
5567: assert( SQLITE_CHECKPOINT_RESTART==2 );
5568:
5569: if( objc!=3 && objc!=4 ){
5570: Tcl_WrongNumArgs(interp, 1, objv, "DB MODE ?NAME?");
5571: return TCL_ERROR;
5572: }
5573:
5574: if( objc==4 ){
5575: zDb = Tcl_GetString(objv[3]);
5576: }
5577: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
5578: || Tcl_GetIndexFromObj(interp, objv[2], aMode, "mode", 0, &eMode)
5579: ){
5580: return TCL_ERROR;
5581: }
5582:
5583: rc = sqlite3_wal_checkpoint_v2(db, zDb, eMode, &nLog, &nCkpt);
5584: if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
5585: Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE);
5586: return TCL_ERROR;
5587: }
5588:
5589: pRet = Tcl_NewObj();
5590: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(rc==SQLITE_BUSY?1:0));
5591: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nLog));
5592: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCkpt));
5593: Tcl_SetObjResult(interp, pRet);
5594:
5595: return TCL_OK;
5596: }
5597:
5598: /*
5599: ** tclcmd: test_sqlite3_log ?SCRIPT?
5600: */
5601: static struct LogCallback {
5602: Tcl_Interp *pInterp;
5603: Tcl_Obj *pObj;
5604: } logcallback = {0, 0};
5605: static void xLogcallback(void *unused, int err, char *zMsg){
5606: Tcl_Obj *pNew = Tcl_DuplicateObj(logcallback.pObj);
5607: Tcl_IncrRefCount(pNew);
5608: Tcl_ListObjAppendElement(
5609: 0, pNew, Tcl_NewStringObj(sqlite3TestErrorName(err), -1)
5610: );
5611: Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zMsg, -1));
5612: Tcl_EvalObjEx(logcallback.pInterp, pNew, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
5613: Tcl_DecrRefCount(pNew);
5614: }
5615: static int test_sqlite3_log(
5616: ClientData clientData,
5617: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
5618: int objc, /* Number of arguments */
5619: Tcl_Obj *CONST objv[] /* Command arguments */
5620: ){
5621: if( objc>2 ){
5622: Tcl_WrongNumArgs(interp, 1, objv, "SCRIPT");
5623: return TCL_ERROR;
5624: }
5625: if( logcallback.pObj ){
5626: Tcl_DecrRefCount(logcallback.pObj);
5627: logcallback.pObj = 0;
5628: logcallback.pInterp = 0;
5629: sqlite3_config(SQLITE_CONFIG_LOG, 0, 0);
5630: }
5631: if( objc>1 ){
5632: logcallback.pObj = objv[1];
5633: Tcl_IncrRefCount(logcallback.pObj);
5634: logcallback.pInterp = interp;
5635: sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, 0);
5636: }
5637: return TCL_OK;
5638: }
5639:
5640: /*
5641: ** tcl_objproc COMMANDNAME ARGS...
5642: **
5643: ** Run a TCL command using its objProc interface. Throw an error if
5644: ** the command has no objProc interface.
5645: */
5646: static int runAsObjProc(
5647: void * clientData,
5648: Tcl_Interp *interp,
5649: int objc,
5650: Tcl_Obj *CONST objv[]
5651: ){
5652: Tcl_CmdInfo cmdInfo;
5653: if( objc<2 ){
5654: Tcl_WrongNumArgs(interp, 1, objv, "COMMAND ...");
5655: return TCL_ERROR;
5656: }
5657: if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
5658: Tcl_AppendResult(interp, "command not found: ",
5659: Tcl_GetString(objv[1]), (char*)0);
5660: return TCL_ERROR;
5661: }
5662: if( cmdInfo.objProc==0 ){
5663: Tcl_AppendResult(interp, "command has no objProc: ",
5664: Tcl_GetString(objv[1]), (char*)0);
5665: return TCL_ERROR;
5666: }
5667: return cmdInfo.objProc(cmdInfo.objClientData, interp, objc-1, objv+1);
5668: }
5669:
5670: #ifndef SQLITE_OMIT_EXPLAIN
5671: /*
5672: ** WARNING: The following function, printExplainQueryPlan() is an exact
5673: ** copy of example code from eqp.in (eqp.html). If this code is modified,
5674: ** then the documentation copy needs to be modified as well.
5675: */
5676: /*
5677: ** Argument pStmt is a prepared SQL statement. This function compiles
5678: ** an EXPLAIN QUERY PLAN command to report on the prepared statement,
5679: ** and prints the report to stdout using printf().
5680: */
5681: int printExplainQueryPlan(sqlite3_stmt *pStmt){
5682: const char *zSql; /* Input SQL */
5683: char *zExplain; /* SQL with EXPLAIN QUERY PLAN prepended */
5684: sqlite3_stmt *pExplain; /* Compiled EXPLAIN QUERY PLAN command */
5685: int rc; /* Return code from sqlite3_prepare_v2() */
5686:
5687: zSql = sqlite3_sql(pStmt);
5688: if( zSql==0 ) return SQLITE_ERROR;
5689:
5690: zExplain = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zSql);
5691: if( zExplain==0 ) return SQLITE_NOMEM;
5692:
5693: rc = sqlite3_prepare_v2(sqlite3_db_handle(pStmt), zExplain, -1, &pExplain, 0);
5694: sqlite3_free(zExplain);
5695: if( rc!=SQLITE_OK ) return rc;
5696:
5697: while( SQLITE_ROW==sqlite3_step(pExplain) ){
5698: int iSelectid = sqlite3_column_int(pExplain, 0);
5699: int iOrder = sqlite3_column_int(pExplain, 1);
5700: int iFrom = sqlite3_column_int(pExplain, 2);
5701: const char *zDetail = (const char *)sqlite3_column_text(pExplain, 3);
5702:
5703: printf("%d %d %d %s\n", iSelectid, iOrder, iFrom, zDetail);
5704: }
5705:
5706: return sqlite3_finalize(pExplain);
5707: }
5708:
5709: static int test_print_eqp(
5710: void * clientData,
5711: Tcl_Interp *interp,
5712: int objc,
5713: Tcl_Obj *CONST objv[]
5714: ){
5715: int rc;
5716: sqlite3_stmt *pStmt;
5717:
5718: if( objc!=2 ){
5719: Tcl_WrongNumArgs(interp, 1, objv, "STMT");
5720: return TCL_ERROR;
5721: }
5722: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
5723: rc = printExplainQueryPlan(pStmt);
5724: /* This is needed on Windows so that a test case using this
5725: ** function can open a read pipe and get the output of
5726: ** printExplainQueryPlan() immediately.
5727: */
5728: fflush(stdout);
5729: Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
5730: return TCL_OK;
5731: }
5732: #endif /* SQLITE_OMIT_EXPLAIN */
5733:
5734: /*
5735: ** sqlite3_test_control VERB ARGS...
5736: */
5737: static int test_test_control(
5738: void * clientData,
5739: Tcl_Interp *interp,
5740: int objc,
5741: Tcl_Obj *CONST objv[]
5742: ){
5743: struct Verb {
5744: const char *zName;
5745: int i;
5746: } aVerb[] = {
5747: { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
5748: };
5749: int iVerb;
5750: int iFlag;
5751: int rc;
5752:
5753: if( objc<2 ){
5754: Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS...");
5755: return TCL_ERROR;
5756: }
5757:
5758: rc = Tcl_GetIndexFromObjStruct(
5759: interp, objv[1], aVerb, sizeof(aVerb[0]), "VERB", 0, &iVerb
5760: );
5761: if( rc!=TCL_OK ) return rc;
5762:
5763: iFlag = aVerb[iVerb].i;
5764: switch( iFlag ){
5765: case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
5766: int val;
5767: if( objc!=3 ){
5768: Tcl_WrongNumArgs(interp, 2, objv, "ONOFF");
5769: return TCL_ERROR;
5770: }
5771: if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
5772: sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val);
5773: break;
5774: }
5775: }
5776:
5777: Tcl_ResetResult(interp);
5778: return TCL_OK;
5779: }
5780:
5781: #if SQLITE_OS_WIN
5782: /*
5783: ** Information passed from the main thread into the windows file locker
5784: ** background thread.
5785: */
5786: struct win32FileLocker {
5787: char *evName; /* Name of event to signal thread startup */
5788: HANDLE h; /* Handle of the file to be locked */
5789: int delay1; /* Delay before locking */
5790: int delay2; /* Delay before unlocking */
5791: int ok; /* Finished ok */
5792: int err; /* True if an error occurs */
5793: };
5794: #endif
5795:
5796:
5797: #if SQLITE_OS_WIN
5798: /*
5799: ** The background thread that does file locking.
5800: */
5801: static void win32_file_locker(void *pAppData){
5802: struct win32FileLocker *p = (struct win32FileLocker*)pAppData;
5803: if( p->evName ){
5804: HANDLE ev = OpenEvent(EVENT_MODIFY_STATE, FALSE, p->evName);
5805: if ( ev ){
5806: SetEvent(ev);
5807: CloseHandle(ev);
5808: }
5809: }
5810: if( p->delay1 ) Sleep(p->delay1);
5811: if( LockFile(p->h, 0, 0, 100000000, 0) ){
5812: Sleep(p->delay2);
5813: UnlockFile(p->h, 0, 0, 100000000, 0);
5814: p->ok = 1;
5815: }else{
5816: p->err = 1;
5817: }
5818: CloseHandle(p->h);
5819: p->h = 0;
5820: p->delay1 = 0;
5821: p->delay2 = 0;
5822: }
5823: #endif
5824:
5825: #if SQLITE_OS_WIN
5826: /*
5827: ** lock_win32_file FILENAME DELAY1 DELAY2
5828: **
5829: ** Get an exclusive manditory lock on file for DELAY2 milliseconds.
5830: ** Wait DELAY1 milliseconds before acquiring the lock.
5831: */
5832: static int win32_file_lock(
5833: void * clientData,
5834: Tcl_Interp *interp,
5835: int objc,
5836: Tcl_Obj *CONST objv[]
5837: ){
5838: static struct win32FileLocker x = { "win32_file_lock", 0, 0, 0, 0, 0 };
5839: const char *zFilename;
5840: char zBuf[200];
5841: int retry = 0;
5842: HANDLE ev;
5843: DWORD wResult;
5844:
5845: if( objc!=4 && objc!=1 ){
5846: Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2");
5847: return TCL_ERROR;
5848: }
5849: if( objc==1 ){
5850: sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d",
5851: x.ok, x.err, x.delay1, x.delay2, x.h);
5852: Tcl_AppendResult(interp, zBuf, (char*)0);
5853: return TCL_OK;
5854: }
5855: while( x.h && retry<30 ){
5856: retry++;
5857: Sleep(100);
5858: }
5859: if( x.h ){
5860: Tcl_AppendResult(interp, "busy", (char*)0);
5861: return TCL_ERROR;
5862: }
5863: if( Tcl_GetIntFromObj(interp, objv[2], &x.delay1) ) return TCL_ERROR;
5864: if( Tcl_GetIntFromObj(interp, objv[3], &x.delay2) ) return TCL_ERROR;
5865: zFilename = Tcl_GetString(objv[1]);
5866: x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE,
5867: FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
5868: FILE_ATTRIBUTE_NORMAL, 0);
5869: if( !x.h ){
5870: Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0);
5871: return TCL_ERROR;
5872: }
5873: ev = CreateEvent(NULL, TRUE, FALSE, x.evName);
5874: if ( !ev ){
5875: Tcl_AppendResult(interp, "cannot create event: ", x.evName, (char*)0);
5876: return TCL_ERROR;
5877: }
5878: _beginthread(win32_file_locker, 0, (void*)&x);
5879: Sleep(0);
5880: if ( (wResult = WaitForSingleObject(ev, 10000))!=WAIT_OBJECT_0 ){
5881: sqlite3_snprintf(sizeof(zBuf), zBuf, "0x%x", wResult);
5882: Tcl_AppendResult(interp, "wait failed: ", zBuf, (char*)0);
5883: CloseHandle(ev);
5884: return TCL_ERROR;
5885: }
5886: CloseHandle(ev);
5887: return TCL_OK;
5888: }
5889: #endif
5890:
5891:
5892: /*
5893: ** optimization_control DB OPT BOOLEAN
5894: **
5895: ** Enable or disable query optimizations using the sqlite3_test_control()
5896: ** interface. Disable if BOOLEAN is false and enable if BOOLEAN is true.
5897: ** OPT is the name of the optimization to be disabled.
5898: */
5899: static int optimization_control(
5900: void * clientData,
5901: Tcl_Interp *interp,
5902: int objc,
5903: Tcl_Obj *CONST objv[]
5904: ){
5905: int i;
5906: sqlite3 *db;
5907: const char *zOpt;
5908: int onoff;
5909: int mask;
5910: static const struct {
5911: const char *zOptName;
5912: int mask;
5913: } aOpt[] = {
5914: { "all", SQLITE_OptMask },
5915: { "query-flattener", SQLITE_QueryFlattener },
5916: { "column-cache", SQLITE_ColumnCache },
5917: { "index-sort", SQLITE_IndexSort },
5918: { "index-search", SQLITE_IndexSearch },
5919: { "index-cover", SQLITE_IndexCover },
5920: { "groupby-order", SQLITE_GroupByOrder },
5921: { "factor-constants", SQLITE_FactorOutConst },
5922: { "real-as-int", SQLITE_IdxRealAsInt },
5923: };
5924:
5925: if( objc!=4 ){
5926: Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN");
5927: return TCL_ERROR;
5928: }
5929: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
5930: if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR;
5931: zOpt = Tcl_GetString(objv[2]);
5932: for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
5933: if( strcmp(zOpt, aOpt[i].zOptName)==0 ){
5934: mask = aOpt[i].mask;
5935: break;
5936: }
5937: }
5938: if( onoff ) mask = ~mask;
5939: if( i>=sizeof(aOpt)/sizeof(aOpt[0]) ){
5940: Tcl_AppendResult(interp, "unknown optimization - should be one of:",
5941: (char*)0);
5942: for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
5943: Tcl_AppendResult(interp, " ", aOpt[i].zOptName);
5944: }
5945: return TCL_ERROR;
5946: }
5947: sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask);
5948: return TCL_OK;
5949: }
5950:
5951: /*
5952: ** Register commands with the TCL interpreter.
5953: */
5954: int Sqlitetest1_Init(Tcl_Interp *interp){
5955: extern int sqlite3_search_count;
5956: extern int sqlite3_found_count;
5957: extern int sqlite3_interrupt_count;
5958: extern int sqlite3_open_file_count;
5959: extern int sqlite3_sort_count;
5960: extern int sqlite3_current_time;
5961: #if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
5962: extern int sqlite3_hostid_num;
5963: #endif
5964: extern int sqlite3_max_blobsize;
5965: extern int sqlite3BtreeSharedCacheReport(void*,
5966: Tcl_Interp*,int,Tcl_Obj*CONST*);
5967: static struct {
5968: char *zName;
5969: Tcl_CmdProc *xProc;
5970: } aCmd[] = {
5971: { "db_enter", (Tcl_CmdProc*)db_enter },
5972: { "db_leave", (Tcl_CmdProc*)db_leave },
5973: { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int },
5974: { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 },
5975: { "sqlite3_mprintf_long", (Tcl_CmdProc*)sqlite3_mprintf_long },
5976: { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str },
5977: { "sqlite3_snprintf_str", (Tcl_CmdProc*)sqlite3_snprintf_str },
5978: { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly},
5979: { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double },
5980: { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled },
5981: { "sqlite3_mprintf_hexdouble", (Tcl_CmdProc*)sqlite3_mprintf_hexdouble},
5982: { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z },
5983: { "sqlite3_mprintf_n_test", (Tcl_CmdProc*)test_mprintf_n },
5984: { "sqlite3_snprintf_int", (Tcl_CmdProc*)test_snprintf_int },
5985: { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid },
5986: { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf },
5987: { "sqlite3_exec_hex", (Tcl_CmdProc*)test_exec_hex },
5988: { "sqlite3_exec", (Tcl_CmdProc*)test_exec },
5989: { "sqlite3_exec_nr", (Tcl_CmdProc*)test_exec_nr },
5990: #ifndef SQLITE_OMIT_GET_TABLE
5991: { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
5992: #endif
5993: { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close },
5994: { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
5995: { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
5996: { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
5997: { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
5998: { "sqlite_bind", (Tcl_CmdProc*)test_bind },
5999: { "breakpoint", (Tcl_CmdProc*)test_breakpoint },
6000: { "sqlite3_key", (Tcl_CmdProc*)test_key },
6001: { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey },
6002: { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic },
6003: { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt },
6004: { "sqlite_delete_function", (Tcl_CmdProc*)delete_function },
6005: { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation },
6006: { "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit },
6007: { "sqlite3_stack_used", (Tcl_CmdProc*)test_stack_used },
6008: { "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout },
6009: { "printf", (Tcl_CmdProc*)test_printf },
6010: { "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace },
6011: };
6012: static struct {
6013: char *zName;
6014: Tcl_ObjCmdProc *xProc;
6015: void *clientData;
6016: } aObjCmd[] = {
6017: { "sqlite3_connection_pointer", get_sqlite_pointer, 0 },
6018: { "sqlite3_bind_int", test_bind_int, 0 },
6019: { "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 },
6020: { "sqlite3_bind_int64", test_bind_int64, 0 },
6021: { "sqlite3_bind_double", test_bind_double, 0 },
6022: { "sqlite3_bind_null", test_bind_null ,0 },
6023: { "sqlite3_bind_text", test_bind_text ,0 },
6024: { "sqlite3_bind_text16", test_bind_text16 ,0 },
6025: { "sqlite3_bind_blob", test_bind_blob ,0 },
6026: { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0},
6027: { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0},
6028: { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0},
6029: { "sqlite3_clear_bindings", test_clear_bindings, 0},
6030: { "sqlite3_sleep", test_sleep, 0},
6031: { "sqlite3_errcode", test_errcode ,0 },
6032: { "sqlite3_extended_errcode", test_ex_errcode ,0 },
6033: { "sqlite3_errmsg", test_errmsg ,0 },
6034: { "sqlite3_errmsg16", test_errmsg16 ,0 },
6035: { "sqlite3_open", test_open ,0 },
6036: { "sqlite3_open16", test_open16 ,0 },
6037: { "sqlite3_open_v2", test_open_v2 ,0 },
6038: { "sqlite3_complete16", test_complete16 ,0 },
6039:
6040: { "sqlite3_prepare", test_prepare ,0 },
6041: { "sqlite3_prepare16", test_prepare16 ,0 },
6042: { "sqlite3_prepare_v2", test_prepare_v2 ,0 },
6043: { "sqlite3_prepare_tkt3134", test_prepare_tkt3134, 0},
6044: { "sqlite3_prepare16_v2", test_prepare16_v2 ,0 },
6045: { "sqlite3_finalize", test_finalize ,0 },
6046: { "sqlite3_stmt_status", test_stmt_status ,0 },
6047: { "sqlite3_reset", test_reset ,0 },
6048: { "sqlite3_expired", test_expired ,0 },
6049: { "sqlite3_transfer_bindings", test_transfer_bind ,0 },
6050: { "sqlite3_changes", test_changes ,0 },
6051: { "sqlite3_step", test_step ,0 },
6052: { "sqlite3_sql", test_sql ,0 },
6053: { "sqlite3_next_stmt", test_next_stmt ,0 },
6054: { "sqlite3_stmt_readonly", test_stmt_readonly ,0 },
6055: { "sqlite3_stmt_busy", test_stmt_busy ,0 },
6056: { "uses_stmt_journal", uses_stmt_journal ,0 },
6057:
6058: { "sqlite3_release_memory", test_release_memory, 0},
6059: { "sqlite3_db_release_memory", test_db_release_memory, 0},
6060: { "sqlite3_db_filename", test_db_filename, 0},
6061: { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
6062: { "sqlite3_thread_cleanup", test_thread_cleanup, 0},
6063: { "sqlite3_pager_refcounts", test_pager_refcounts, 0},
6064:
6065: { "sqlite3_load_extension", test_load_extension, 0},
6066: { "sqlite3_enable_load_extension", test_enable_load, 0},
6067: { "sqlite3_extended_result_codes", test_extended_result_codes, 0},
6068: { "sqlite3_limit", test_limit, 0},
6069:
6070: { "save_prng_state", save_prng_state, 0 },
6071: { "restore_prng_state", restore_prng_state, 0 },
6072: { "reset_prng_state", reset_prng_state, 0 },
6073: { "optimization_control", optimization_control,0},
6074: #if SQLITE_OS_WIN
6075: { "lock_win32_file", win32_file_lock, 0 },
6076: #endif
6077: { "tcl_objproc", runAsObjProc, 0 },
6078:
6079: /* sqlite3_column_*() API */
6080: { "sqlite3_column_count", test_column_count ,0 },
6081: { "sqlite3_data_count", test_data_count ,0 },
6082: { "sqlite3_column_type", test_column_type ,0 },
6083: { "sqlite3_column_blob", test_column_blob ,0 },
6084: { "sqlite3_column_double", test_column_double ,0 },
6085: { "sqlite3_column_int64", test_column_int64 ,0 },
6086: { "sqlite3_column_text", test_stmt_utf8, (void*)sqlite3_column_text },
6087: { "sqlite3_column_name", test_stmt_utf8, (void*)sqlite3_column_name },
6088: { "sqlite3_column_int", test_stmt_int, (void*)sqlite3_column_int },
6089: { "sqlite3_column_bytes", test_stmt_int, (void*)sqlite3_column_bytes},
6090: #ifndef SQLITE_OMIT_DECLTYPE
6091: { "sqlite3_column_decltype",test_stmt_utf8,(void*)sqlite3_column_decltype},
6092: #endif
6093: #ifdef SQLITE_ENABLE_COLUMN_METADATA
6094: { "sqlite3_column_database_name",test_stmt_utf8,(void*)sqlite3_column_database_name},
6095: { "sqlite3_column_table_name",test_stmt_utf8,(void*)sqlite3_column_table_name},
6096: { "sqlite3_column_origin_name",test_stmt_utf8,(void*)sqlite3_column_origin_name},
6097: #endif
6098:
6099: #ifndef SQLITE_OMIT_UTF16
6100: { "sqlite3_column_bytes16", test_stmt_int, (void*)sqlite3_column_bytes16 },
6101: { "sqlite3_column_text16", test_stmt_utf16, (void*)sqlite3_column_text16},
6102: { "sqlite3_column_name16", test_stmt_utf16, (void*)sqlite3_column_name16},
6103: { "add_alignment_test_collations", add_alignment_test_collations, 0 },
6104: #ifndef SQLITE_OMIT_DECLTYPE
6105: { "sqlite3_column_decltype16",test_stmt_utf16,(void*)sqlite3_column_decltype16},
6106: #endif
6107: #ifdef SQLITE_ENABLE_COLUMN_METADATA
6108: {"sqlite3_column_database_name16",
6109: test_stmt_utf16, sqlite3_column_database_name16},
6110: {"sqlite3_column_table_name16", test_stmt_utf16, (void*)sqlite3_column_table_name16},
6111: {"sqlite3_column_origin_name16", test_stmt_utf16, (void*)sqlite3_column_origin_name16},
6112: #endif
6113: #endif
6114: { "sqlite3_create_collation_v2", test_create_collation_v2, 0 },
6115: { "sqlite3_global_recover", test_global_recover, 0 },
6116: { "working_64bit_int", working_64bit_int, 0 },
6117: { "vfs_unlink_test", vfs_unlink_test, 0 },
6118: { "vfs_initfail_test", vfs_initfail_test, 0 },
6119: { "vfs_unregister_all", vfs_unregister_all, 0 },
6120: { "vfs_reregister_all", vfs_reregister_all, 0 },
6121: { "file_control_test", file_control_test, 0 },
6122: { "file_control_lasterrno_test", file_control_lasterrno_test, 0 },
6123: { "file_control_lockproxy_test", file_control_lockproxy_test, 0 },
6124: { "file_control_chunksize_test", file_control_chunksize_test, 0 },
6125: { "file_control_sizehint_test", file_control_sizehint_test, 0 },
6126: { "file_control_win32_av_retry", file_control_win32_av_retry, 0 },
6127: { "file_control_persist_wal", file_control_persist_wal, 0 },
6128: { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
6129: { "file_control_vfsname", file_control_vfsname, 0 },
6130: { "sqlite3_vfs_list", vfs_list, 0 },
6131: { "sqlite3_create_function_v2", test_create_function_v2, 0 },
6132:
6133: /* Functions from os.h */
6134: #ifndef SQLITE_OMIT_UTF16
6135: { "add_test_collate", test_collate, 0 },
6136: { "add_test_collate_needed", test_collate_needed, 0 },
6137: { "add_test_function", test_function, 0 },
6138: #endif
6139: { "sqlite3_test_errstr", test_errstr, 0 },
6140: { "tcl_variable_type", tcl_variable_type, 0 },
6141: #ifndef SQLITE_OMIT_SHARED_CACHE
6142: { "sqlite3_enable_shared_cache", test_enable_shared, 0 },
6143: { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0},
6144: #endif
6145: { "sqlite3_libversion_number", test_libversion_number, 0 },
6146: #ifdef SQLITE_ENABLE_COLUMN_METADATA
6147: { "sqlite3_table_column_metadata", test_table_column_metadata, 0 },
6148: #endif
6149: #ifndef SQLITE_OMIT_INCRBLOB
6150: { "sqlite3_blob_read", test_blob_read, 0 },
6151: { "sqlite3_blob_write", test_blob_write, 0 },
6152: { "sqlite3_blob_reopen", test_blob_reopen, 0 },
6153: { "sqlite3_blob_bytes", test_blob_bytes, 0 },
6154: { "sqlite3_blob_close", test_blob_close, 0 },
6155: #endif
6156: { "pcache_stats", test_pcache_stats, 0 },
6157: #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
6158: { "sqlite3_unlock_notify", test_unlock_notify, 0 },
6159: #endif
6160: { "sqlite3_wal_checkpoint", test_wal_checkpoint, 0 },
6161: { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0 },
6162: { "test_sqlite3_log", test_sqlite3_log, 0 },
6163: #ifndef SQLITE_OMIT_EXPLAIN
6164: { "print_explain_query_plan", test_print_eqp, 0 },
6165: #endif
6166: { "sqlite3_test_control", test_test_control },
6167: };
6168: static int bitmask_size = sizeof(Bitmask)*8;
6169: int i;
6170: extern int sqlite3_sync_count, sqlite3_fullsync_count;
6171: extern int sqlite3_opentemp_count;
6172: extern int sqlite3_like_count;
6173: extern int sqlite3_xferopt_count;
6174: extern int sqlite3_pager_readdb_count;
6175: extern int sqlite3_pager_writedb_count;
6176: extern int sqlite3_pager_writej_count;
6177: #if SQLITE_OS_WIN
6178: extern int sqlite3_os_type;
6179: #endif
6180: #ifdef SQLITE_DEBUG
6181: extern int sqlite3WhereTrace;
6182: extern int sqlite3OSTrace;
6183: extern int sqlite3VdbeAddopTrace;
6184: extern int sqlite3WalTrace;
6185: #endif
6186: #ifdef SQLITE_TEST
6187: extern char sqlite3_query_plan[];
6188: static char *query_plan = sqlite3_query_plan;
6189: #ifdef SQLITE_ENABLE_FTS3
6190: extern int sqlite3_fts3_enable_parentheses;
6191: #endif
6192: #endif
6193:
6194: for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
6195: Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
6196: }
6197: for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
6198: Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
6199: aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
6200: }
6201: Tcl_LinkVar(interp, "sqlite_search_count",
6202: (char*)&sqlite3_search_count, TCL_LINK_INT);
6203: Tcl_LinkVar(interp, "sqlite_found_count",
6204: (char*)&sqlite3_found_count, TCL_LINK_INT);
6205: Tcl_LinkVar(interp, "sqlite_sort_count",
6206: (char*)&sqlite3_sort_count, TCL_LINK_INT);
6207: Tcl_LinkVar(interp, "sqlite3_max_blobsize",
6208: (char*)&sqlite3_max_blobsize, TCL_LINK_INT);
6209: Tcl_LinkVar(interp, "sqlite_like_count",
6210: (char*)&sqlite3_like_count, TCL_LINK_INT);
6211: Tcl_LinkVar(interp, "sqlite_interrupt_count",
6212: (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
6213: Tcl_LinkVar(interp, "sqlite_open_file_count",
6214: (char*)&sqlite3_open_file_count, TCL_LINK_INT);
6215: Tcl_LinkVar(interp, "sqlite_current_time",
6216: (char*)&sqlite3_current_time, TCL_LINK_INT);
6217: #if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
6218: Tcl_LinkVar(interp, "sqlite_hostid_num",
6219: (char*)&sqlite3_hostid_num, TCL_LINK_INT);
6220: #endif
6221: Tcl_LinkVar(interp, "sqlite3_xferopt_count",
6222: (char*)&sqlite3_xferopt_count, TCL_LINK_INT);
6223: Tcl_LinkVar(interp, "sqlite3_pager_readdb_count",
6224: (char*)&sqlite3_pager_readdb_count, TCL_LINK_INT);
6225: Tcl_LinkVar(interp, "sqlite3_pager_writedb_count",
6226: (char*)&sqlite3_pager_writedb_count, TCL_LINK_INT);
6227: Tcl_LinkVar(interp, "sqlite3_pager_writej_count",
6228: (char*)&sqlite3_pager_writej_count, TCL_LINK_INT);
6229: #ifndef SQLITE_OMIT_UTF16
6230: Tcl_LinkVar(interp, "unaligned_string_counter",
6231: (char*)&unaligned_string_counter, TCL_LINK_INT);
6232: #endif
6233: #ifndef SQLITE_OMIT_UTF16
6234: Tcl_LinkVar(interp, "sqlite_last_needed_collation",
6235: (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
6236: #endif
6237: #if SQLITE_OS_WIN
6238: Tcl_LinkVar(interp, "sqlite_os_type",
6239: (char*)&sqlite3_os_type, TCL_LINK_INT);
6240: #endif
6241: #ifdef SQLITE_TEST
6242: Tcl_LinkVar(interp, "sqlite_query_plan",
6243: (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
6244: #endif
6245: #ifdef SQLITE_DEBUG
6246: Tcl_LinkVar(interp, "sqlite_addop_trace",
6247: (char*)&sqlite3VdbeAddopTrace, TCL_LINK_INT);
6248: Tcl_LinkVar(interp, "sqlite_where_trace",
6249: (char*)&sqlite3WhereTrace, TCL_LINK_INT);
6250: Tcl_LinkVar(interp, "sqlite_os_trace",
6251: (char*)&sqlite3OSTrace, TCL_LINK_INT);
6252: #ifndef SQLITE_OMIT_WAL
6253: Tcl_LinkVar(interp, "sqlite_wal_trace",
6254: (char*)&sqlite3WalTrace, TCL_LINK_INT);
6255: #endif
6256: #endif
6257: #ifndef SQLITE_OMIT_DISKIO
6258: Tcl_LinkVar(interp, "sqlite_opentemp_count",
6259: (char*)&sqlite3_opentemp_count, TCL_LINK_INT);
6260: #endif
6261: Tcl_LinkVar(interp, "sqlite_static_bind_value",
6262: (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
6263: Tcl_LinkVar(interp, "sqlite_static_bind_nbyte",
6264: (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT);
6265: Tcl_LinkVar(interp, "sqlite_temp_directory",
6266: (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
6267: Tcl_LinkVar(interp, "bitmask_size",
6268: (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
6269: Tcl_LinkVar(interp, "sqlite_sync_count",
6270: (char*)&sqlite3_sync_count, TCL_LINK_INT);
6271: Tcl_LinkVar(interp, "sqlite_fullsync_count",
6272: (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
6273: #if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST)
6274: Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses",
6275: (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT);
6276: #endif
6277: return TCL_OK;
6278: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>