4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
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.
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.
16 #include "sqliteInt.h"
22 #if defined(INCLUDE_SQLITE_TCL_H)
23 # include "sqlite_tcl.h"
31 ** This is a copy of the first part of the SqliteDb structure in
32 ** tclsqlite.c. We need it here so that the get_sqlite_pointer routine
33 ** can extract the sqlite3* pointer from an existing Tcl SQLite
41 ** Convert text generated by the "%p" conversion format back into
44 static int testHexToInt(int h
){
45 if( h
>='0' && h
<='9' ){
47 }else if( h
>='a' && h
<='f' ){
50 assert( h
>='A' && h
<='F' );
54 void *sqlite3TestTextToPtr(const char *z
){
58 if( z
[0]=='0' && z
[1]=='x' ){
63 v
= (v
<<4) + testHexToInt(*z
);
66 if( sizeof(p
)==sizeof(v
) ){
67 memcpy(&p
, &v
, sizeof(p
));
69 assert( sizeof(p
)==sizeof(v2
) );
71 memcpy(&p
, &v2
, sizeof(p
));
78 ** A TCL command that returns the address of the sqlite* pointer
79 ** for an sqlite connection instance. Bad things happen if the
80 ** input is not an sqlite connection.
82 static int SQLITE_TCLAPI
get_sqlite_pointer(
92 Tcl_WrongNumArgs(interp
, 1, objv
, "SQLITE-CONNECTION");
95 if( !Tcl_GetCommandInfo(interp
, Tcl_GetString(objv
[1]), &cmdInfo
) ){
96 Tcl_AppendResult(interp
, "command not found: ",
97 Tcl_GetString(objv
[1]), (char*)0);
100 p
= (struct SqliteDb
*)cmdInfo
.objClientData
;
101 sqlite3_snprintf(sizeof(zBuf
), zBuf
, "%p", p
->db
);
102 Tcl_AppendResult(interp
, zBuf
, 0);
107 ** Decode a pointer to an sqlite3 object.
109 int getDbPointer(Tcl_Interp
*interp
, const char *zA
, sqlite3
**ppDb
){
112 if( Tcl_GetCommandInfo(interp
, zA
, &cmdInfo
) ){
113 p
= (struct SqliteDb
*)cmdInfo
.objClientData
;
116 *ppDb
= (sqlite3
*)sqlite3TestTextToPtr(zA
);
123 ** Decode a Win32 HANDLE object.
125 int getWin32Handle(Tcl_Interp
*interp
, const char *zA
, LPHANDLE phFile
){
126 *phFile
= (HANDLE
)sqlite3TestTextToPtr(zA
);
131 extern const char *sqlite3ErrName(int);
132 #define t1ErrorName sqlite3ErrName
135 ** Convert an sqlite3_stmt* into an sqlite3*. This depends on the
136 ** fact that the sqlite3* is the first field in the Vdbe structure.
138 #define StmtToDb(X) sqlite3_db_handle(X)
141 ** Check a return value to make sure it agrees with the results
142 ** from sqlite3_errcode.
144 int sqlite3TestErrCode(Tcl_Interp
*interp
, sqlite3
*db
, int rc
){
145 if( sqlite3_threadsafe()==0 && rc
!=SQLITE_MISUSE
&& rc
!=SQLITE_OK
146 && sqlite3_errcode(db
)!=rc
){
148 int r2
= sqlite3_errcode(db
);
149 sqlite3_snprintf(sizeof(zBuf
), zBuf
,
150 "error code %s (%d) does not match sqlite3_errcode %s (%d)",
151 t1ErrorName(rc
), rc
, t1ErrorName(r2
), r2
);
152 Tcl_ResetResult(interp
);
153 Tcl_AppendResult(interp
, zBuf
, 0);
160 ** Decode a pointer to an sqlite3_stmt object.
162 static int getStmtPointer(
165 sqlite3_stmt
**ppStmt
167 *ppStmt
= (sqlite3_stmt
*)sqlite3TestTextToPtr(zArg
);
172 ** Generate a text representation of a pointer that can be understood
173 ** by the getDbPointer and getVmPointer routines above.
175 ** The problem is, on some machines (Solaris) if you do a printf with
176 ** "%p" you cannot turn around and do a scanf with the same "%p" and
177 ** get your pointer back. You have to prepend a "0x" before it will
178 ** work. Or at least that is what is reported to me (drh). But this
179 ** behavior varies from machine to machine. The solution used her is
180 ** to test the string right after it is generated to see if it can be
181 ** understood by scanf, and if not, try prepending an "0x" to see if
182 ** that helps. If nothing works, a fatal error is generated.
184 int sqlite3TestMakePointerStr(Tcl_Interp
*interp
, char *zPtr
, void *p
){
185 sqlite3_snprintf(100, zPtr
, "%p", p
);
190 ** The callback routine for sqlite3_exec_printf().
192 static int exec_printf_cb(void *pArg
, int argc
, char **argv
, char **name
){
193 Tcl_DString
*str
= (Tcl_DString
*)pArg
;
196 if( Tcl_DStringLength(str
)==0 ){
197 for(i
=0; i
<argc
; i
++){
198 Tcl_DStringAppendElement(str
, name
[i
] ? name
[i
] : "NULL");
201 for(i
=0; i
<argc
; i
++){
202 Tcl_DStringAppendElement(str
, argv
[i
] ? argv
[i
] : "NULL");
208 ** The I/O tracing callback.
210 #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
211 static FILE *iotrace_file
= 0;
212 static void io_trace_callback(const char *zFormat
, ...){
214 va_start(ap
, zFormat
);
215 vfprintf(iotrace_file
, zFormat
, ap
);
217 fflush(iotrace_file
);
222 ** Usage: io_trace FILENAME
224 ** Turn I/O tracing on or off. If FILENAME is not an empty string,
225 ** I/O tracing begins going into FILENAME. If FILENAME is an empty
226 ** string, I/O tracing is turned off.
228 static int SQLITE_TCLAPI
test_io_trace(
230 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
231 int argc
, /* Number of arguments */
232 char **argv
/* Text of each argument */
234 #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
236 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
241 if( iotrace_file
!=stdout
&& iotrace_file
!=stderr
){
242 fclose(iotrace_file
);
248 if( strcmp(argv
[1],"stdout")==0 ){
249 iotrace_file
= stdout
;
250 }else if( strcmp(argv
[1],"stderr")==0 ){
251 iotrace_file
= stderr
;
253 iotrace_file
= fopen(argv
[1], "w");
255 sqlite3IoTrace
= io_trace_callback
;
262 ** Usage: clang_sanitize_address
264 ** Returns true if the program was compiled using clang with the
265 ** -fsanitize=address switch on the command line. False otherwise.
267 ** Also return true if the OMIT_MISUSE environment variable exists.
269 static int SQLITE_TCLAPI
clang_sanitize_address(
271 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
272 int argc
, /* Number of arguments */
273 char **argv
/* Text of each argument */
276 #if defined(__has_feature)
277 # if __has_feature(address_sanitizer)
281 #ifdef __SANITIZE_ADDRESS__
284 if( res
==0 && getenv("OMIT_MISUSE")!=0 ) res
= 1;
285 Tcl_SetObjResult(interp
, Tcl_NewIntObj(res
));
290 ** Usage: sqlite3_exec_printf DB FORMAT STRING
292 ** Invoke the sqlite3_exec_printf() interface using the open database
293 ** DB. The SQL is the string FORMAT. The format string should contain
294 ** one %s or %q. STRING is the value inserted into %s or %q.
296 static int SQLITE_TCLAPI
test_exec_printf(
298 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
299 int argc
, /* Number of arguments */
300 char **argv
/* Text of each argument */
309 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
310 " DB FORMAT STRING", 0);
313 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
314 Tcl_DStringInit(&str
);
315 zSql
= sqlite3_mprintf(argv
[2], argv
[3]);
316 rc
= sqlite3_exec(db
, zSql
, exec_printf_cb
, &str
, &zErr
);
318 sqlite3_snprintf(sizeof(zBuf
), zBuf
, "%d", rc
);
319 Tcl_AppendElement(interp
, zBuf
);
320 Tcl_AppendElement(interp
, rc
==SQLITE_OK
? Tcl_DStringValue(&str
) : zErr
);
321 Tcl_DStringFree(&str
);
322 if( zErr
) sqlite3_free(zErr
);
323 if( sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
328 ** Usage: sqlite3_exec_hex DB HEX
330 ** Invoke the sqlite3_exec() on a string that is obtained by translating
331 ** HEX into ASCII. Most characters are translated as is. %HH becomes
334 static int SQLITE_TCLAPI
test_exec_hex(
336 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
337 int argc
, /* Number of arguments */
338 char **argv
/* Text of each argument */
348 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
352 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
354 for(i
=j
=0; i
<(sizeof(zSql
)-1) && zHex
[j
]; i
++, j
++){
355 if( zHex
[j
]=='%' && zHex
[j
+2] && zHex
[j
+2] ){
356 zSql
[i
] = (testHexToInt(zHex
[j
+1])<<4) + testHexToInt(zHex
[j
+2]);
363 Tcl_DStringInit(&str
);
364 rc
= sqlite3_exec(db
, zSql
, exec_printf_cb
, &str
, &zErr
);
365 sqlite3_snprintf(sizeof(zBuf
), zBuf
, "%d", rc
);
366 Tcl_AppendElement(interp
, zBuf
);
367 Tcl_AppendElement(interp
, rc
==SQLITE_OK
? Tcl_DStringValue(&str
) : zErr
);
368 Tcl_DStringFree(&str
);
369 if( zErr
) sqlite3_free(zErr
);
370 if( sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
375 ** Usage: db_enter DB
378 ** Enter or leave the mutex on a database connection.
380 static int SQLITE_TCLAPI
db_enter(
382 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
383 int argc
, /* Number of arguments */
384 char **argv
/* Text of each argument */
388 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
392 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
393 sqlite3_mutex_enter(db
->mutex
);
396 static int SQLITE_TCLAPI
db_leave(
398 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
399 int argc
, /* Number of arguments */
400 char **argv
/* Text of each argument */
404 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
408 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
409 sqlite3_mutex_leave(db
->mutex
);
414 ** Usage: sqlite3_exec DB SQL
416 ** Invoke the sqlite3_exec interface using the open database DB
418 static int SQLITE_TCLAPI
test_exec(
420 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
421 int argc
, /* Number of arguments */
422 char **argv
/* Text of each argument */
432 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
436 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
437 Tcl_DStringInit(&str
);
438 zSql
= sqlite3_mprintf("%s", argv
[2]);
439 for(i
=j
=0; zSql
[i
];){
441 zSql
[j
++] = (testHexToInt(zSql
[i
+1])<<4) + testHexToInt(zSql
[i
+2]);
444 zSql
[j
++] = zSql
[i
++];
448 rc
= sqlite3_exec(db
, zSql
, exec_printf_cb
, &str
, &zErr
);
450 sqlite3_snprintf(sizeof(zBuf
), zBuf
, "%d", rc
);
451 Tcl_AppendElement(interp
, zBuf
);
452 Tcl_AppendElement(interp
, rc
==SQLITE_OK
? Tcl_DStringValue(&str
) : zErr
);
453 Tcl_DStringFree(&str
);
454 if( zErr
) sqlite3_free(zErr
);
455 if( sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
460 ** Usage: sqlite3_exec_nr DB SQL
462 ** Invoke the sqlite3_exec interface using the open database DB. Discard
465 static int SQLITE_TCLAPI
test_exec_nr(
467 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
468 int argc
, /* Number of arguments */
469 char **argv
/* Text of each argument */
475 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
479 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
480 rc
= sqlite3_exec(db
, argv
[2], 0, 0, &zErr
);
481 if( sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
486 ** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ...
488 ** Test the %z format of sqlite_mprintf(). Use multiple mprintf() calls to
489 ** concatenate arg0 through argn using separator as the separator.
490 ** Return the result.
492 static int SQLITE_TCLAPI
test_mprintf_z(
494 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
495 int argc
, /* Number of arguments */
496 char **argv
/* Text of each argument */
501 for(i
=2; i
<argc
&& (i
==2 || zResult
); i
++){
502 zResult
= sqlite3_mprintf("%z%s%s", zResult
, argv
[1], argv
[i
]);
504 Tcl_AppendResult(interp
, zResult
, 0);
505 sqlite3_free(zResult
);
510 ** Usage: sqlite3_mprintf_n_test STRING
512 ** Test the %n format of sqlite_mprintf(). Return the length of the
515 static int SQLITE_TCLAPI
test_mprintf_n(
517 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
518 int argc
, /* Number of arguments */
519 char **argv
/* Text of each argument */
523 zStr
= sqlite3_mprintf("%s%n", argv
[1], &n
);
525 Tcl_SetObjResult(interp
, Tcl_NewIntObj(n
));
530 ** Usage: sqlite3_snprintf_int SIZE FORMAT INT
532 ** Test the of sqlite3_snprintf() routine. SIZE is the size of the
533 ** output buffer in bytes. The maximum size is 100. FORMAT is the
534 ** format string. INT is a single integer argument. The FORMAT
535 ** string must require no more than this one integer argument. If
536 ** You pass in a format string that requires more than one argument,
537 ** bad things will happen.
539 static int SQLITE_TCLAPI
test_snprintf_int(
541 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
542 int argc
, /* Number of arguments */
543 char **argv
/* Text of each argument */
546 int n
= atoi(argv
[1]);
547 const char *zFormat
= argv
[2];
548 int a1
= atoi(argv
[3]);
549 if( n
>sizeof(zStr
) ) n
= sizeof(zStr
);
550 sqlite3_snprintf(sizeof(zStr
), zStr
, "abcdefghijklmnopqrstuvwxyz");
551 sqlite3_snprintf(n
, zStr
, zFormat
, a1
);
552 Tcl_AppendResult(interp
, zStr
, 0);
556 #ifndef SQLITE_OMIT_GET_TABLE
559 ** Usage: sqlite3_get_table_printf DB FORMAT STRING ?--no-counts?
561 ** Invoke the sqlite3_get_table_printf() interface using the open database
562 ** DB. The SQL is the string FORMAT. The format string should contain
563 ** one %s or %q. STRING is the value inserted into %s or %q.
565 static int SQLITE_TCLAPI
test_get_table_printf(
567 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
568 int argc
, /* Number of arguments */
569 char **argv
/* Text of each argument */
575 int nRow
= 0, nCol
= 0;
582 if( Tcl_GetInt(interp
, argv
[4], &resCount
) ) return TCL_ERROR
;
584 if( argc
!=4 && argc
!=5 ){
585 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
586 " DB FORMAT STRING ?COUNT?", 0);
589 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
590 Tcl_DStringInit(&str
);
591 zSql
= sqlite3_mprintf(argv
[2],argv
[3]);
593 rc
= sqlite3_get_table(db
, zSql
, &aResult
, 0, 0, &zErr
);
595 rc
= sqlite3_get_table(db
, zSql
, &aResult
, &nRow
, &nCol
, &zErr
);
596 resCount
= (nRow
+1)*nCol
;
599 sqlite3_snprintf(sizeof(zBuf
), zBuf
, "%d", rc
);
600 Tcl_AppendElement(interp
, zBuf
);
603 sqlite3_snprintf(sizeof(zBuf
), zBuf
, "%d", nRow
);
604 Tcl_AppendElement(interp
, zBuf
);
605 sqlite3_snprintf(sizeof(zBuf
), zBuf
, "%d", nCol
);
606 Tcl_AppendElement(interp
, zBuf
);
608 for(i
=0; i
<resCount
; i
++){
609 Tcl_AppendElement(interp
, aResult
[i
] ? aResult
[i
] : "NULL");
612 Tcl_AppendElement(interp
, zErr
);
614 sqlite3_free_table(aResult
);
615 if( zErr
) sqlite3_free(zErr
);
616 if( sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
620 #endif /* SQLITE_OMIT_GET_TABLE */
624 ** Usage: sqlite3_last_insert_rowid DB
626 ** Returns the integer ROWID of the most recent insert.
628 static int SQLITE_TCLAPI
test_last_rowid(
630 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
631 int argc
, /* Number of arguments */
632 char **argv
/* Text of each argument */
638 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0], " DB\"", 0);
641 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
642 sqlite3_snprintf(sizeof(zBuf
), zBuf
, "%lld", sqlite3_last_insert_rowid(db
));
643 Tcl_AppendResult(interp
, zBuf
, 0);
648 ** Usage: sqlite3_key DB KEY
650 ** Set the codec key.
652 static int SQLITE_TCLAPI
test_key(
654 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
655 int argc
, /* Number of arguments */
656 char **argv
/* Text of each argument */
658 #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
663 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
667 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
670 sqlite3_key(db
, zKey
, nKey
);
676 ** Usage: sqlite3_rekey DB KEY
678 ** Change the codec key.
680 static int SQLITE_TCLAPI
test_rekey(
682 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
683 int argc
, /* Number of arguments */
684 char **argv
/* Text of each argument */
686 #ifdef SQLITE_HAS_CODEC
691 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
695 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
698 sqlite3_rekey(db
, zKey
, nKey
);
704 ** Usage: sqlite3_close DB
706 ** Closes the database opened by sqlite3_open.
708 static int SQLITE_TCLAPI
sqlite_test_close(
710 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
711 int argc
, /* Number of arguments */
712 char **argv
/* Text of each argument */
717 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
721 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
722 rc
= sqlite3_close(db
);
723 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), TCL_STATIC
);
728 ** Usage: sqlite3_close_v2 DB
730 ** Closes the database opened by sqlite3_open.
732 static int SQLITE_TCLAPI
sqlite_test_close_v2(
734 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
735 int argc
, /* Number of arguments */
736 char **argv
/* Text of each argument */
741 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
745 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
746 rc
= sqlite3_close_v2(db
);
747 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), TCL_STATIC
);
752 ** Implementation of the x_coalesce() function.
753 ** Return the first argument non-NULL argument.
755 static void t1_ifnullFunc(
756 sqlite3_context
*context
,
761 for(i
=0; i
<argc
; i
++){
762 if( SQLITE_NULL
!=sqlite3_value_type(argv
[i
]) ){
763 int n
= sqlite3_value_bytes(argv
[i
]);
764 sqlite3_result_text(context
, (char*)sqlite3_value_text(argv
[i
]),
765 n
, SQLITE_TRANSIENT
);
772 ** These are test functions. hex8() interprets its argument as
773 ** UTF8 and returns a hex encoding. hex16le() interprets its argument
774 ** as UTF16le and returns a hex encoding.
776 static void hex8Func(sqlite3_context
*p
, int argc
, sqlite3_value
**argv
){
777 const unsigned char *z
;
780 z
= sqlite3_value_text(argv
[0]);
781 for(i
=0; i
<sizeof(zBuf
)/2 - 2 && z
[i
]; i
++){
782 sqlite3_snprintf(sizeof(zBuf
)-i
*2, &zBuf
[i
*2], "%02x", z
[i
]);
785 sqlite3_result_text(p
, (char*)zBuf
, -1, SQLITE_TRANSIENT
);
787 #ifndef SQLITE_OMIT_UTF16
788 static void hex16Func(sqlite3_context
*p
, int argc
, sqlite3_value
**argv
){
789 const unsigned short int *z
;
792 z
= sqlite3_value_text16(argv
[0]);
793 for(i
=0; i
<sizeof(zBuf
)/4 - 4 && z
[i
]; i
++){
794 sqlite3_snprintf(sizeof(zBuf
)-i
*4, &zBuf
[i
*4],"%04x", z
[i
]&0xff);
797 sqlite3_result_text(p
, (char*)zBuf
, -1, SQLITE_TRANSIENT
);
802 ** A structure into which to accumulate text.
805 int nAlloc
; /* Space allocated */
806 int nUsed
; /* Space used */
807 char *z
; /* The space */
811 ** Append text to a dstr
813 static void dstrAppend(struct dstr
*p
, const char *z
, int divider
){
814 int n
= (int)strlen(z
);
815 if( p
->nUsed
+ n
+ 2 > p
->nAlloc
){
817 p
->nAlloc
= p
->nAlloc
*2 + n
+ 200;
818 zNew
= sqlite3_realloc(p
->z
, p
->nAlloc
);
821 memset(p
, 0, sizeof(*p
));
826 if( divider
&& p
->nUsed
>0 ){
827 p
->z
[p
->nUsed
++] = divider
;
829 memcpy(&p
->z
[p
->nUsed
], z
, n
+1);
834 ** Invoked for each callback from sqlite3ExecFunc
836 static int execFuncCallback(void *pData
, int argc
, char **argv
, char **NotUsed
){
837 struct dstr
*p
= (struct dstr
*)pData
;
839 for(i
=0; i
<argc
; i
++){
841 dstrAppend(p
, "NULL", ' ');
843 dstrAppend(p
, argv
[i
], ' ');
850 ** Implementation of the x_sqlite_exec() function. This function takes
851 ** a single argument and attempts to execute that argument as SQL code.
852 ** This is illegal and should set the SQLITE_MISUSE flag on the database.
854 ** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec()
855 ** from within a function call.
857 ** This routine simulates the effect of having two threads attempt to
858 ** use the same database at the same time.
860 static void sqlite3ExecFunc(
861 sqlite3_context
*context
,
866 memset(&x
, 0, sizeof(x
));
867 (void)sqlite3_exec((sqlite3
*)sqlite3_user_data(context
),
868 (char*)sqlite3_value_text(argv
[0]),
869 execFuncCallback
, &x
, 0);
870 sqlite3_result_text(context
, x
.z
, x
.nUsed
, SQLITE_TRANSIENT
);
875 ** Implementation of tkt2213func(), a scalar function that takes exactly
876 ** one argument. It has two interesting features:
878 ** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*.
879 ** If the three pointers returned are not the same an SQL error is raised.
881 ** * Otherwise it returns a copy of the text representation of its
882 ** argument in such a way as the VDBE representation is a Mem* cell
883 ** with the MEM_Term flag clear.
885 ** Ticket #2213 can therefore be tested by evaluating the following
888 ** tkt2213func(tkt2213func('a string'));
890 static void tkt2213Function(
891 sqlite3_context
*context
,
896 unsigned char const *zText1
;
897 unsigned char const *zText2
;
898 unsigned char const *zText3
;
900 nText
= sqlite3_value_bytes(argv
[0]);
901 zText1
= sqlite3_value_text(argv
[0]);
902 zText2
= sqlite3_value_text(argv
[0]);
903 zText3
= sqlite3_value_text(argv
[0]);
905 if( zText1
!=zText2
|| zText2
!=zText3
){
906 sqlite3_result_error(context
, "tkt2213 is not fixed", -1);
908 char *zCopy
= (char *)sqlite3_malloc(nText
);
909 memcpy(zCopy
, zText1
, nText
);
910 sqlite3_result_text(context
, zCopy
, nText
, sqlite3_free
);
915 ** The following SQL function takes 4 arguments. The 2nd and
916 ** 4th argument must be one of these strings: 'text', 'text16',
917 ** or 'blob' corresponding to API functions
919 ** sqlite3_value_text()
920 ** sqlite3_value_text16()
921 ** sqlite3_value_blob()
923 ** The third argument is a string, either 'bytes' or 'bytes16' or 'noop',
924 ** corresponding to APIs:
926 ** sqlite3_value_bytes()
927 ** sqlite3_value_bytes16()
930 ** The APIs designated by the 2nd through 4th arguments are applied
931 ** to the first argument in order. If the pointers returned by the
932 ** second and fourth are different, this routine returns 1. Otherwise,
933 ** this routine returns 0.
935 ** This function is used to test to see when returned pointers from
936 ** the _text(), _text16() and _blob() APIs become invalidated.
938 static void ptrChngFunction(
939 sqlite3_context
*context
,
945 if( argc
!=4 ) return;
946 zCmd
= (const char*)sqlite3_value_text(argv
[1]);
947 if( zCmd
==0 ) return;
948 if( strcmp(zCmd
,"text")==0 ){
949 p1
= (const void*)sqlite3_value_text(argv
[0]);
950 #ifndef SQLITE_OMIT_UTF16
951 }else if( strcmp(zCmd
, "text16")==0 ){
952 p1
= (const void*)sqlite3_value_text16(argv
[0]);
954 }else if( strcmp(zCmd
, "blob")==0 ){
955 p1
= (const void*)sqlite3_value_blob(argv
[0]);
959 zCmd
= (const char*)sqlite3_value_text(argv
[2]);
960 if( zCmd
==0 ) return;
961 if( strcmp(zCmd
,"bytes")==0 ){
962 sqlite3_value_bytes(argv
[0]);
963 #ifndef SQLITE_OMIT_UTF16
964 }else if( strcmp(zCmd
, "bytes16")==0 ){
965 sqlite3_value_bytes16(argv
[0]);
967 }else if( strcmp(zCmd
, "noop")==0 ){
972 zCmd
= (const char*)sqlite3_value_text(argv
[3]);
973 if( zCmd
==0 ) return;
974 if( strcmp(zCmd
,"text")==0 ){
975 p2
= (const void*)sqlite3_value_text(argv
[0]);
976 #ifndef SQLITE_OMIT_UTF16
977 }else if( strcmp(zCmd
, "text16")==0 ){
978 p2
= (const void*)sqlite3_value_text16(argv
[0]);
980 }else if( strcmp(zCmd
, "blob")==0 ){
981 p2
= (const void*)sqlite3_value_blob(argv
[0]);
985 sqlite3_result_int(context
, p1
!=p2
);
989 ** This SQL function returns a different answer each time it is called, even if
990 ** the arguments are the same.
992 static void nondeterministicFunction(
993 sqlite3_context
*context
,
998 sqlite3_result_int(context
, cnt
++);
1002 ** Usage: sqlite3_create_function DB
1004 ** Call the sqlite3_create_function API on the given database in order
1005 ** to create a function named "x_coalesce". This function does the same thing
1006 ** as the "coalesce" function. This function also registers an SQL function
1007 ** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec()
1008 ** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
1009 ** The effect is similar to trying to use the same database connection from
1010 ** two threads at the same time.
1012 ** The original motivation for this routine was to be able to call the
1013 ** sqlite3_create_function function while a query is in progress in order
1014 ** to test the SQLITE_MISUSE detection logic.
1016 static int SQLITE_TCLAPI
test_create_function(
1018 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1019 int argc
, /* Number of arguments */
1020 char **argv
/* Text of each argument */
1026 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
1030 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
1031 rc
= sqlite3_create_function(db
, "x_coalesce", -1, SQLITE_UTF8
, 0,
1032 t1_ifnullFunc
, 0, 0);
1033 if( rc
==SQLITE_OK
){
1034 rc
= sqlite3_create_function(db
, "hex8", 1, SQLITE_UTF8
| SQLITE_DETERMINISTIC
,
1037 #ifndef SQLITE_OMIT_UTF16
1038 if( rc
==SQLITE_OK
){
1039 rc
= sqlite3_create_function(db
, "hex16", 1, SQLITE_UTF16
| SQLITE_DETERMINISTIC
,
1040 0, hex16Func
, 0, 0);
1043 if( rc
==SQLITE_OK
){
1044 rc
= sqlite3_create_function(db
, "tkt2213func", 1, SQLITE_ANY
, 0,
1045 tkt2213Function
, 0, 0);
1047 if( rc
==SQLITE_OK
){
1048 rc
= sqlite3_create_function(db
, "pointer_change", 4, SQLITE_ANY
, 0,
1049 ptrChngFunction
, 0, 0);
1052 /* Functions counter1() and counter2() have the same implementation - they
1053 ** both return an ascending integer with each call. But counter1() is marked
1054 ** as non-deterministic and counter2() is marked as deterministic.
1056 if( rc
==SQLITE_OK
){
1057 rc
= sqlite3_create_function(db
, "counter1", -1, SQLITE_UTF8
,
1058 0, nondeterministicFunction
, 0, 0);
1060 if( rc
==SQLITE_OK
){
1061 rc
= sqlite3_create_function(db
, "counter2", -1, SQLITE_UTF8
|SQLITE_DETERMINISTIC
,
1062 0, nondeterministicFunction
, 0, 0);
1065 #ifndef SQLITE_OMIT_UTF16
1066 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
1067 ** because it is not tested anywhere else. */
1068 if( rc
==SQLITE_OK
){
1070 sqlite3_value
*pVal
;
1071 sqlite3_mutex_enter(db
->mutex
);
1072 pVal
= sqlite3ValueNew(db
);
1073 sqlite3ValueSetStr(pVal
, -1, "x_sqlite_exec", SQLITE_UTF8
, SQLITE_STATIC
);
1074 zUtf16
= sqlite3ValueText(pVal
, SQLITE_UTF16NATIVE
);
1075 if( db
->mallocFailed
){
1078 rc
= sqlite3_create_function16(db
, zUtf16
,
1079 1, SQLITE_UTF16
, db
, sqlite3ExecFunc
, 0, 0);
1081 sqlite3ValueFree(pVal
);
1082 sqlite3_mutex_leave(db
->mutex
);
1086 if( sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
1087 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), 0);
1092 ** Routines to implement the x_count() aggregate function.
1094 ** x_count() counts the number of non-null arguments. But there are
1095 ** some twists for testing purposes.
1097 ** If the argument to x_count() is 40 then a UTF-8 error is reported
1098 ** on the step function. If x_count(41) is seen, then a UTF-16 error
1099 ** is reported on the step function. If the total count is 42, then
1100 ** a UTF-8 error is reported on the finalize function.
1102 typedef struct t1CountCtx t1CountCtx
;
1106 static void t1CountStep(
1107 sqlite3_context
*context
,
1109 sqlite3_value
**argv
1112 p
= sqlite3_aggregate_context(context
, sizeof(*p
));
1113 if( (argc
==0 || SQLITE_NULL
!=sqlite3_value_type(argv
[0]) ) && p
){
1117 int v
= sqlite3_value_int(argv
[0]);
1119 sqlite3_result_error(context
, "value of 40 handed to x_count", -1);
1120 #ifndef SQLITE_OMIT_UTF16
1122 const char zUtf16ErrMsg
[] = { 0, 0x61, 0, 0x62, 0, 0x63, 0, 0, 0};
1123 sqlite3_result_error16(context
, &zUtf16ErrMsg
[1-SQLITE_BIGENDIAN
], -1);
1128 static void t1CountFinalize(sqlite3_context
*context
){
1130 p
= sqlite3_aggregate_context(context
, sizeof(*p
));
1133 sqlite3_result_error(context
, "x_count totals to 42", -1);
1135 sqlite3_result_int(context
, p
? p
->n
: 0);
1140 #ifndef SQLITE_OMIT_DEPRECATED
1141 static void legacyCountStep(
1142 sqlite3_context
*context
,
1144 sqlite3_value
**argv
1149 static void legacyCountFinalize(sqlite3_context
*context
){
1150 sqlite3_result_int(context
, sqlite3_aggregate_count(context
));
1155 ** Usage: sqlite3_create_aggregate DB
1157 ** Call the sqlite3_create_function API on the given database in order
1158 ** to create a function named "x_count". This function is similar
1159 ** to the built-in count() function, with a few special quirks
1160 ** for testing the sqlite3_result_error() APIs.
1162 ** The original motivation for this routine was to be able to call the
1163 ** sqlite3_create_aggregate function while a query is in progress in order
1164 ** to test the SQLITE_MISUSE detection logic. See misuse.test.
1166 ** This routine was later extended to test the use of sqlite3_result_error()
1167 ** within aggregate functions.
1169 ** Later: It is now also extended to register the aggregate function
1170 ** "legacy_count()" with the supplied database handle. This is used
1171 ** to test the deprecated sqlite3_aggregate_count() API.
1173 static int SQLITE_TCLAPI
test_create_aggregate(
1175 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1176 int argc
, /* Number of arguments */
1177 char **argv
/* Text of each argument */
1182 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
1186 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
1187 rc
= sqlite3_create_function(db
, "x_count", 0, SQLITE_UTF8
, 0, 0,
1188 t1CountStep
,t1CountFinalize
);
1189 if( rc
==SQLITE_OK
){
1190 rc
= sqlite3_create_function(db
, "x_count", 1, SQLITE_UTF8
, 0, 0,
1191 t1CountStep
,t1CountFinalize
);
1193 #ifndef SQLITE_OMIT_DEPRECATED
1194 if( rc
==SQLITE_OK
){
1195 rc
= sqlite3_create_function(db
, "legacy_count", 0, SQLITE_ANY
, 0, 0,
1196 legacyCountStep
, legacyCountFinalize
1200 if( sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
1201 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), 0);
1207 ** Usage: printf TEXT
1209 ** Send output to printf. Use this rather than puts to merge the output
1210 ** in the correct sequence with debugging printfs inserted into C code.
1211 ** Puts uses a separate buffer and debugging statements will be out of
1212 ** sequence if it is used.
1214 static int SQLITE_TCLAPI
test_printf(
1216 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1217 int argc
, /* Number of arguments */
1218 char **argv
/* Text of each argument */
1221 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
1225 printf("%s\n", argv
[1]);
1232 ** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
1234 ** Call mprintf with three integer arguments
1236 static int SQLITE_TCLAPI
sqlite3_mprintf_int(
1238 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1239 int argc
, /* Number of arguments */
1240 char **argv
/* Text of each argument */
1245 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
1246 " FORMAT INT INT INT\"", 0);
1250 if( Tcl_GetInt(interp
, argv
[i
], &a
[i
-2]) ) return TCL_ERROR
;
1252 z
= sqlite3_mprintf(argv
[1], a
[0], a
[1], a
[2]);
1253 Tcl_AppendResult(interp
, z
, 0);
1259 ** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
1261 ** Call mprintf with three 64-bit integer arguments
1263 static int SQLITE_TCLAPI
sqlite3_mprintf_int64(
1265 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1266 int argc
, /* Number of arguments */
1267 char **argv
/* Text of each argument */
1273 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
1274 " FORMAT INT INT INT\"", 0);
1278 if( sqlite3Atoi64(argv
[i
], &a
[i
-2], sqlite3Strlen30(argv
[i
]), SQLITE_UTF8
) ){
1279 Tcl_AppendResult(interp
, "argument is not a valid 64-bit integer", 0);
1283 z
= sqlite3_mprintf(argv
[1], a
[0], a
[1], a
[2]);
1284 Tcl_AppendResult(interp
, z
, 0);
1290 ** Usage: sqlite3_mprintf_long FORMAT INTEGER INTEGER INTEGER
1292 ** Call mprintf with three long integer arguments. This might be the
1293 ** same as sqlite3_mprintf_int or sqlite3_mprintf_int64, depending on
1296 static int SQLITE_TCLAPI
sqlite3_mprintf_long(
1298 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1299 int argc
, /* Number of arguments */
1300 char **argv
/* Text of each argument */
1307 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
1308 " FORMAT INT INT INT\"", 0);
1312 if( Tcl_GetInt(interp
, argv
[i
], &b
[i
-2]) ) return TCL_ERROR
;
1313 a
[i
-2] = (long int)b
[i
-2];
1314 a
[i
-2] &= (((u64
)1)<<(sizeof(int)*8))-1;
1316 z
= sqlite3_mprintf(argv
[1], a
[0], a
[1], a
[2]);
1317 Tcl_AppendResult(interp
, z
, 0);
1323 ** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
1325 ** Call mprintf with two integer arguments and one string argument
1327 static int SQLITE_TCLAPI
sqlite3_mprintf_str(
1329 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1330 int argc
, /* Number of arguments */
1331 char **argv
/* Text of each argument */
1335 if( argc
<4 || argc
>5 ){
1336 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
1337 " FORMAT INT INT ?STRING?\"", 0);
1341 if( Tcl_GetInt(interp
, argv
[i
], &a
[i
-2]) ) return TCL_ERROR
;
1343 z
= sqlite3_mprintf(argv
[1], a
[0], a
[1], argc
>4 ? argv
[4] : NULL
);
1344 Tcl_AppendResult(interp
, z
, 0);
1350 ** Usage: sqlite3_snprintf_str INTEGER FORMAT INTEGER INTEGER STRING
1352 ** Call mprintf with two integer arguments and one string argument
1354 static int SQLITE_TCLAPI
sqlite3_snprintf_str(
1356 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1357 int argc
, /* Number of arguments */
1358 char **argv
/* Text of each argument */
1363 if( argc
<5 || argc
>6 ){
1364 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
1365 " INT FORMAT INT INT ?STRING?\"", 0);
1368 if( Tcl_GetInt(interp
, argv
[1], &n
) ) return TCL_ERROR
;
1370 Tcl_AppendResult(interp
, "N must be non-negative", 0);
1374 if( Tcl_GetInt(interp
, argv
[i
], &a
[i
-3]) ) return TCL_ERROR
;
1376 z
= sqlite3_malloc( n
+1 );
1377 sqlite3_snprintf(n
, z
, argv
[2], a
[0], a
[1], argc
>4 ? argv
[5] : NULL
);
1378 Tcl_AppendResult(interp
, z
, 0);
1384 ** Usage: sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE
1386 ** Call mprintf with two integer arguments and one double argument
1388 static int SQLITE_TCLAPI
sqlite3_mprintf_double(
1390 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1391 int argc
, /* Number of arguments */
1392 char **argv
/* Text of each argument */
1398 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
1399 " FORMAT INT INT DOUBLE\"", 0);
1403 if( Tcl_GetInt(interp
, argv
[i
], &a
[i
-2]) ) return TCL_ERROR
;
1405 if( Tcl_GetDouble(interp
, argv
[4], &r
) ) return TCL_ERROR
;
1406 z
= sqlite3_mprintf(argv
[1], a
[0], a
[1], r
);
1407 Tcl_AppendResult(interp
, z
, 0);
1413 ** Usage: sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE
1415 ** Call mprintf with a single double argument which is the product of the
1416 ** two arguments given above. This is used to generate overflow and underflow
1417 ** doubles to test that they are converted properly.
1419 static int SQLITE_TCLAPI
sqlite3_mprintf_scaled(
1421 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1422 int argc
, /* Number of arguments */
1423 char **argv
/* Text of each argument */
1429 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
1430 " FORMAT DOUBLE DOUBLE\"", 0);
1434 if( Tcl_GetDouble(interp
, argv
[i
], &r
[i
-2]) ) return TCL_ERROR
;
1436 z
= sqlite3_mprintf(argv
[1], r
[0]*r
[1]);
1437 Tcl_AppendResult(interp
, z
, 0);
1443 ** Usage: sqlite3_mprintf_stronly FORMAT STRING
1445 ** Call mprintf with a single double argument which is the product of the
1446 ** two arguments given above. This is used to generate overflow and underflow
1447 ** doubles to test that they are converted properly.
1449 static int SQLITE_TCLAPI
sqlite3_mprintf_stronly(
1451 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1452 int argc
, /* Number of arguments */
1453 char **argv
/* Text of each argument */
1457 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
1458 " FORMAT STRING\"", 0);
1461 z
= sqlite3_mprintf(argv
[1], argv
[2]);
1462 Tcl_AppendResult(interp
, z
, 0);
1468 ** Usage: sqlite3_mprintf_hexdouble FORMAT HEX
1470 ** Call mprintf with a single double argument which is derived from the
1471 ** hexadecimal encoding of an IEEE double.
1473 static int SQLITE_TCLAPI
sqlite3_mprintf_hexdouble(
1475 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1476 int argc
, /* Number of arguments */
1477 char **argv
/* Text of each argument */
1481 unsigned int x1
, x2
;
1484 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
1485 " FORMAT STRING\"", 0);
1488 if( sscanf(argv
[2], "%08x%08x", &x2
, &x1
)!=2 ){
1489 Tcl_AppendResult(interp
, "2nd argument should be 16-characters of hex", 0);
1494 memcpy(&r
, &d
, sizeof(r
));
1495 z
= sqlite3_mprintf(argv
[1], r
);
1496 Tcl_AppendResult(interp
, z
, 0);
1502 ** Usage: sqlite3_enable_shared_cache ?BOOLEAN?
1505 #if !defined(SQLITE_OMIT_SHARED_CACHE)
1506 static int SQLITE_TCLAPI
test_enable_shared(
1507 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
1508 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1509 int objc
, /* Number of arguments */
1510 Tcl_Obj
*CONST objv
[] /* Command arguments */
1516 if( objc
!=2 && objc
!=1 ){
1517 Tcl_WrongNumArgs(interp
, 1, objv
, "?BOOLEAN?");
1520 ret
= sqlite3GlobalConfig
.sharedCacheEnabled
;
1523 if( Tcl_GetBooleanFromObj(interp
, objv
[1], &enable
) ){
1526 rc
= sqlite3_enable_shared_cache(enable
);
1527 if( rc
!=SQLITE_OK
){
1528 Tcl_SetResult(interp
, (char *)sqlite3ErrStr(rc
), TCL_STATIC
);
1532 Tcl_SetObjResult(interp
, Tcl_NewBooleanObj(ret
));
1540 ** Usage: sqlite3_extended_result_codes DB BOOLEAN
1543 static int SQLITE_TCLAPI
test_extended_result_codes(
1544 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
1545 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1546 int objc
, /* Number of arguments */
1547 Tcl_Obj
*CONST objv
[] /* Command arguments */
1553 Tcl_WrongNumArgs(interp
, 1, objv
, "DB BOOLEAN");
1556 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
1557 if( Tcl_GetBooleanFromObj(interp
, objv
[2], &enable
) ) return TCL_ERROR
;
1558 sqlite3_extended_result_codes(db
, enable
);
1563 ** Usage: sqlite3_libversion_number
1566 static int SQLITE_TCLAPI
test_libversion_number(
1567 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
1568 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1569 int objc
, /* Number of arguments */
1570 Tcl_Obj
*CONST objv
[] /* Command arguments */
1572 Tcl_SetObjResult(interp
, Tcl_NewIntObj(sqlite3_libversion_number()));
1577 ** Usage: sqlite3_table_column_metadata DB dbname tblname colname
1580 static int SQLITE_TCLAPI
test_table_column_metadata(
1581 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
1582 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1583 int objc
, /* Number of arguments */
1584 Tcl_Obj
*CONST objv
[] /* Command arguments */
1593 const char *zDatatype
;
1594 const char *zCollseq
;
1599 if( objc
!=5 && objc
!=4 ){
1600 Tcl_WrongNumArgs(interp
, 1, objv
, "DB dbname tblname colname");
1603 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
1604 zDb
= Tcl_GetString(objv
[2]);
1605 zTbl
= Tcl_GetString(objv
[3]);
1606 zCol
= objc
==5 ? Tcl_GetString(objv
[4]) : 0;
1608 if( strlen(zDb
)==0 ) zDb
= 0;
1610 rc
= sqlite3_table_column_metadata(db
, zDb
, zTbl
, zCol
,
1611 &zDatatype
, &zCollseq
, ¬null
, &primarykey
, &autoincrement
);
1613 if( rc
!=SQLITE_OK
){
1614 Tcl_AppendResult(interp
, sqlite3_errmsg(db
), 0);
1618 pRet
= Tcl_NewObj();
1619 Tcl_ListObjAppendElement(0, pRet
, Tcl_NewStringObj(zDatatype
, -1));
1620 Tcl_ListObjAppendElement(0, pRet
, Tcl_NewStringObj(zCollseq
, -1));
1621 Tcl_ListObjAppendElement(0, pRet
, Tcl_NewIntObj(notnull
));
1622 Tcl_ListObjAppendElement(0, pRet
, Tcl_NewIntObj(primarykey
));
1623 Tcl_ListObjAppendElement(0, pRet
, Tcl_NewIntObj(autoincrement
));
1624 Tcl_SetObjResult(interp
, pRet
);
1629 #ifndef SQLITE_OMIT_INCRBLOB
1631 static int SQLITE_TCLAPI
blobHandleFromObj(
1634 sqlite3_blob
**ppBlob
1639 z
= Tcl_GetStringFromObj(pObj
, &n
);
1644 Tcl_Channel channel
;
1645 ClientData instanceData
;
1647 channel
= Tcl_GetChannel(interp
, z
, ¬Used
);
1648 if( !channel
) return TCL_ERROR
;
1651 Tcl_Seek(channel
, 0, SEEK_SET
);
1653 instanceData
= Tcl_GetChannelInstanceData(channel
);
1654 *ppBlob
= *((sqlite3_blob
**)instanceData
);
1660 static int SQLITE_TCLAPI
test_blob_reopen(
1661 ClientData clientData
, /* Not used */
1662 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1663 int objc
, /* Number of arguments */
1664 Tcl_Obj
*CONST objv
[] /* Command arguments */
1667 sqlite3_blob
*pBlob
;
1671 Tcl_WrongNumArgs(interp
, 1, objv
, "CHANNEL ROWID");
1675 if( blobHandleFromObj(interp
, objv
[1], &pBlob
) ) return TCL_ERROR
;
1676 if( Tcl_GetWideIntFromObj(interp
, objv
[2], &iRowid
) ) return TCL_ERROR
;
1678 rc
= sqlite3_blob_reopen(pBlob
, iRowid
);
1679 if( rc
!=SQLITE_OK
){
1680 Tcl_SetResult(interp
, (char *)sqlite3ErrName(rc
), TCL_VOLATILE
);
1683 return (rc
==SQLITE_OK
? TCL_OK
: TCL_ERROR
);
1689 ** Usage: sqlite3_create_collation_v2 DB-HANDLE NAME CMP-PROC DEL-PROC
1691 ** This Tcl proc is used for testing the experimental
1692 ** sqlite3_create_collation_v2() interface.
1694 struct TestCollationX
{
1699 typedef struct TestCollationX TestCollationX
;
1700 static void testCreateCollationDel(void *pCtx
){
1701 TestCollationX
*p
= (TestCollationX
*)pCtx
;
1703 int rc
= Tcl_EvalObjEx(p
->interp
, p
->pDel
, TCL_EVAL_DIRECT
|TCL_EVAL_GLOBAL
);
1705 Tcl_BackgroundError(p
->interp
);
1708 Tcl_DecrRefCount(p
->pCmp
);
1709 Tcl_DecrRefCount(p
->pDel
);
1710 sqlite3_free((void *)p
);
1712 static int testCreateCollationCmp(
1719 TestCollationX
*p
= (TestCollationX
*)pCtx
;
1720 Tcl_Obj
*pScript
= Tcl_DuplicateObj(p
->pCmp
);
1723 Tcl_IncrRefCount(pScript
);
1724 Tcl_ListObjAppendElement(0, pScript
, Tcl_NewStringObj((char *)zLeft
, nLeft
));
1725 Tcl_ListObjAppendElement(0, pScript
, Tcl_NewStringObj((char *)zRight
,nRight
));
1727 if( TCL_OK
!=Tcl_EvalObjEx(p
->interp
, pScript
, TCL_EVAL_DIRECT
|TCL_EVAL_GLOBAL
)
1728 || TCL_OK
!=Tcl_GetIntFromObj(p
->interp
, Tcl_GetObjResult(p
->interp
), &iRes
)
1730 Tcl_BackgroundError(p
->interp
);
1732 Tcl_DecrRefCount(pScript
);
1736 static int SQLITE_TCLAPI
test_create_collation_v2(
1737 ClientData clientData
, /* Not used */
1738 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1739 int objc
, /* Number of arguments */
1740 Tcl_Obj
*CONST objv
[] /* Command arguments */
1747 Tcl_WrongNumArgs(interp
, 1, objv
, "DB-HANDLE NAME CMP-PROC DEL-PROC");
1750 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
1752 p
= (TestCollationX
*)sqlite3_malloc(sizeof(TestCollationX
));
1756 Tcl_IncrRefCount(p
->pCmp
);
1757 Tcl_IncrRefCount(p
->pDel
);
1759 rc
= sqlite3_create_collation_v2(db
, Tcl_GetString(objv
[2]), 16,
1760 (void *)p
, testCreateCollationCmp
, testCreateCollationDel
1762 if( rc
!=SQLITE_MISUSE
){
1763 Tcl_AppendResult(interp
, "sqlite3_create_collate_v2() failed to detect "
1764 "an invalid encoding", (char*)0);
1767 rc
= sqlite3_create_collation_v2(db
, Tcl_GetString(objv
[2]), SQLITE_UTF8
,
1768 (void *)p
, testCreateCollationCmp
, testCreateCollationDel
1774 ** USAGE: sqlite3_create_function_v2 DB NAME NARG ENC ?SWITCHES?
1776 ** Available switches are:
1783 typedef struct CreateFunctionV2 CreateFunctionV2
;
1784 struct CreateFunctionV2
{
1786 Tcl_Obj
*pFunc
; /* Script for function invocation */
1787 Tcl_Obj
*pStep
; /* Script for agg. step invocation */
1788 Tcl_Obj
*pFinal
; /* Script for agg. finalization invocation */
1789 Tcl_Obj
*pDestroy
; /* Destructor script */
1791 static void cf2Func(sqlite3_context
*ctx
, int nArg
, sqlite3_value
**aArg
){
1793 static void cf2Step(sqlite3_context
*ctx
, int nArg
, sqlite3_value
**aArg
){
1795 static void cf2Final(sqlite3_context
*ctx
){
1797 static void cf2Destroy(void *pUser
){
1798 CreateFunctionV2
*p
= (CreateFunctionV2
*)pUser
;
1800 if( p
->interp
&& p
->pDestroy
){
1801 int rc
= Tcl_EvalObjEx(p
->interp
, p
->pDestroy
, 0);
1802 if( rc
!=TCL_OK
) Tcl_BackgroundError(p
->interp
);
1805 if( p
->pFunc
) Tcl_DecrRefCount(p
->pFunc
);
1806 if( p
->pStep
) Tcl_DecrRefCount(p
->pStep
);
1807 if( p
->pFinal
) Tcl_DecrRefCount(p
->pFinal
);
1808 if( p
->pDestroy
) Tcl_DecrRefCount(p
->pDestroy
);
1811 static int SQLITE_TCLAPI
test_create_function_v2(
1812 ClientData clientData
, /* Not used */
1813 Tcl_Interp
*interp
, /* The invoking TCL interpreter */
1814 int objc
, /* Number of arguments */
1815 Tcl_Obj
*CONST objv
[] /* Command arguments */
1821 CreateFunctionV2
*p
;
1829 {"utf8", SQLITE_UTF8
},
1830 {"utf16", SQLITE_UTF16
},
1831 {"utf16le", SQLITE_UTF16LE
},
1832 {"utf16be", SQLITE_UTF16BE
},
1833 {"any", SQLITE_ANY
},
1837 if( objc
<5 || (objc
%2)==0 ){
1838 Tcl_WrongNumArgs(interp
, 1, objv
, "DB NAME NARG ENC SWITCHES...");
1842 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
1843 zFunc
= Tcl_GetString(objv
[2]);
1844 if( Tcl_GetIntFromObj(interp
, objv
[3], &nArg
) ) return TCL_ERROR
;
1845 if( Tcl_GetIndexFromObjStruct(interp
, objv
[4], aEnc
, sizeof(aEnc
[0]),
1846 "encoding", 0, &enc
)
1850 enc
= aEnc
[enc
].enc
;
1852 p
= sqlite3_malloc(sizeof(CreateFunctionV2
));
1854 memset(p
, 0, sizeof(CreateFunctionV2
));
1857 for(i
=5; i
<objc
; i
+=2){
1859 const char *azSwitch
[] = {"-func", "-step", "-final", "-destroy", 0};
1860 if( Tcl_GetIndexFromObj(interp
, objv
[i
], azSwitch
, "switch", 0, &iSwitch
) ){
1866 case 0: p
->pFunc
= objv
[i
+1]; break;
1867 case 1: p
->pStep
= objv
[i
+1]; break;
1868 case 2: p
->pFinal
= objv
[i
+1]; break;
1869 case 3: p
->pDestroy
= objv
[i
+1]; break;
1872 if( p
->pFunc
) p
->pFunc
= Tcl_DuplicateObj(p
->pFunc
);
1873 if( p
->pStep
) p
->pStep
= Tcl_DuplicateObj(p
->pStep
);
1874 if( p
->pFinal
) p
->pFinal
= Tcl_DuplicateObj(p
->pFinal
);
1875 if( p
->pDestroy
) p
->pDestroy
= Tcl_DuplicateObj(p
->pDestroy
);
1877 if( p
->pFunc
) Tcl_IncrRefCount(p
->pFunc
);
1878 if( p
->pStep
) Tcl_IncrRefCount(p
->pStep
);
1879 if( p
->pFinal
) Tcl_IncrRefCount(p
->pFinal
);
1880 if( p
->pDestroy
) Tcl_IncrRefCount(p
->pDestroy
);
1882 rc
= sqlite3_create_function_v2(db
, zFunc
, nArg
, enc
, (void *)p
,
1883 (p
->pFunc
? cf2Func
: 0),
1884 (p
->pStep
? cf2Step
: 0),
1885 (p
->pFinal
? cf2Final
: 0),
1888 if( rc
!=SQLITE_OK
){
1889 Tcl_ResetResult(interp
);
1890 Tcl_AppendResult(interp
, sqlite3ErrName(rc
), 0);
1897 ** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC?
1899 static int SQLITE_TCLAPI
test_load_extension(
1900 ClientData clientData
, /* Not used */
1901 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1902 int objc
, /* Number of arguments */
1903 Tcl_Obj
*CONST objv
[] /* Command arguments */
1905 Tcl_CmdInfo cmdInfo
;
1913 if( objc
!=4 && objc
!=3 ){
1914 Tcl_WrongNumArgs(interp
, 1, objv
, "DB-HANDLE FILE ?PROC?");
1917 zDb
= Tcl_GetString(objv
[1]);
1918 zFile
= Tcl_GetString(objv
[2]);
1920 zProc
= Tcl_GetString(objv
[3]);
1923 /* Extract the C database handle from the Tcl command name */
1924 if( !Tcl_GetCommandInfo(interp
, zDb
, &cmdInfo
) ){
1925 Tcl_AppendResult(interp
, "command not found: ", zDb
, (char*)0);
1928 db
= ((struct SqliteDb
*)cmdInfo
.objClientData
)->db
;
1931 /* Call the underlying C function. If an error occurs, set rc to
1932 ** TCL_ERROR and load any error string into the interpreter. If no
1933 ** error occurs, set rc to TCL_OK.
1935 #ifdef SQLITE_OMIT_LOAD_EXTENSION
1937 zErr
= sqlite3_mprintf("this build omits sqlite3_load_extension()");
1941 rc
= sqlite3_load_extension(db
, zFile
, zProc
, &zErr
);
1943 if( rc
!=SQLITE_OK
){
1944 Tcl_SetResult(interp
, zErr
? zErr
: "", TCL_VOLATILE
);
1955 ** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF
1957 static int SQLITE_TCLAPI
test_enable_load(
1958 ClientData clientData
, /* Not used */
1959 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
1960 int objc
, /* Number of arguments */
1961 Tcl_Obj
*CONST objv
[] /* Command arguments */
1963 Tcl_CmdInfo cmdInfo
;
1969 Tcl_WrongNumArgs(interp
, 1, objv
, "DB-HANDLE ONOFF");
1972 zDb
= Tcl_GetString(objv
[1]);
1974 /* Extract the C database handle from the Tcl command name */
1975 if( !Tcl_GetCommandInfo(interp
, zDb
, &cmdInfo
) ){
1976 Tcl_AppendResult(interp
, "command not found: ", zDb
, (char*)0);
1979 db
= ((struct SqliteDb
*)cmdInfo
.objClientData
)->db
;
1982 /* Get the onoff parameter */
1983 if( Tcl_GetBooleanFromObj(interp
, objv
[2], &onoff
) ){
1987 #ifdef SQLITE_OMIT_LOAD_EXTENSION
1988 Tcl_AppendResult(interp
, "this build omits sqlite3_load_extension()");
1991 sqlite3_enable_load_extension(db
, onoff
);
1997 ** Usage: sqlite_abort
1999 ** Shutdown the process immediately. This is not a clean shutdown.
2000 ** This command is used to test the recoverability of a database in
2001 ** the event of a program crash.
2003 static int SQLITE_TCLAPI
sqlite_abort(
2005 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
2006 int argc
, /* Number of arguments */
2007 char **argv
/* Text of each argument */
2009 #if defined(_MSC_VER)
2010 /* We do this, otherwise the test will halt with a popup message
2011 * that we have to click away before the test will continue.
2013 _set_abort_behavior( 0, _CALL_REPORTFAULT
);
2016 assert( interp
==0 ); /* This will always fail */
2021 ** The following routine is a user-defined SQL function whose purpose
2022 ** is to test the sqlite_set_result() API.
2024 static void testFunc(sqlite3_context
*context
, int argc
, sqlite3_value
**argv
){
2026 const char *zArg0
= (char*)sqlite3_value_text(argv
[0]);
2028 if( 0==sqlite3StrICmp(zArg0
, "int") ){
2029 sqlite3_result_int(context
, sqlite3_value_int(argv
[1]));
2030 }else if( sqlite3StrICmp(zArg0
,"int64")==0 ){
2031 sqlite3_result_int64(context
, sqlite3_value_int64(argv
[1]));
2032 }else if( sqlite3StrICmp(zArg0
,"string")==0 ){
2033 sqlite3_result_text(context
, (char*)sqlite3_value_text(argv
[1]), -1,
2035 }else if( sqlite3StrICmp(zArg0
,"double")==0 ){
2036 sqlite3_result_double(context
, sqlite3_value_double(argv
[1]));
2037 }else if( sqlite3StrICmp(zArg0
,"null")==0 ){
2038 sqlite3_result_null(context
);
2039 }else if( sqlite3StrICmp(zArg0
,"value")==0 ){
2040 sqlite3_result_value(context
, argv
[sqlite3_value_int(argv
[1])]);
2053 sqlite3_result_error(context
,"first argument should be one of: "
2054 "int int64 string double null value", -1);
2058 ** Usage: sqlite_register_test_function DB NAME
2060 ** Register the test SQL function on the database DB under the name NAME.
2062 static int SQLITE_TCLAPI
test_register_func(
2064 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
2065 int argc
, /* Number of arguments */
2066 char **argv
/* Text of each argument */
2071 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
2072 " DB FUNCTION-NAME", 0);
2075 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
2076 rc
= sqlite3_create_function(db
, argv
[2], -1, SQLITE_UTF8
, 0,
2079 Tcl_AppendResult(interp
, sqlite3ErrStr(rc
), 0);
2082 if( sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
2087 ** Usage: sqlite3_finalize STMT
2089 ** Finalize a statement handle.
2091 static int SQLITE_TCLAPI
test_finalize(
2095 Tcl_Obj
*CONST objv
[]
2097 sqlite3_stmt
*pStmt
;
2102 Tcl_AppendResult(interp
, "wrong # args: should be \"",
2103 Tcl_GetStringFromObj(objv
[0], 0), " <STMT>", 0);
2107 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
2110 db
= StmtToDb(pStmt
);
2112 rc
= sqlite3_finalize(pStmt
);
2113 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), TCL_STATIC
);
2114 if( db
&& sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
2119 ** Usage: sqlite3_stmt_status STMT CODE RESETFLAG
2121 ** Get the value of a status counter from a statement.
2123 static int SQLITE_TCLAPI
test_stmt_status(
2127 Tcl_Obj
*CONST objv
[]
2130 int i
, op
= 0, resetFlag
;
2131 const char *zOpName
;
2132 sqlite3_stmt
*pStmt
;
2134 static const struct {
2138 { "SQLITE_STMTSTATUS_FULLSCAN_STEP", SQLITE_STMTSTATUS_FULLSCAN_STEP
},
2139 { "SQLITE_STMTSTATUS_SORT", SQLITE_STMTSTATUS_SORT
},
2140 { "SQLITE_STMTSTATUS_AUTOINDEX", SQLITE_STMTSTATUS_AUTOINDEX
},
2141 { "SQLITE_STMTSTATUS_VM_STEP", SQLITE_STMTSTATUS_VM_STEP
},
2142 { "SQLITE_STMTSTATUS_REPREPARE", SQLITE_STMTSTATUS_REPREPARE
},
2143 { "SQLITE_STMTSTATUS_RUN", SQLITE_STMTSTATUS_RUN
},
2144 { "SQLITE_STMTSTATUS_MEMUSED", SQLITE_STMTSTATUS_MEMUSED
},
2147 Tcl_WrongNumArgs(interp
, 1, objv
, "STMT PARAMETER RESETFLAG");
2150 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
2151 zOpName
= Tcl_GetString(objv
[2]);
2152 for(i
=0; i
<ArraySize(aOp
); i
++){
2153 if( strcmp(aOp
[i
].zName
, zOpName
)==0 ){
2158 if( i
>=ArraySize(aOp
) ){
2159 if( Tcl_GetIntFromObj(interp
, objv
[2], &op
) ) return TCL_ERROR
;
2161 if( Tcl_GetBooleanFromObj(interp
, objv
[3], &resetFlag
) ) return TCL_ERROR
;
2162 iValue
= sqlite3_stmt_status(pStmt
, op
, resetFlag
);
2163 Tcl_SetObjResult(interp
, Tcl_NewIntObj(iValue
));
2167 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
2169 ** Usage: sqlite3_stmt_scanstatus STMT IDX
2171 static int SQLITE_TCLAPI
test_stmt_scanstatus(
2175 Tcl_Obj
*CONST objv
[]
2177 sqlite3_stmt
*pStmt
; /* First argument */
2178 int idx
; /* Second argument */
2181 const char *zExplain
;
2182 sqlite3_int64 nLoop
;
2183 sqlite3_int64 nVisit
;
2188 Tcl_WrongNumArgs(interp
, 1, objv
, "STMT IDX");
2191 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
2192 if( Tcl_GetIntFromObj(interp
, objv
[2], &idx
) ) return TCL_ERROR
;
2194 res
= sqlite3_stmt_scanstatus(pStmt
, idx
, SQLITE_SCANSTAT_NLOOP
, (void*)&nLoop
);
2196 Tcl_Obj
*pRet
= Tcl_NewObj();
2197 Tcl_ListObjAppendElement(0, pRet
, Tcl_NewStringObj("nLoop", -1));
2198 Tcl_ListObjAppendElement(0, pRet
, Tcl_NewWideIntObj(nLoop
));
2199 sqlite3_stmt_scanstatus(pStmt
, idx
, SQLITE_SCANSTAT_NVISIT
, (void*)&nVisit
);
2200 Tcl_ListObjAppendElement(0, pRet
, Tcl_NewStringObj("nVisit", -1));
2201 Tcl_ListObjAppendElement(0, pRet
, Tcl_NewWideIntObj(nVisit
));
2202 sqlite3_stmt_scanstatus(pStmt
, idx
, SQLITE_SCANSTAT_EST
, (void*)&rEst
);
2203 Tcl_ListObjAppendElement(0, pRet
, Tcl_NewStringObj("nEst", -1));
2204 Tcl_ListObjAppendElement(0, pRet
, Tcl_NewDoubleObj(rEst
));
2205 sqlite3_stmt_scanstatus(pStmt
, idx
, SQLITE_SCANSTAT_NAME
, (void*)&zName
);
2206 Tcl_ListObjAppendElement(0, pRet
, Tcl_NewStringObj("zName", -1));
2207 Tcl_ListObjAppendElement(0, pRet
, Tcl_NewStringObj(zName
, -1));
2208 sqlite3_stmt_scanstatus(pStmt
, idx
, SQLITE_SCANSTAT_EXPLAIN
, (void*)&zExplain
);
2209 Tcl_ListObjAppendElement(0, pRet
, Tcl_NewStringObj("zExplain", -1));
2210 Tcl_ListObjAppendElement(0, pRet
, Tcl_NewStringObj(zExplain
, -1));
2211 Tcl_SetObjResult(interp
, pRet
);
2213 Tcl_ResetResult(interp
);
2219 ** Usage: sqlite3_stmt_scanstatus_reset STMT
2221 static int SQLITE_TCLAPI
test_stmt_scanstatus_reset(
2225 Tcl_Obj
*CONST objv
[]
2227 sqlite3_stmt
*pStmt
; /* First argument */
2229 Tcl_WrongNumArgs(interp
, 1, objv
, "STMT");
2232 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
2233 sqlite3_stmt_scanstatus_reset(pStmt
);
2238 #ifdef SQLITE_ENABLE_SQLLOG
2240 ** Usage: sqlite3_config_sqllog
2242 ** Zero the SQLITE_CONFIG_SQLLOG configuration
2244 static int SQLITE_TCLAPI
test_config_sqllog(
2248 Tcl_Obj
*CONST objv
[]
2251 Tcl_WrongNumArgs(interp
, 1, objv
, "");
2254 sqlite3_config(SQLITE_CONFIG_SQLLOG
, 0, 0);
2260 ** Usage: sqlite3_config_sorterref
2262 ** Set the SQLITE_CONFIG_SORTERREF_SIZE configuration option
2264 static int SQLITE_TCLAPI
test_config_sorterref(
2268 Tcl_Obj
*CONST objv
[]
2272 Tcl_WrongNumArgs(interp
, 1, objv
, "NBYTE");
2275 if( Tcl_GetIntFromObj(interp
, objv
[1], &iVal
) ) return TCL_ERROR
;
2276 sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE
, iVal
);
2281 ** Usage: vfs_current_time_int64
2283 ** Return the value returned by the default VFS's xCurrentTimeInt64 method.
2285 static int SQLITE_TCLAPI
vfsCurrentTimeInt64(
2289 Tcl_Obj
*CONST objv
[]
2292 sqlite3_vfs
*pVfs
= sqlite3_vfs_find(0);
2294 Tcl_WrongNumArgs(interp
, 1, objv
, "");
2297 pVfs
->xCurrentTimeInt64(pVfs
, &t
);
2298 Tcl_SetObjResult(interp
, Tcl_NewWideIntObj(t
));
2302 #ifdef SQLITE_ENABLE_SNAPSHOT
2304 ** Usage: sqlite3_snapshot_get DB DBNAME
2306 static int SQLITE_TCLAPI
test_snapshot_get(
2310 Tcl_Obj
*CONST objv
[]
2315 sqlite3_snapshot
*pSnapshot
= 0;
2318 Tcl_WrongNumArgs(interp
, 1, objv
, "DB DBNAME");
2321 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
2322 zName
= Tcl_GetString(objv
[2]);
2324 rc
= sqlite3_snapshot_get(db
, zName
, &pSnapshot
);
2325 if( rc
!=SQLITE_OK
){
2326 Tcl_SetObjResult(interp
, Tcl_NewStringObj(sqlite3ErrName(rc
), -1));
2330 if( sqlite3TestMakePointerStr(interp
, zBuf
, pSnapshot
) ) return TCL_ERROR
;
2331 Tcl_SetObjResult(interp
, Tcl_NewStringObj(zBuf
, -1));
2335 #endif /* SQLITE_ENABLE_SNAPSHOT */
2337 #ifdef SQLITE_ENABLE_SNAPSHOT
2339 ** Usage: sqlite3_snapshot_recover DB DBNAME
2341 static int SQLITE_TCLAPI
test_snapshot_recover(
2345 Tcl_Obj
*CONST objv
[]
2352 Tcl_WrongNumArgs(interp
, 1, objv
, "DB DBNAME");
2355 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
2356 zName
= Tcl_GetString(objv
[2]);
2358 rc
= sqlite3_snapshot_recover(db
, zName
);
2359 if( rc
!=SQLITE_OK
){
2360 Tcl_SetObjResult(interp
, Tcl_NewStringObj(sqlite3ErrName(rc
), -1));
2363 Tcl_ResetResult(interp
);
2367 #endif /* SQLITE_ENABLE_SNAPSHOT */
2369 #ifdef SQLITE_ENABLE_SNAPSHOT
2371 ** Usage: sqlite3_snapshot_open DB DBNAME SNAPSHOT
2373 static int SQLITE_TCLAPI
test_snapshot_open(
2377 Tcl_Obj
*CONST objv
[]
2382 sqlite3_snapshot
*pSnapshot
;
2385 Tcl_WrongNumArgs(interp
, 1, objv
, "DB DBNAME SNAPSHOT");
2388 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
2389 zName
= Tcl_GetString(objv
[2]);
2390 pSnapshot
= (sqlite3_snapshot
*)sqlite3TestTextToPtr(Tcl_GetString(objv
[3]));
2392 rc
= sqlite3_snapshot_open(db
, zName
, pSnapshot
);
2393 if( rc
!=SQLITE_OK
){
2394 Tcl_SetObjResult(interp
, Tcl_NewStringObj(sqlite3ErrName(rc
), -1));
2399 #endif /* SQLITE_ENABLE_SNAPSHOT */
2401 #ifdef SQLITE_ENABLE_SNAPSHOT
2403 ** Usage: sqlite3_snapshot_free SNAPSHOT
2405 static int SQLITE_TCLAPI
test_snapshot_free(
2409 Tcl_Obj
*CONST objv
[]
2411 sqlite3_snapshot
*pSnapshot
;
2413 Tcl_WrongNumArgs(interp
, 1, objv
, "SNAPSHOT");
2416 pSnapshot
= (sqlite3_snapshot
*)sqlite3TestTextToPtr(Tcl_GetString(objv
[1]));
2417 sqlite3_snapshot_free(pSnapshot
);
2420 #endif /* SQLITE_ENABLE_SNAPSHOT */
2422 #ifdef SQLITE_ENABLE_SNAPSHOT
2424 ** Usage: sqlite3_snapshot_cmp SNAPSHOT1 SNAPSHOT2
2426 static int SQLITE_TCLAPI
test_snapshot_cmp(
2430 Tcl_Obj
*CONST objv
[]
2433 sqlite3_snapshot
*p1
;
2434 sqlite3_snapshot
*p2
;
2436 Tcl_WrongNumArgs(interp
, 1, objv
, "SNAPSHOT1 SNAPSHOT2");
2439 p1
= (sqlite3_snapshot
*)sqlite3TestTextToPtr(Tcl_GetString(objv
[1]));
2440 p2
= (sqlite3_snapshot
*)sqlite3TestTextToPtr(Tcl_GetString(objv
[2]));
2441 res
= sqlite3_snapshot_cmp(p1
, p2
);
2442 Tcl_SetObjResult(interp
, Tcl_NewIntObj(res
));
2445 #endif /* SQLITE_ENABLE_SNAPSHOT */
2447 #ifdef SQLITE_ENABLE_SNAPSHOT
2449 ** Usage: sqlite3_snapshot_get_blob DB DBNAME
2451 static int SQLITE_TCLAPI
test_snapshot_get_blob(
2455 Tcl_Obj
*CONST objv
[]
2460 sqlite3_snapshot
*pSnapshot
= 0;
2463 Tcl_WrongNumArgs(interp
, 1, objv
, "DB DBNAME");
2466 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
2467 zName
= Tcl_GetString(objv
[2]);
2469 rc
= sqlite3_snapshot_get(db
, zName
, &pSnapshot
);
2470 if( rc
!=SQLITE_OK
){
2471 Tcl_SetObjResult(interp
, Tcl_NewStringObj(sqlite3ErrName(rc
), -1));
2474 Tcl_SetObjResult(interp
,
2475 Tcl_NewByteArrayObj((unsigned char*)pSnapshot
, sizeof(sqlite3_snapshot
))
2477 sqlite3_snapshot_free(pSnapshot
);
2481 #endif /* SQLITE_ENABLE_SNAPSHOT */
2483 #ifdef SQLITE_ENABLE_SNAPSHOT
2485 ** Usage: sqlite3_snapshot_open_blob DB DBNAME SNAPSHOT
2487 static int SQLITE_TCLAPI
test_snapshot_open_blob(
2491 Tcl_Obj
*CONST objv
[]
2496 unsigned char *pBlob
;
2500 Tcl_WrongNumArgs(interp
, 1, objv
, "DB DBNAME SNAPSHOT");
2503 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
2504 zName
= Tcl_GetString(objv
[2]);
2505 pBlob
= Tcl_GetByteArrayFromObj(objv
[3], &nBlob
);
2506 if( nBlob
!=sizeof(sqlite3_snapshot
) ){
2507 Tcl_AppendResult(interp
, "bad SNAPSHOT", 0);
2510 rc
= sqlite3_snapshot_open(db
, zName
, (sqlite3_snapshot
*)pBlob
);
2511 if( rc
!=SQLITE_OK
){
2512 Tcl_SetObjResult(interp
, Tcl_NewStringObj(sqlite3ErrName(rc
), -1));
2517 #endif /* SQLITE_ENABLE_SNAPSHOT */
2519 #ifdef SQLITE_ENABLE_SNAPSHOT
2521 ** Usage: sqlite3_snapshot_cmp_blob SNAPSHOT1 SNAPSHOT2
2523 static int SQLITE_TCLAPI
test_snapshot_cmp_blob(
2527 Tcl_Obj
*CONST objv
[]
2536 Tcl_WrongNumArgs(interp
, 1, objv
, "SNAPSHOT1 SNAPSHOT2");
2540 p1
= Tcl_GetByteArrayFromObj(objv
[1], &n1
);
2541 p2
= Tcl_GetByteArrayFromObj(objv
[2], &n2
);
2543 if( n1
!=sizeof(sqlite3_snapshot
) || n1
!=n2
){
2544 Tcl_AppendResult(interp
, "bad SNAPSHOT", 0);
2548 res
= sqlite3_snapshot_cmp((sqlite3_snapshot
*)p1
, (sqlite3_snapshot
*)p2
);
2549 Tcl_SetObjResult(interp
, Tcl_NewIntObj(res
));
2552 #endif /* SQLITE_ENABLE_SNAPSHOT */
2555 ** Usage: sqlite3_delete_database FILENAME
2557 int sqlite3_delete_database(const char*); /* in test_delete.c */
2558 static int SQLITE_TCLAPI
test_delete_database(
2562 Tcl_Obj
*CONST objv
[]
2567 Tcl_WrongNumArgs(interp
, 1, objv
, "FILE");
2570 zFile
= (const char*)Tcl_GetString(objv
[1]);
2571 rc
= sqlite3_delete_database(zFile
);
2573 Tcl_SetObjResult(interp
, Tcl_NewStringObj(sqlite3ErrName(rc
), -1));
2578 ** Usage: atomic_batch_write PATH
2580 static int SQLITE_TCLAPI
test_atomic_batch_write(
2584 Tcl_Obj
*CONST objv
[]
2586 char *zFile
= 0; /* Path to file to test */
2587 sqlite3
*db
= 0; /* Database handle */
2588 sqlite3_file
*pFd
= 0; /* SQLite fd open on zFile */
2589 int bRes
= 0; /* Integer result of this command */
2590 int dc
= 0; /* Device-characteristics mask */
2591 int rc
; /* sqlite3_open() return code */
2594 Tcl_WrongNumArgs(interp
, 1, objv
, "PATH");
2597 zFile
= Tcl_GetString(objv
[1]);
2599 rc
= sqlite3_open(zFile
, &db
);
2600 if( rc
!=SQLITE_OK
){
2601 Tcl_AppendResult(interp
, sqlite3_errmsg(db
), 0);
2606 rc
= sqlite3_file_control(db
, "main", SQLITE_FCNTL_FILE_POINTER
, (void*)&pFd
);
2607 dc
= pFd
->pMethods
->xDeviceCharacteristics(pFd
);
2608 if( dc
& SQLITE_IOCAP_BATCH_ATOMIC
){
2612 Tcl_SetObjResult(interp
, Tcl_NewIntObj(bRes
));
2618 ** Usage: sqlite3_next_stmt DB STMT
2620 ** Return the next statment in sequence after STMT.
2622 static int SQLITE_TCLAPI
test_next_stmt(
2626 Tcl_Obj
*CONST objv
[]
2628 sqlite3_stmt
*pStmt
;
2633 Tcl_AppendResult(interp
, "wrong # args: should be \"",
2634 Tcl_GetStringFromObj(objv
[0], 0), " DB STMT", 0);
2638 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
2639 if( getStmtPointer(interp
, Tcl_GetString(objv
[2]), &pStmt
) ) return TCL_ERROR
;
2640 pStmt
= sqlite3_next_stmt(db
, pStmt
);
2642 if( sqlite3TestMakePointerStr(interp
, zBuf
, pStmt
) ) return TCL_ERROR
;
2643 Tcl_AppendResult(interp
, zBuf
, 0);
2649 ** Usage: sqlite3_stmt_readonly STMT
2651 ** Return true if STMT is a NULL pointer or a pointer to a statement
2652 ** that is guaranteed to leave the database unmodified.
2654 static int SQLITE_TCLAPI
test_stmt_readonly(
2658 Tcl_Obj
*CONST objv
[]
2660 sqlite3_stmt
*pStmt
;
2664 Tcl_AppendResult(interp
, "wrong # args: should be \"",
2665 Tcl_GetStringFromObj(objv
[0], 0), " STMT", 0);
2669 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
2670 rc
= sqlite3_stmt_readonly(pStmt
);
2671 Tcl_SetObjResult(interp
, Tcl_NewBooleanObj(rc
));
2676 ** Usage: sqlite3_stmt_busy STMT
2678 ** Return true if STMT is a non-NULL pointer to a statement
2679 ** that has been stepped but not to completion.
2681 static int SQLITE_TCLAPI
test_stmt_busy(
2685 Tcl_Obj
*CONST objv
[]
2687 sqlite3_stmt
*pStmt
;
2691 Tcl_AppendResult(interp
, "wrong # args: should be \"",
2692 Tcl_GetStringFromObj(objv
[0], 0), " STMT", 0);
2696 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
2697 rc
= sqlite3_stmt_busy(pStmt
);
2698 Tcl_SetObjResult(interp
, Tcl_NewBooleanObj(rc
));
2703 ** Usage: uses_stmt_journal STMT
2705 ** Return true if STMT uses a statement journal.
2707 static int SQLITE_TCLAPI
uses_stmt_journal(
2711 Tcl_Obj
*CONST objv
[]
2713 sqlite3_stmt
*pStmt
;
2716 Tcl_AppendResult(interp
, "wrong # args: should be \"",
2717 Tcl_GetStringFromObj(objv
[0], 0), " STMT", 0);
2721 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
2722 sqlite3_stmt_readonly(pStmt
);
2723 Tcl_SetObjResult(interp
, Tcl_NewBooleanObj(((Vdbe
*)pStmt
)->usesStmtJournal
));
2729 ** Usage: sqlite3_reset STMT
2731 ** Reset a statement handle.
2733 static int SQLITE_TCLAPI
test_reset(
2737 Tcl_Obj
*CONST objv
[]
2739 sqlite3_stmt
*pStmt
;
2743 Tcl_AppendResult(interp
, "wrong # args: should be \"",
2744 Tcl_GetStringFromObj(objv
[0], 0), " <STMT>", 0);
2748 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
2750 rc
= sqlite3_reset(pStmt
);
2751 if( pStmt
&& sqlite3TestErrCode(interp
, StmtToDb(pStmt
), rc
) ){
2754 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), TCL_STATIC
);
2764 ** Usage: sqlite3_expired STMT
2766 ** Return TRUE if a recompilation of the statement is recommended.
2768 static int SQLITE_TCLAPI
test_expired(
2772 Tcl_Obj
*CONST objv
[]
2774 #ifndef SQLITE_OMIT_DEPRECATED
2775 sqlite3_stmt
*pStmt
;
2777 Tcl_AppendResult(interp
, "wrong # args: should be \"",
2778 Tcl_GetStringFromObj(objv
[0], 0), " <STMT>", 0);
2781 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
2782 Tcl_SetObjResult(interp
, Tcl_NewBooleanObj(sqlite3_expired(pStmt
)));
2788 ** Usage: sqlite3_transfer_bindings FROMSTMT TOSTMT
2790 ** Transfer all bindings from FROMSTMT over to TOSTMT
2792 static int SQLITE_TCLAPI
test_transfer_bind(
2796 Tcl_Obj
*CONST objv
[]
2798 #ifndef SQLITE_OMIT_DEPRECATED
2799 sqlite3_stmt
*pStmt1
, *pStmt2
;
2801 Tcl_AppendResult(interp
, "wrong # args: should be \"",
2802 Tcl_GetStringFromObj(objv
[0], 0), " FROM-STMT TO-STMT", 0);
2805 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt1
)) return TCL_ERROR
;
2806 if( getStmtPointer(interp
, Tcl_GetString(objv
[2]), &pStmt2
)) return TCL_ERROR
;
2807 Tcl_SetObjResult(interp
,
2808 Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1
,pStmt2
)));
2814 ** Usage: sqlite3_changes DB
2816 ** Return the number of changes made to the database by the last SQL
2819 static int SQLITE_TCLAPI
test_changes(
2823 Tcl_Obj
*CONST objv
[]
2827 Tcl_AppendResult(interp
, "wrong # args: should be \"",
2828 Tcl_GetString(objv
[0]), " DB", 0);
2831 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
2832 Tcl_SetObjResult(interp
, Tcl_NewIntObj(sqlite3_changes(db
)));
2837 ** This is the "static_bind_value" that variables are bound to when
2838 ** the FLAG option of sqlite3_bind is "static"
2840 static char *sqlite_static_bind_value
= 0;
2841 static int sqlite_static_bind_nbyte
= 0;
2844 ** Usage: sqlite3_bind VM IDX VALUE FLAGS
2846 ** Sets the value of the IDX-th occurrence of "?" in the original SQL
2847 ** string. VALUE is the new value. If FLAGS=="null" then VALUE is
2848 ** ignored and the value is set to NULL. If FLAGS=="static" then
2849 ** the value is set to the value of a static variable named
2850 ** "sqlite_static_bind_value". If FLAGS=="normal" then a copy
2851 ** of the VALUE is made. If FLAGS=="blob10" then a VALUE is ignored
2852 ** an a 10-byte blob "abc\000xyz\000pq" is inserted.
2854 static int SQLITE_TCLAPI
test_bind(
2856 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
2857 int argc
, /* Number of arguments */
2858 char **argv
/* Text of each argument */
2860 sqlite3_stmt
*pStmt
;
2864 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
2865 " VM IDX VALUE (null|static|normal)\"", 0);
2868 if( getStmtPointer(interp
, argv
[1], &pStmt
) ) return TCL_ERROR
;
2869 if( Tcl_GetInt(interp
, argv
[2], &idx
) ) return TCL_ERROR
;
2870 if( strcmp(argv
[4],"null")==0 ){
2871 rc
= sqlite3_bind_null(pStmt
, idx
);
2872 }else if( strcmp(argv
[4],"static")==0 ){
2873 rc
= sqlite3_bind_text(pStmt
, idx
, sqlite_static_bind_value
, -1, 0);
2874 }else if( strcmp(argv
[4],"static-nbytes")==0 ){
2875 rc
= sqlite3_bind_text(pStmt
, idx
, sqlite_static_bind_value
,
2876 sqlite_static_bind_nbyte
, 0);
2877 }else if( strcmp(argv
[4],"normal")==0 ){
2878 rc
= sqlite3_bind_text(pStmt
, idx
, argv
[3], -1, SQLITE_TRANSIENT
);
2879 }else if( strcmp(argv
[4],"blob10")==0 ){
2880 rc
= sqlite3_bind_text(pStmt
, idx
, "abc\000xyz\000pq", 10, SQLITE_STATIC
);
2882 Tcl_AppendResult(interp
, "4th argument should be "
2883 "\"null\" or \"static\" or \"normal\"", 0);
2886 if( sqlite3TestErrCode(interp
, StmtToDb(pStmt
), rc
) ) return TCL_ERROR
;
2889 sqlite3_snprintf(sizeof(zBuf
), zBuf
, "(%d) ", rc
);
2890 Tcl_AppendResult(interp
, zBuf
, sqlite3ErrStr(rc
), 0);
2896 #ifndef SQLITE_OMIT_UTF16
2898 ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
2900 ** This function is used to test that SQLite selects the correct collation
2901 ** sequence callback when multiple versions (for different text encodings)
2904 ** Calling this routine registers the collation sequence "test_collate"
2905 ** with database handle <db>. The second argument must be a list of three
2906 ** boolean values. If the first is true, then a version of test_collate is
2907 ** registered for UTF-8, if the second is true, a version is registered for
2908 ** UTF-16le, if the third is true, a UTF-16be version is available.
2909 ** Previous versions of test_collate are deleted.
2911 ** The collation sequence test_collate is implemented by calling the
2912 ** following TCL script:
2914 ** "test_collate <enc> <lhs> <rhs>"
2916 ** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
2917 ** The <enc> parameter is the encoding of the collation function that
2918 ** SQLite selected to call. The TCL test script implements the
2919 ** "test_collate" proc.
2921 ** Note that this will only work with one interpreter at a time, as the
2922 ** interp pointer to use when evaluating the TCL script is stored in
2923 ** pTestCollateInterp.
2925 static Tcl_Interp
* pTestCollateInterp
;
2926 static int test_collate_func(
2928 int nA
, const void *zA
,
2929 int nB
, const void *zB
2931 Tcl_Interp
*i
= pTestCollateInterp
;
2932 int encin
= SQLITE_PTR_TO_INT(pCtx
);
2936 sqlite3_value
*pVal
;
2939 pX
= Tcl_NewStringObj("test_collate", -1);
2940 Tcl_IncrRefCount(pX
);
2944 Tcl_ListObjAppendElement(i
,pX
,Tcl_NewStringObj("UTF-8",-1));
2946 case SQLITE_UTF16LE
:
2947 Tcl_ListObjAppendElement(i
,pX
,Tcl_NewStringObj("UTF-16LE",-1));
2949 case SQLITE_UTF16BE
:
2950 Tcl_ListObjAppendElement(i
,pX
,Tcl_NewStringObj("UTF-16BE",-1));
2956 sqlite3BeginBenignMalloc();
2957 pVal
= sqlite3ValueNew(0);
2959 sqlite3ValueSetStr(pVal
, nA
, zA
, encin
, SQLITE_STATIC
);
2960 n
= sqlite3_value_bytes(pVal
);
2961 Tcl_ListObjAppendElement(i
,pX
,
2962 Tcl_NewStringObj((char*)sqlite3_value_text(pVal
),n
));
2963 sqlite3ValueSetStr(pVal
, nB
, zB
, encin
, SQLITE_STATIC
);
2964 n
= sqlite3_value_bytes(pVal
);
2965 Tcl_ListObjAppendElement(i
,pX
,
2966 Tcl_NewStringObj((char*)sqlite3_value_text(pVal
),n
));
2967 sqlite3ValueFree(pVal
);
2969 sqlite3EndBenignMalloc();
2971 Tcl_EvalObjEx(i
, pX
, 0);
2972 Tcl_DecrRefCount(pX
);
2973 Tcl_GetIntFromObj(i
, Tcl_GetObjResult(i
), &res
);
2976 static int SQLITE_TCLAPI
test_collate(
2980 Tcl_Obj
*CONST objv
[]
2984 sqlite3_value
*pVal
;
2987 if( objc
!=5 ) goto bad_args
;
2988 pTestCollateInterp
= interp
;
2989 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
2991 if( TCL_OK
!=Tcl_GetBooleanFromObj(interp
, objv
[2], &val
) ) return TCL_ERROR
;
2992 rc
= sqlite3_create_collation(db
, "test_collate", SQLITE_UTF8
,
2993 (void *)SQLITE_UTF8
, val
?test_collate_func
:0);
2994 if( rc
==SQLITE_OK
){
2996 if( TCL_OK
!=Tcl_GetBooleanFromObj(interp
, objv
[3], &val
) ) return TCL_ERROR
;
2997 rc
= sqlite3_create_collation(db
, "test_collate", SQLITE_UTF16LE
,
2998 (void *)SQLITE_UTF16LE
, val
?test_collate_func
:0);
2999 if( TCL_OK
!=Tcl_GetBooleanFromObj(interp
, objv
[4], &val
) ) return TCL_ERROR
;
3002 if( sqlite3_iMallocFail
>0 ){
3003 sqlite3_iMallocFail
++;
3006 sqlite3_mutex_enter(db
->mutex
);
3007 pVal
= sqlite3ValueNew(db
);
3008 sqlite3ValueSetStr(pVal
, -1, "test_collate", SQLITE_UTF8
, SQLITE_STATIC
);
3009 zUtf16
= sqlite3ValueText(pVal
, SQLITE_UTF16NATIVE
);
3010 if( db
->mallocFailed
){
3013 rc
= sqlite3_create_collation16(db
, zUtf16
, SQLITE_UTF16BE
,
3014 (void *)SQLITE_UTF16BE
, val
?test_collate_func
:0);
3016 sqlite3ValueFree(pVal
);
3017 sqlite3_mutex_leave(db
->mutex
);
3019 if( sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
3021 if( rc
!=SQLITE_OK
){
3022 Tcl_AppendResult(interp
, sqlite3ErrName(rc
), 0);
3028 Tcl_AppendResult(interp
, "wrong # args: should be \"",
3029 Tcl_GetStringFromObj(objv
[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
3034 ** Usage: add_test_utf16bin_collate <db ptr>
3036 ** Add a utf-16 collation sequence named "utf16bin" to the database
3037 ** handle. This collation sequence compares arguments in the same way as the
3038 ** built-in collation "binary".
3040 static int test_utf16bin_collate_func(
3042 int nA
, const void *zA
,
3043 int nB
, const void *zB
3045 int nCmp
= (nA
>nB
? nB
: nA
);
3046 int res
= memcmp(zA
, zB
, nCmp
);
3047 if( res
==0 ) res
= nA
- nB
;
3050 static int SQLITE_TCLAPI
test_utf16bin_collate(
3054 Tcl_Obj
*CONST objv
[]
3059 if( objc
!=2 ) goto bad_args
;
3060 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
3062 rc
= sqlite3_create_collation(db
, "utf16bin", SQLITE_UTF16
, 0,
3063 test_utf16bin_collate_func
3065 if( sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
3069 Tcl_WrongNumArgs(interp
, 1, objv
, "DB");
3074 ** When the collation needed callback is invoked, record the name of
3075 ** the requested collating function here. The recorded name is linked
3076 ** to a TCL variable and used to make sure that the requested collation
3079 static char zNeededCollation
[200];
3080 static char *pzNeededCollation
= zNeededCollation
;
3084 ** Called when a collating sequence is needed. Registered using
3085 ** sqlite3_collation_needed16().
3087 static void test_collate_needed_cb(
3096 for(z
= (char*)pName
, i
=0; *z
|| z
[1]; z
++){
3097 if( *z
) zNeededCollation
[i
++] = *z
;
3099 zNeededCollation
[i
] = 0;
3100 sqlite3_create_collation(
3101 db
, "test_collate", ENC(db
), SQLITE_INT_TO_PTR(enc
), test_collate_func
);
3105 ** Usage: add_test_collate_needed DB
3107 static int SQLITE_TCLAPI
test_collate_needed(
3111 Tcl_Obj
*CONST objv
[]
3116 if( objc
!=2 ) goto bad_args
;
3117 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
3118 rc
= sqlite3_collation_needed16(db
, 0, test_collate_needed_cb
);
3119 zNeededCollation
[0] = 0;
3120 if( sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
3124 Tcl_WrongNumArgs(interp
, 1, objv
, "DB");
3129 ** tclcmd: add_alignment_test_collations DB
3131 ** Add two new collating sequences to the database DB
3136 ** Both collating sequences use the same sort order as BINARY.
3137 ** The only difference is that the utf16_aligned collating
3138 ** sequence is declared with the SQLITE_UTF16_ALIGNED flag.
3139 ** Both collating functions increment the unaligned utf16 counter
3140 ** whenever they see a string that begins on an odd byte boundary.
3142 static int unaligned_string_counter
= 0;
3143 static int alignmentCollFunc(
3145 int nKey1
, const void *pKey1
,
3146 int nKey2
, const void *pKey2
3149 n
= nKey1
<nKey2
? nKey1
: nKey2
;
3150 if( nKey1
>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey1
))) ) unaligned_string_counter
++;
3151 if( nKey2
>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey2
))) ) unaligned_string_counter
++;
3152 rc
= memcmp(pKey1
, pKey2
, n
);
3158 static int SQLITE_TCLAPI
add_alignment_test_collations(
3162 Tcl_Obj
*CONST objv
[]
3166 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
3167 sqlite3_create_collation(db
, "utf16_unaligned", SQLITE_UTF16
,
3168 0, alignmentCollFunc
);
3169 sqlite3_create_collation(db
, "utf16_aligned", SQLITE_UTF16_ALIGNED
,
3170 0, alignmentCollFunc
);
3174 #endif /* !defined(SQLITE_OMIT_UTF16) */
3177 ** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
3179 ** This function is used to test that SQLite selects the correct user
3180 ** function callback when multiple versions (for different text encodings)
3183 ** Calling this routine registers up to three versions of the user function
3184 ** "test_function" with database handle <db>. If the second argument is
3185 ** true, then a version of test_function is registered for UTF-8, if the
3186 ** third is true, a version is registered for UTF-16le, if the fourth is
3187 ** true, a UTF-16be version is available. Previous versions of
3188 ** test_function are deleted.
3190 ** The user function is implemented by calling the following TCL script:
3192 ** "test_function <enc> <arg>"
3194 ** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
3195 ** single argument passed to the SQL function. The value returned by
3196 ** the TCL script is used as the return value of the SQL function. It
3197 ** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
3198 ** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
3199 ** prefers UTF-16BE.
3201 #ifndef SQLITE_OMIT_UTF16
3202 static void test_function_utf8(
3203 sqlite3_context
*pCtx
,
3205 sqlite3_value
**argv
3209 sqlite3_value
*pVal
;
3210 interp
= (Tcl_Interp
*)sqlite3_user_data(pCtx
);
3211 pX
= Tcl_NewStringObj("test_function", -1);
3212 Tcl_IncrRefCount(pX
);
3213 Tcl_ListObjAppendElement(interp
, pX
, Tcl_NewStringObj("UTF-8", -1));
3214 Tcl_ListObjAppendElement(interp
, pX
,
3215 Tcl_NewStringObj((char*)sqlite3_value_text(argv
[0]), -1));
3216 Tcl_EvalObjEx(interp
, pX
, 0);
3217 Tcl_DecrRefCount(pX
);
3218 sqlite3_result_text(pCtx
, Tcl_GetStringResult(interp
), -1, SQLITE_TRANSIENT
);
3219 pVal
= sqlite3ValueNew(0);
3220 sqlite3ValueSetStr(pVal
, -1, Tcl_GetStringResult(interp
),
3221 SQLITE_UTF8
, SQLITE_STATIC
);
3222 sqlite3_result_text16be(pCtx
, sqlite3_value_text16be(pVal
),
3223 -1, SQLITE_TRANSIENT
);
3224 sqlite3ValueFree(pVal
);
3226 static void test_function_utf16le(
3227 sqlite3_context
*pCtx
,
3229 sqlite3_value
**argv
3233 sqlite3_value
*pVal
;
3234 interp
= (Tcl_Interp
*)sqlite3_user_data(pCtx
);
3235 pX
= Tcl_NewStringObj("test_function", -1);
3236 Tcl_IncrRefCount(pX
);
3237 Tcl_ListObjAppendElement(interp
, pX
, Tcl_NewStringObj("UTF-16LE", -1));
3238 Tcl_ListObjAppendElement(interp
, pX
,
3239 Tcl_NewStringObj((char*)sqlite3_value_text(argv
[0]), -1));
3240 Tcl_EvalObjEx(interp
, pX
, 0);
3241 Tcl_DecrRefCount(pX
);
3242 pVal
= sqlite3ValueNew(0);
3243 sqlite3ValueSetStr(pVal
, -1, Tcl_GetStringResult(interp
),
3244 SQLITE_UTF8
, SQLITE_STATIC
);
3245 sqlite3_result_text(pCtx
,(char*)sqlite3_value_text(pVal
),-1,SQLITE_TRANSIENT
);
3246 sqlite3ValueFree(pVal
);
3248 static void test_function_utf16be(
3249 sqlite3_context
*pCtx
,
3251 sqlite3_value
**argv
3255 sqlite3_value
*pVal
;
3256 interp
= (Tcl_Interp
*)sqlite3_user_data(pCtx
);
3257 pX
= Tcl_NewStringObj("test_function", -1);
3258 Tcl_IncrRefCount(pX
);
3259 Tcl_ListObjAppendElement(interp
, pX
, Tcl_NewStringObj("UTF-16BE", -1));
3260 Tcl_ListObjAppendElement(interp
, pX
,
3261 Tcl_NewStringObj((char*)sqlite3_value_text(argv
[0]), -1));
3262 Tcl_EvalObjEx(interp
, pX
, 0);
3263 Tcl_DecrRefCount(pX
);
3264 pVal
= sqlite3ValueNew(0);
3265 sqlite3ValueSetStr(pVal
, -1, Tcl_GetStringResult(interp
),
3266 SQLITE_UTF8
, SQLITE_STATIC
);
3267 sqlite3_result_text16(pCtx
, sqlite3_value_text16le(pVal
),
3268 -1, SQLITE_TRANSIENT
);
3269 sqlite3_result_text16be(pCtx
, sqlite3_value_text16le(pVal
),
3270 -1, SQLITE_TRANSIENT
);
3271 sqlite3_result_text16le(pCtx
, sqlite3_value_text16le(pVal
),
3272 -1, SQLITE_TRANSIENT
);
3273 sqlite3ValueFree(pVal
);
3275 #endif /* SQLITE_OMIT_UTF16 */
3276 static int SQLITE_TCLAPI
test_function(
3280 Tcl_Obj
*CONST objv
[]
3282 #ifndef SQLITE_OMIT_UTF16
3286 if( objc
!=5 ) goto bad_args
;
3287 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
3289 if( TCL_OK
!=Tcl_GetBooleanFromObj(interp
, objv
[2], &val
) ) return TCL_ERROR
;
3291 sqlite3_create_function(db
, "test_function", 1, SQLITE_UTF8
,
3292 interp
, test_function_utf8
, 0, 0);
3294 if( TCL_OK
!=Tcl_GetBooleanFromObj(interp
, objv
[3], &val
) ) return TCL_ERROR
;
3296 sqlite3_create_function(db
, "test_function", 1, SQLITE_UTF16LE
,
3297 interp
, test_function_utf16le
, 0, 0);
3299 if( TCL_OK
!=Tcl_GetBooleanFromObj(interp
, objv
[4], &val
) ) return TCL_ERROR
;
3301 sqlite3_create_function(db
, "test_function", 1, SQLITE_UTF16BE
,
3302 interp
, test_function_utf16be
, 0, 0);
3307 Tcl_AppendResult(interp
, "wrong # args: should be \"",
3308 Tcl_GetStringFromObj(objv
[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
3309 #endif /* SQLITE_OMIT_UTF16 */
3314 ** Usage: sqlite3_test_errstr <err code>
3316 ** Test that the english language string equivalents for sqlite error codes
3317 ** are sane. The parameter is an integer representing an sqlite error code.
3318 ** The result is a list of two elements, the string representation of the
3319 ** error code and the english language explanation.
3321 static int SQLITE_TCLAPI
test_errstr(
3325 Tcl_Obj
*CONST objv
[]
3330 Tcl_WrongNumArgs(interp
, 1, objv
, "<error code>");
3333 zCode
= Tcl_GetString(objv
[1]);
3334 for(i
=0; i
<200; i
++){
3335 if( 0==strcmp(t1ErrorName(i
), zCode
) ) break;
3337 Tcl_SetResult(interp
, (char *)sqlite3ErrStr(i
), 0);
3342 ** Usage: breakpoint
3344 ** This routine exists for one purpose - to provide a place to put a
3345 ** breakpoint with GDB that can be triggered using TCL code. The use
3346 ** for this is when a particular test fails on (say) the 1485th iteration.
3347 ** In the TCL test script, we can add code like this:
3349 ** if {$i==1485} breakpoint
3351 ** Then run testfixture in the debugger and wait for the breakpoint to
3352 ** fire. Then additional breakpoints can be set to trace down the bug.
3354 static int SQLITE_TCLAPI
test_breakpoint(
3356 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
3357 int argc
, /* Number of arguments */
3358 char **argv
/* Text of each argument */
3360 return TCL_OK
; /* Do nothing */
3364 ** Usage: sqlite3_bind_zeroblob STMT IDX N
3366 ** Test the sqlite3_bind_zeroblob interface. STMT is a prepared statement.
3367 ** IDX is the index of a wildcard in the prepared statement. This command
3368 ** binds a N-byte zero-filled BLOB to the wildcard.
3370 static int SQLITE_TCLAPI
test_bind_zeroblob(
3374 Tcl_Obj
*CONST objv
[]
3376 sqlite3_stmt
*pStmt
;
3382 Tcl_WrongNumArgs(interp
, 1, objv
, "STMT IDX N");
3386 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
3387 if( Tcl_GetIntFromObj(interp
, objv
[2], &idx
) ) return TCL_ERROR
;
3388 if( Tcl_GetIntFromObj(interp
, objv
[3], &n
) ) return TCL_ERROR
;
3390 rc
= sqlite3_bind_zeroblob(pStmt
, idx
, n
);
3391 if( sqlite3TestErrCode(interp
, StmtToDb(pStmt
), rc
) ) return TCL_ERROR
;
3392 if( rc
!=SQLITE_OK
){
3400 ** Usage: sqlite3_bind_zeroblob64 STMT IDX N
3402 ** Test the sqlite3_bind_zeroblob64 interface. STMT is a prepared statement.
3403 ** IDX is the index of a wildcard in the prepared statement. This command
3404 ** binds a N-byte zero-filled BLOB to the wildcard.
3406 static int SQLITE_TCLAPI
test_bind_zeroblob64(
3410 Tcl_Obj
*CONST objv
[]
3412 sqlite3_stmt
*pStmt
;
3418 Tcl_WrongNumArgs(interp
, 1, objv
, "STMT IDX N");
3422 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
3423 if( Tcl_GetIntFromObj(interp
, objv
[2], &idx
) ) return TCL_ERROR
;
3424 if( Tcl_GetWideIntFromObj(interp
, objv
[3], &n
) ) return TCL_ERROR
;
3426 rc
= sqlite3_bind_zeroblob64(pStmt
, idx
, n
);
3427 if( sqlite3TestErrCode(interp
, StmtToDb(pStmt
), rc
) ) return TCL_ERROR
;
3428 if( rc
!=SQLITE_OK
){
3429 Tcl_AppendResult(interp
, sqlite3ErrName(rc
), 0);
3437 ** Usage: sqlite3_bind_int STMT N VALUE
3439 ** Test the sqlite3_bind_int interface. STMT is a prepared statement.
3440 ** N is the index of a wildcard in the prepared statement. This command
3441 ** binds a 32-bit integer VALUE to that wildcard.
3443 static int SQLITE_TCLAPI
test_bind_int(
3447 Tcl_Obj
*CONST objv
[]
3449 sqlite3_stmt
*pStmt
;
3455 Tcl_AppendResult(interp
, "wrong # args: should be \"",
3456 Tcl_GetStringFromObj(objv
[0], 0), " STMT N VALUE", 0);
3460 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
3461 if( Tcl_GetIntFromObj(interp
, objv
[2], &idx
) ) return TCL_ERROR
;
3462 if( Tcl_GetIntFromObj(interp
, objv
[3], &value
) ) return TCL_ERROR
;
3464 rc
= sqlite3_bind_int(pStmt
, idx
, value
);
3465 if( sqlite3TestErrCode(interp
, StmtToDb(pStmt
), rc
) ) return TCL_ERROR
;
3466 if( rc
!=SQLITE_OK
){
3475 ** Usage: intarray_addr INT ...
3477 ** Return the address of a C-language array of 32-bit integers.
3479 ** Space to hold the array is obtained from malloc(). Call this procedure once
3480 ** with no arguments in order to release memory. Each call to this procedure
3481 ** overwrites the previous array.
3483 static int SQLITE_TCLAPI
test_intarray_addr(
3487 Tcl_Obj
*CONST objv
[]
3495 p
= sqlite3_malloc( sizeof(p
[0])*(objc
-1) );
3496 if( p
==0 ) return TCL_ERROR
;
3497 for(i
=0; i
<objc
-1; i
++){
3498 if( Tcl_GetIntFromObj(interp
, objv
[1+i
], &p
[i
]) ){
3505 Tcl_SetObjResult(interp
, Tcl_NewWideIntObj((sqlite3_int64
)p
));
3509 ** Usage: intarray_addr INT ...
3511 ** Return the address of a C-language array of 32-bit integers.
3513 ** Space to hold the array is obtained from malloc(). Call this procedure once
3514 ** with no arguments in order to release memory. Each call to this procedure
3515 ** overwrites the previous array.
3517 static int SQLITE_TCLAPI
test_int64array_addr(
3521 Tcl_Obj
*CONST objv
[]
3524 static sqlite3_int64
*p
= 0;
3529 p
= sqlite3_malloc( sizeof(p
[0])*(objc
-1) );
3530 if( p
==0 ) return TCL_ERROR
;
3531 for(i
=0; i
<objc
-1; i
++){
3533 if( Tcl_GetWideIntFromObj(interp
, objv
[1+i
], &v
) ){
3541 Tcl_SetObjResult(interp
, Tcl_NewWideIntObj((sqlite3_int64
)p
));
3545 ** Usage: doublearray_addr INT ...
3547 ** Return the address of a C-language array of doubles.
3549 ** Space to hold the array is obtained from malloc(). Call this procedure once
3550 ** with no arguments in order to release memory. Each call to this procedure
3551 ** overwrites the previous array.
3553 static int SQLITE_TCLAPI
test_doublearray_addr(
3557 Tcl_Obj
*CONST objv
[]
3560 static double *p
= 0;
3565 p
= sqlite3_malloc( sizeof(p
[0])*(objc
-1) );
3566 if( p
==0 ) return TCL_ERROR
;
3567 for(i
=0; i
<objc
-1; i
++){
3568 if( Tcl_GetDoubleFromObj(interp
, objv
[1+i
], &p
[i
]) ){
3575 Tcl_SetObjResult(interp
, Tcl_NewWideIntObj((sqlite3_int64
)p
));
3579 ** Usage: textarray_addr TEXT ...
3581 ** Return the address of a C-language array of strings.
3583 ** Space to hold the array is obtained from malloc(). Call this procedure once
3584 ** with no arguments in order to release memory. Each call to this procedure
3585 ** overwrites the previous array.
3587 static int SQLITE_TCLAPI
test_textarray_addr(
3591 Tcl_Obj
*CONST objv
[]
3595 static char **p
= 0;
3597 for(i
=0; i
<n
; i
++) sqlite3_free(p
[i
]);
3601 p
= sqlite3_malloc( sizeof(p
[0])*(objc
-1) );
3602 if( p
==0 ) return TCL_ERROR
;
3603 for(i
=0; i
<objc
-1; i
++){
3604 p
[i
] = sqlite3_mprintf("%s", Tcl_GetString(objv
[1+i
]));
3608 Tcl_SetObjResult(interp
, Tcl_NewWideIntObj((sqlite3_int64
)p
));
3614 ** Usage: sqlite3_bind_int64 STMT N VALUE
3616 ** Test the sqlite3_bind_int64 interface. STMT is a prepared statement.
3617 ** N is the index of a wildcard in the prepared statement. This command
3618 ** binds a 64-bit integer VALUE to that wildcard.
3620 static int SQLITE_TCLAPI
test_bind_int64(
3624 Tcl_Obj
*CONST objv
[]
3626 sqlite3_stmt
*pStmt
;
3632 Tcl_AppendResult(interp
, "wrong # args: should be \"",
3633 Tcl_GetStringFromObj(objv
[0], 0), " STMT N VALUE", 0);
3637 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
3638 if( Tcl_GetIntFromObj(interp
, objv
[2], &idx
) ) return TCL_ERROR
;
3639 if( Tcl_GetWideIntFromObj(interp
, objv
[3], &value
) ) return TCL_ERROR
;
3641 rc
= sqlite3_bind_int64(pStmt
, idx
, value
);
3642 if( sqlite3TestErrCode(interp
, StmtToDb(pStmt
), rc
) ) return TCL_ERROR
;
3643 if( rc
!=SQLITE_OK
){
3652 ** Usage: sqlite3_bind_double STMT N VALUE
3654 ** Test the sqlite3_bind_double interface. STMT is a prepared statement.
3655 ** N is the index of a wildcard in the prepared statement. This command
3656 ** binds a 64-bit integer VALUE to that wildcard.
3658 static int SQLITE_TCLAPI
test_bind_double(
3662 Tcl_Obj
*CONST objv
[]
3664 sqlite3_stmt
*pStmt
;
3670 static const struct {
3671 const char *zName
; /* Name of the special floating point value */
3672 unsigned int iUpper
; /* Upper 32 bits */
3673 unsigned int iLower
; /* Lower 32 bits */
3675 { "NaN", 0x7fffffff, 0xffffffff },
3676 { "SNaN", 0x7ff7ffff, 0xffffffff },
3677 { "-NaN", 0xffffffff, 0xffffffff },
3678 { "-SNaN", 0xfff7ffff, 0xffffffff },
3679 { "+Inf", 0x7ff00000, 0x00000000 },
3680 { "-Inf", 0xfff00000, 0x00000000 },
3681 { "Epsilon", 0x00000000, 0x00000001 },
3682 { "-Epsilon", 0x80000000, 0x00000001 },
3683 { "NaN0", 0x7ff80000, 0x00000000 },
3684 { "-NaN0", 0xfff80000, 0x00000000 },
3688 Tcl_AppendResult(interp
, "wrong # args: should be \"",
3689 Tcl_GetStringFromObj(objv
[0], 0), " STMT N VALUE", 0);
3693 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
3694 if( Tcl_GetIntFromObj(interp
, objv
[2], &idx
) ) return TCL_ERROR
;
3696 /* Intercept the string "NaN" and generate a NaN value for it.
3697 ** All other strings are passed through to Tcl_GetDoubleFromObj().
3698 ** Tcl_GetDoubleFromObj() should understand "NaN" but some versions
3701 zVal
= Tcl_GetString(objv
[3]);
3702 for(i
=0; i
<sizeof(aSpecialFp
)/sizeof(aSpecialFp
[0]); i
++){
3703 if( strcmp(aSpecialFp
[i
].zName
, zVal
)==0 ){
3705 x
= aSpecialFp
[i
].iUpper
;
3707 x
|= aSpecialFp
[i
].iLower
;
3708 assert( sizeof(value
)==8 );
3709 assert( sizeof(x
)==8 );
3710 memcpy(&value
, &x
, 8);
3714 if( i
>=sizeof(aSpecialFp
)/sizeof(aSpecialFp
[0]) &&
3715 Tcl_GetDoubleFromObj(interp
, objv
[3], &value
) ){
3718 rc
= sqlite3_bind_double(pStmt
, idx
, value
);
3719 if( sqlite3TestErrCode(interp
, StmtToDb(pStmt
), rc
) ) return TCL_ERROR
;
3720 if( rc
!=SQLITE_OK
){
3728 ** Usage: sqlite3_bind_null STMT N
3730 ** Test the sqlite3_bind_null interface. STMT is a prepared statement.
3731 ** N is the index of a wildcard in the prepared statement. This command
3732 ** binds a NULL to the wildcard.
3734 static int SQLITE_TCLAPI
test_bind_null(
3738 Tcl_Obj
*CONST objv
[]
3740 sqlite3_stmt
*pStmt
;
3745 Tcl_AppendResult(interp
, "wrong # args: should be \"",
3746 Tcl_GetStringFromObj(objv
[0], 0), " STMT N", 0);
3750 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
3751 if( Tcl_GetIntFromObj(interp
, objv
[2], &idx
) ) return TCL_ERROR
;
3753 rc
= sqlite3_bind_null(pStmt
, idx
);
3754 if( sqlite3TestErrCode(interp
, StmtToDb(pStmt
), rc
) ) return TCL_ERROR
;
3755 if( rc
!=SQLITE_OK
){
3763 ** Usage: sqlite3_bind_text STMT N STRING BYTES
3765 ** Test the sqlite3_bind_text interface. STMT is a prepared statement.
3766 ** N is the index of a wildcard in the prepared statement. This command
3767 ** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes
3770 static int SQLITE_TCLAPI
test_bind_text(
3774 Tcl_Obj
*CONST objv
[]
3776 sqlite3_stmt
*pStmt
;
3783 Tcl_AppendResult(interp
, "wrong # args: should be \"",
3784 Tcl_GetStringFromObj(objv
[0], 0), " STMT N VALUE BYTES", 0);
3788 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
3789 if( Tcl_GetIntFromObj(interp
, objv
[2], &idx
) ) return TCL_ERROR
;
3790 value
= (char*)Tcl_GetByteArrayFromObj(objv
[3], &bytes
);
3791 if( Tcl_GetIntFromObj(interp
, objv
[4], &bytes
) ) return TCL_ERROR
;
3793 rc
= sqlite3_bind_text(pStmt
, idx
, value
, bytes
, SQLITE_TRANSIENT
);
3794 if( sqlite3TestErrCode(interp
, StmtToDb(pStmt
), rc
) ) return TCL_ERROR
;
3795 if( rc
!=SQLITE_OK
){
3796 Tcl_AppendResult(interp
, sqlite3ErrName(rc
), 0);
3804 ** Usage: sqlite3_bind_text16 ?-static? STMT N STRING BYTES
3806 ** Test the sqlite3_bind_text16 interface. STMT is a prepared statement.
3807 ** N is the index of a wildcard in the prepared statement. This command
3808 ** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes
3811 static int SQLITE_TCLAPI
test_bind_text16(
3815 Tcl_Obj
*CONST objv
[]
3817 #ifndef SQLITE_OMIT_UTF16
3818 sqlite3_stmt
*pStmt
;
3824 void (*xDel
)(void*) = (objc
==6?SQLITE_STATIC
:SQLITE_TRANSIENT
);
3825 Tcl_Obj
*oStmt
= objv
[objc
-4];
3826 Tcl_Obj
*oN
= objv
[objc
-3];
3827 Tcl_Obj
*oString
= objv
[objc
-2];
3828 Tcl_Obj
*oBytes
= objv
[objc
-1];
3830 if( objc
!=5 && objc
!=6){
3831 Tcl_AppendResult(interp
, "wrong # args: should be \"",
3832 Tcl_GetStringFromObj(objv
[0], 0), " STMT N VALUE BYTES", 0);
3836 if( getStmtPointer(interp
, Tcl_GetString(oStmt
), &pStmt
) ) return TCL_ERROR
;
3837 if( Tcl_GetIntFromObj(interp
, oN
, &idx
) ) return TCL_ERROR
;
3838 value
= (char*)Tcl_GetByteArrayFromObj(oString
, 0);
3839 if( Tcl_GetIntFromObj(interp
, oBytes
, &bytes
) ) return TCL_ERROR
;
3841 rc
= sqlite3_bind_text16(pStmt
, idx
, (void *)value
, bytes
, xDel
);
3842 if( sqlite3TestErrCode(interp
, StmtToDb(pStmt
), rc
) ) return TCL_ERROR
;
3843 if( rc
!=SQLITE_OK
){
3844 Tcl_AppendResult(interp
, sqlite3ErrName(rc
), 0);
3848 #endif /* SQLITE_OMIT_UTF16 */
3853 ** Usage: sqlite3_bind_blob ?-static? STMT N DATA BYTES
3855 ** Test the sqlite3_bind_blob interface. STMT is a prepared statement.
3856 ** N is the index of a wildcard in the prepared statement. This command
3857 ** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size.
3859 static int SQLITE_TCLAPI
test_bind_blob(
3863 Tcl_Obj
*CONST objv
[]
3865 sqlite3_stmt
*pStmt
;
3870 sqlite3_destructor_type xDestructor
= SQLITE_TRANSIENT
;
3872 if( objc
!=5 && objc
!=6 ){
3873 Tcl_AppendResult(interp
, "wrong # args: should be \"",
3874 Tcl_GetStringFromObj(objv
[0], 0), " STMT N DATA BYTES", 0);
3879 xDestructor
= SQLITE_STATIC
;
3883 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
3884 if( Tcl_GetIntFromObj(interp
, objv
[2], &idx
) ) return TCL_ERROR
;
3886 value
= (char*)Tcl_GetByteArrayFromObj(objv
[3], &len
);
3887 if( Tcl_GetIntFromObj(interp
, objv
[4], &bytes
) ) return TCL_ERROR
;
3891 sqlite3_snprintf(sizeof(zBuf
), zBuf
,
3892 "cannot use %d blob bytes, have %d", bytes
, len
);
3893 Tcl_AppendResult(interp
, zBuf
, -1);
3897 rc
= sqlite3_bind_blob(pStmt
, idx
, value
, bytes
, xDestructor
);
3898 if( sqlite3TestErrCode(interp
, StmtToDb(pStmt
), rc
) ) return TCL_ERROR
;
3899 if( rc
!=SQLITE_OK
){
3907 ** Usage: sqlite3_bind_parameter_count STMT
3909 ** Return the number of wildcards in the given statement.
3911 static int SQLITE_TCLAPI
test_bind_parameter_count(
3915 Tcl_Obj
*CONST objv
[]
3917 sqlite3_stmt
*pStmt
;
3920 Tcl_WrongNumArgs(interp
, 1, objv
, "STMT");
3923 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
3924 Tcl_SetObjResult(interp
, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt
)));
3929 ** Usage: sqlite3_bind_parameter_name STMT N
3931 ** Return the name of the Nth wildcard. The first wildcard is 1.
3932 ** An empty string is returned if N is out of range or if the wildcard
3935 static int SQLITE_TCLAPI
test_bind_parameter_name(
3939 Tcl_Obj
*CONST objv
[]
3941 sqlite3_stmt
*pStmt
;
3945 Tcl_WrongNumArgs(interp
, 1, objv
, "STMT N");
3948 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
3949 if( Tcl_GetIntFromObj(interp
, objv
[2], &i
) ) return TCL_ERROR
;
3950 Tcl_SetObjResult(interp
,
3951 Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt
,i
),-1)
3957 ** Usage: sqlite3_bind_parameter_index STMT NAME
3959 ** Return the index of the wildcard called NAME. Return 0 if there is
3960 ** no such wildcard.
3962 static int SQLITE_TCLAPI
test_bind_parameter_index(
3966 Tcl_Obj
*CONST objv
[]
3968 sqlite3_stmt
*pStmt
;
3971 Tcl_WrongNumArgs(interp
, 1, objv
, "STMT NAME");
3974 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
3975 Tcl_SetObjResult(interp
,
3977 sqlite3_bind_parameter_index(pStmt
,Tcl_GetString(objv
[2]))
3984 ** Usage: sqlite3_clear_bindings STMT
3987 static int SQLITE_TCLAPI
test_clear_bindings(
3991 Tcl_Obj
*CONST objv
[]
3993 sqlite3_stmt
*pStmt
;
3996 Tcl_WrongNumArgs(interp
, 1, objv
, "STMT");
3999 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
4000 Tcl_SetObjResult(interp
, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt
)));
4005 ** Usage: sqlite3_sleep MILLISECONDS
4007 static int SQLITE_TCLAPI
test_sleep(
4011 Tcl_Obj
*CONST objv
[]
4016 Tcl_WrongNumArgs(interp
, 1, objv
, "MILLISECONDS");
4019 if( Tcl_GetIntFromObj(interp
, objv
[1], &ms
) ){
4022 Tcl_SetObjResult(interp
, Tcl_NewIntObj(sqlite3_sleep(ms
)));
4027 ** Usage: sqlite3_extended_errcode DB
4029 ** Return the string representation of the most recent sqlite3_* API
4030 ** error code. e.g. "SQLITE_ERROR".
4032 static int SQLITE_TCLAPI
test_ex_errcode(
4036 Tcl_Obj
*CONST objv
[]
4042 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4043 Tcl_GetString(objv
[0]), " DB", 0);
4046 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
4047 rc
= sqlite3_extended_errcode(db
);
4048 Tcl_AppendResult(interp
, (char *)t1ErrorName(rc
), 0);
4054 ** Usage: sqlite3_errcode DB
4056 ** Return the string representation of the most recent sqlite3_* API
4057 ** error code. e.g. "SQLITE_ERROR".
4059 static int SQLITE_TCLAPI
test_errcode(
4063 Tcl_Obj
*CONST objv
[]
4069 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4070 Tcl_GetString(objv
[0]), " DB", 0);
4073 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
4074 rc
= sqlite3_errcode(db
);
4075 Tcl_AppendResult(interp
, (char *)t1ErrorName(rc
), 0);
4080 ** Usage: sqlite3_errmsg DB
4082 ** Returns the UTF-8 representation of the error message string for the
4083 ** most recent sqlite3_* API call.
4085 static int SQLITE_TCLAPI
test_errmsg(
4089 Tcl_Obj
*CONST objv
[]
4095 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4096 Tcl_GetString(objv
[0]), " DB", 0);
4099 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
4101 zErr
= sqlite3_errmsg(db
);
4102 Tcl_SetObjResult(interp
, Tcl_NewStringObj(zErr
, -1));
4107 ** Usage: test_errmsg16 DB
4109 ** Returns the UTF-16 representation of the error message string for the
4110 ** most recent sqlite3_* API call. This is a byte array object at the TCL
4111 ** level, and it includes the 0x00 0x00 terminator bytes at the end of the
4114 static int SQLITE_TCLAPI
test_errmsg16(
4118 Tcl_Obj
*CONST objv
[]
4120 #ifndef SQLITE_OMIT_UTF16
4127 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4128 Tcl_GetString(objv
[0]), " DB", 0);
4131 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
4133 zErr
= sqlite3_errmsg16(db
);
4136 for(bytes
=0; z
[bytes
] || z
[bytes
+1]; bytes
+=2){}
4138 Tcl_SetObjResult(interp
, Tcl_NewByteArrayObj(zErr
, bytes
));
4139 #endif /* SQLITE_OMIT_UTF16 */
4144 ** Usage: sqlite3_prepare DB sql bytes ?tailvar?
4146 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
4147 ** database handle <DB>. The parameter <tailval> is the name of a global
4148 ** variable that is set to the unused portion of <sql> (if any). A
4149 ** STMT handle is returned.
4151 static int SQLITE_TCLAPI
test_prepare(
4155 Tcl_Obj
*CONST objv
[]
4160 const char *zTail
= 0;
4161 sqlite3_stmt
*pStmt
= 0;
4165 if( objc
!=5 && objc
!=4 ){
4166 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4167 Tcl_GetString(objv
[0]), " DB sql bytes ?tailvar?", 0);
4170 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
4171 zSql
= Tcl_GetString(objv
[2]);
4172 if( Tcl_GetIntFromObj(interp
, objv
[3], &bytes
) ) return TCL_ERROR
;
4174 rc
= sqlite3_prepare(db
, zSql
, bytes
, &pStmt
, objc
>=5 ? &zTail
: 0);
4175 Tcl_ResetResult(interp
);
4176 if( sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
4177 if( zTail
&& objc
>=5 ){
4179 bytes
= bytes
- (int)(zTail
-zSql
);
4181 if( (int)strlen(zTail
)<bytes
){
4182 bytes
= (int)strlen(zTail
);
4184 Tcl_ObjSetVar2(interp
, objv
[4], 0, Tcl_NewStringObj(zTail
, bytes
), 0);
4186 if( rc
!=SQLITE_OK
){
4188 sqlite3_snprintf(sizeof(zBuf
), zBuf
, "(%d) ", rc
);
4189 Tcl_AppendResult(interp
, zBuf
, sqlite3_errmsg(db
), 0);
4194 if( sqlite3TestMakePointerStr(interp
, zBuf
, pStmt
) ) return TCL_ERROR
;
4195 Tcl_AppendResult(interp
, zBuf
, 0);
4201 ** Usage: sqlite3_prepare_v2 DB sql bytes ?tailvar?
4203 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
4204 ** database handle <DB>. The parameter <tailval> is the name of a global
4205 ** variable that is set to the unused portion of <sql> (if any). A
4206 ** STMT handle is returned.
4208 static int SQLITE_TCLAPI
test_prepare_v2(
4212 Tcl_Obj
*CONST objv
[]
4216 char *zCopy
= 0; /* malloc() copy of zSql */
4218 const char *zTail
= 0;
4219 sqlite3_stmt
*pStmt
= 0;
4223 if( objc
!=5 && objc
!=4 ){
4224 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4225 Tcl_GetString(objv
[0]), " DB sql bytes tailvar", 0);
4228 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
4229 zSql
= Tcl_GetString(objv
[2]);
4230 if( Tcl_GetIntFromObj(interp
, objv
[3], &bytes
) ) return TCL_ERROR
;
4232 /* Instead of using zSql directly, make a copy into a buffer obtained
4233 ** directly from malloc(). The idea is to make it easier for valgrind
4234 ** to spot buffer overreads. */
4236 zCopy
= malloc(bytes
);
4237 memcpy(zCopy
, zSql
, bytes
);
4239 int n
= (int)strlen(zSql
) + 1;
4241 memcpy(zCopy
, zSql
, n
);
4243 rc
= sqlite3_prepare_v2(db
, zCopy
, bytes
, &pStmt
, objc
>=5 ? &zTail
: 0);
4245 zTail
= &zSql
[(zTail
- zCopy
)];
4247 assert(rc
==SQLITE_OK
|| pStmt
==0);
4248 Tcl_ResetResult(interp
);
4249 if( sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
4250 if( rc
==SQLITE_OK
&& zTail
&& objc
>=5 ){
4252 bytes
= bytes
- (int)(zTail
-zSql
);
4254 Tcl_ObjSetVar2(interp
, objv
[4], 0, Tcl_NewStringObj(zTail
, bytes
), 0);
4256 if( rc
!=SQLITE_OK
){
4258 sqlite3_snprintf(sizeof(zBuf
), zBuf
, "(%d) ", rc
);
4259 Tcl_AppendResult(interp
, zBuf
, sqlite3_errmsg(db
), 0);
4264 if( sqlite3TestMakePointerStr(interp
, zBuf
, pStmt
) ) return TCL_ERROR
;
4265 Tcl_AppendResult(interp
, zBuf
, 0);
4271 ** Usage: sqlite3_prepare_tkt3134 DB
4273 ** Generate a prepared statement for a zero-byte string as a test
4274 ** for ticket #3134. The string should be preceded by a zero byte.
4276 static int SQLITE_TCLAPI
test_prepare_tkt3134(
4280 Tcl_Obj
*CONST objv
[]
4283 static const char zSql
[] = "\000SELECT 1";
4284 sqlite3_stmt
*pStmt
= 0;
4289 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4290 Tcl_GetString(objv
[0]), " DB sql bytes tailvar", 0);
4293 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
4294 rc
= sqlite3_prepare_v2(db
, &zSql
[1], 0, &pStmt
, 0);
4295 assert(rc
==SQLITE_OK
|| pStmt
==0);
4296 if( sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
4297 if( rc
!=SQLITE_OK
){
4299 sqlite3_snprintf(sizeof(zBuf
), zBuf
, "(%d) ", rc
);
4300 Tcl_AppendResult(interp
, zBuf
, sqlite3_errmsg(db
), 0);
4305 if( sqlite3TestMakePointerStr(interp
, zBuf
, pStmt
) ) return TCL_ERROR
;
4306 Tcl_AppendResult(interp
, zBuf
, 0);
4312 ** Usage: sqlite3_prepare16 DB sql bytes tailvar
4314 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
4315 ** database handle <DB>. The parameter <tailval> is the name of a global
4316 ** variable that is set to the unused portion of <sql> (if any). A
4317 ** STMT handle is returned.
4319 static int SQLITE_TCLAPI
test_prepare16(
4323 Tcl_Obj
*CONST objv
[]
4325 #ifndef SQLITE_OMIT_UTF16
4328 const void *zTail
= 0;
4330 sqlite3_stmt
*pStmt
= 0;
4333 int bytes
; /* The integer specified as arg 3 */
4334 int objlen
; /* The byte-array length of arg 2 */
4336 if( objc
!=5 && objc
!=4 ){
4337 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4338 Tcl_GetString(objv
[0]), " DB sql bytes ?tailvar?", 0);
4341 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
4342 zSql
= Tcl_GetByteArrayFromObj(objv
[2], &objlen
);
4343 if( Tcl_GetIntFromObj(interp
, objv
[3], &bytes
) ) return TCL_ERROR
;
4345 rc
= sqlite3_prepare16(db
, zSql
, bytes
, &pStmt
, objc
>=5 ? &zTail
: 0);
4346 if( sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
4353 objlen
= objlen
- (int)((u8
*)zTail
-(u8
*)zSql
);
4357 pTail
= Tcl_NewByteArrayObj((u8
*)zTail
, objlen
);
4358 Tcl_IncrRefCount(pTail
);
4359 Tcl_ObjSetVar2(interp
, objv
[4], 0, pTail
, 0);
4360 Tcl_DecrRefCount(pTail
);
4364 if( sqlite3TestMakePointerStr(interp
, zBuf
, pStmt
) ) return TCL_ERROR
;
4366 Tcl_AppendResult(interp
, zBuf
, 0);
4367 #endif /* SQLITE_OMIT_UTF16 */
4372 ** Usage: sqlite3_prepare16_v2 DB sql bytes ?tailvar?
4374 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
4375 ** database handle <DB>. The parameter <tailval> is the name of a global
4376 ** variable that is set to the unused portion of <sql> (if any). A
4377 ** STMT handle is returned.
4379 static int SQLITE_TCLAPI
test_prepare16_v2(
4383 Tcl_Obj
*CONST objv
[]
4385 #ifndef SQLITE_OMIT_UTF16
4388 const void *zTail
= 0;
4390 sqlite3_stmt
*pStmt
= 0;
4393 int bytes
; /* The integer specified as arg 3 */
4394 int objlen
; /* The byte-array length of arg 2 */
4396 if( objc
!=5 && objc
!=4 ){
4397 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4398 Tcl_GetString(objv
[0]), " DB sql bytes ?tailvar?", 0);
4401 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
4402 zSql
= Tcl_GetByteArrayFromObj(objv
[2], &objlen
);
4403 if( Tcl_GetIntFromObj(interp
, objv
[3], &bytes
) ) return TCL_ERROR
;
4405 rc
= sqlite3_prepare16_v2(db
, zSql
, bytes
, &pStmt
, objc
>=5 ? &zTail
: 0);
4406 if( sqlite3TestErrCode(interp
, db
, rc
) ) return TCL_ERROR
;
4413 objlen
= objlen
- (int)((u8
*)zTail
-(u8
*)zSql
);
4417 pTail
= Tcl_NewByteArrayObj((u8
*)zTail
, objlen
);
4418 Tcl_IncrRefCount(pTail
);
4419 Tcl_ObjSetVar2(interp
, objv
[4], 0, pTail
, 0);
4420 Tcl_DecrRefCount(pTail
);
4424 if( sqlite3TestMakePointerStr(interp
, zBuf
, pStmt
) ) return TCL_ERROR
;
4426 Tcl_AppendResult(interp
, zBuf
, 0);
4427 #endif /* SQLITE_OMIT_UTF16 */
4432 ** Usage: sqlite3_open filename ?options-list?
4434 static int SQLITE_TCLAPI
test_open(
4438 Tcl_Obj
*CONST objv
[]
4440 const char *zFilename
;
4444 if( objc
!=3 && objc
!=2 && objc
!=1 ){
4445 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4446 Tcl_GetString(objv
[0]), " filename options-list", 0);
4450 zFilename
= objc
>1 ? Tcl_GetString(objv
[1]) : 0;
4451 sqlite3_open(zFilename
, &db
);
4453 if( sqlite3TestMakePointerStr(interp
, zBuf
, db
) ) return TCL_ERROR
;
4454 Tcl_AppendResult(interp
, zBuf
, 0);
4459 ** Usage: sqlite3_open_v2 FILENAME FLAGS VFS
4461 static int SQLITE_TCLAPI
test_open_v2(
4465 Tcl_Obj
*CONST objv
[]
4467 const char *zFilename
;
4479 Tcl_WrongNumArgs(interp
, 1, objv
, "FILENAME FLAGS VFS");
4482 zFilename
= Tcl_GetString(objv
[1]);
4483 zVfs
= Tcl_GetString(objv
[3]);
4484 if( zVfs
[0]==0x00 ) zVfs
= 0;
4486 rc
= Tcl_ListObjGetElements(interp
, objv
[2], &nFlag
, &apFlag
);
4487 if( rc
!=TCL_OK
) return rc
;
4488 for(i
=0; i
<nFlag
; i
++){
4494 { "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY
},
4495 { "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE
},
4496 { "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE
},
4497 { "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE
},
4498 { "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE
},
4499 { "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY
},
4500 { "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB
},
4501 { "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB
},
4502 { "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB
},
4503 { "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL
},
4504 { "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL
},
4505 { "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL
},
4506 { "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL
},
4507 { "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX
},
4508 { "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX
},
4509 { "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE
},
4510 { "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE
},
4511 { "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL
},
4512 { "SQLITE_OPEN_URI", SQLITE_OPEN_URI
},
4515 rc
= Tcl_GetIndexFromObjStruct(interp
, apFlag
[i
], aFlag
, sizeof(aFlag
[0]),
4518 if( rc
!=TCL_OK
) return rc
;
4519 flags
|= aFlag
[iFlag
].flag
;
4522 rc
= sqlite3_open_v2(zFilename
, &db
, flags
, zVfs
);
4523 if( sqlite3TestMakePointerStr(interp
, zBuf
, db
) ) return TCL_ERROR
;
4524 Tcl_AppendResult(interp
, zBuf
, 0);
4529 ** Usage: sqlite3_open16 filename options
4531 static int SQLITE_TCLAPI
test_open16(
4535 Tcl_Obj
*CONST objv
[]
4537 #ifndef SQLITE_OMIT_UTF16
4538 const void *zFilename
;
4543 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4544 Tcl_GetString(objv
[0]), " filename options-list", 0);
4548 zFilename
= Tcl_GetByteArrayFromObj(objv
[1], 0);
4549 sqlite3_open16(zFilename
, &db
);
4551 if( sqlite3TestMakePointerStr(interp
, zBuf
, db
) ) return TCL_ERROR
;
4552 Tcl_AppendResult(interp
, zBuf
, 0);
4553 #endif /* SQLITE_OMIT_UTF16 */
4558 ** Usage: sqlite3_complete16 <UTF-16 string>
4560 ** Return 1 if the supplied argument is a complete SQL statement, or zero
4563 static int SQLITE_TCLAPI
test_complete16(
4567 Tcl_Obj
*CONST objv
[]
4569 #if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16)
4573 Tcl_WrongNumArgs(interp
, 1, objv
, "<utf-16 sql>");
4577 zBuf
= (char*)Tcl_GetByteArrayFromObj(objv
[1], 0);
4578 Tcl_SetObjResult(interp
, Tcl_NewIntObj(sqlite3_complete16(zBuf
)));
4579 #endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */
4584 ** Usage: sqlite3_normalize SQL
4586 ** Return the normalized value for an SQL statement.
4588 static int SQLITE_TCLAPI
test_normalize(
4592 Tcl_Obj
*CONST objv
[]
4596 extern char *sqlite3_normalize(const char*);
4599 Tcl_WrongNumArgs(interp
, 1, objv
, "SQL");
4603 zSql
= (char*)Tcl_GetString(objv
[1]);
4604 zNorm
= sqlite3_normalize(zSql
);
4606 Tcl_SetObjResult(interp
, Tcl_NewStringObj(zNorm
, -1));
4607 sqlite3_free(zNorm
);
4613 ** Usage: sqlite3_step STMT
4615 ** Advance the statement to the next row.
4617 static int SQLITE_TCLAPI
test_step(
4621 Tcl_Obj
*CONST objv
[]
4623 sqlite3_stmt
*pStmt
;
4627 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4628 Tcl_GetString(objv
[0]), " STMT", 0);
4632 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
4633 rc
= sqlite3_step(pStmt
);
4635 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
4636 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), 0);
4640 static int SQLITE_TCLAPI
test_sql(
4644 Tcl_Obj
*CONST objv
[]
4646 sqlite3_stmt
*pStmt
;
4649 Tcl_WrongNumArgs(interp
, 1, objv
, "STMT");
4653 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
4654 Tcl_SetResult(interp
, (char *)sqlite3_sql(pStmt
), TCL_VOLATILE
);
4657 static int SQLITE_TCLAPI
test_ex_sql(
4661 Tcl_Obj
*CONST objv
[]
4663 sqlite3_stmt
*pStmt
;
4667 Tcl_WrongNumArgs(interp
, 1, objv
, "STMT");
4671 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
4672 z
= sqlite3_expanded_sql(pStmt
);
4673 Tcl_SetResult(interp
, z
, TCL_VOLATILE
);
4679 ** Usage: sqlite3_column_count STMT
4681 ** Return the number of columns returned by the sql statement STMT.
4683 static int SQLITE_TCLAPI
test_column_count(
4687 Tcl_Obj
*CONST objv
[]
4689 sqlite3_stmt
*pStmt
;
4692 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4693 Tcl_GetString(objv
[0]), " STMT column", 0);
4697 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
4699 Tcl_SetObjResult(interp
, Tcl_NewIntObj(sqlite3_column_count(pStmt
)));
4704 ** Usage: sqlite3_column_type STMT column
4706 ** Return the type of the data in column 'column' of the current row.
4708 static int SQLITE_TCLAPI
test_column_type(
4712 Tcl_Obj
*CONST objv
[]
4714 sqlite3_stmt
*pStmt
;
4719 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4720 Tcl_GetString(objv
[0]), " STMT column", 0);
4724 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
4725 if( Tcl_GetIntFromObj(interp
, objv
[2], &col
) ) return TCL_ERROR
;
4727 tp
= sqlite3_column_type(pStmt
, col
);
4729 case SQLITE_INTEGER
:
4730 Tcl_SetResult(interp
, "INTEGER", TCL_STATIC
);
4733 Tcl_SetResult(interp
, "NULL", TCL_STATIC
);
4736 Tcl_SetResult(interp
, "FLOAT", TCL_STATIC
);
4739 Tcl_SetResult(interp
, "TEXT", TCL_STATIC
);
4742 Tcl_SetResult(interp
, "BLOB", TCL_STATIC
);
4752 ** Usage: sqlite3_column_int64 STMT column
4754 ** Return the data in column 'column' of the current row cast as an
4755 ** wide (64-bit) integer.
4757 static int SQLITE_TCLAPI
test_column_int64(
4761 Tcl_Obj
*CONST objv
[]
4763 sqlite3_stmt
*pStmt
;
4768 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4769 Tcl_GetString(objv
[0]), " STMT column", 0);
4773 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
4774 if( Tcl_GetIntFromObj(interp
, objv
[2], &col
) ) return TCL_ERROR
;
4776 iVal
= sqlite3_column_int64(pStmt
, col
);
4777 Tcl_SetObjResult(interp
, Tcl_NewWideIntObj(iVal
));
4782 ** Usage: sqlite3_column_blob STMT column
4784 static int SQLITE_TCLAPI
test_column_blob(
4788 Tcl_Obj
*CONST objv
[]
4790 sqlite3_stmt
*pStmt
;
4797 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4798 Tcl_GetString(objv
[0]), " STMT column", 0);
4802 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
4803 if( Tcl_GetIntFromObj(interp
, objv
[2], &col
) ) return TCL_ERROR
;
4805 len
= sqlite3_column_bytes(pStmt
, col
);
4806 pBlob
= sqlite3_column_blob(pStmt
, col
);
4807 Tcl_SetObjResult(interp
, Tcl_NewByteArrayObj(pBlob
, len
));
4812 ** Usage: sqlite3_column_double STMT column
4814 ** Return the data in column 'column' of the current row cast as a double.
4816 static int SQLITE_TCLAPI
test_column_double(
4820 Tcl_Obj
*CONST objv
[]
4822 sqlite3_stmt
*pStmt
;
4827 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4828 Tcl_GetString(objv
[0]), " STMT column", 0);
4832 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
4833 if( Tcl_GetIntFromObj(interp
, objv
[2], &col
) ) return TCL_ERROR
;
4835 rVal
= sqlite3_column_double(pStmt
, col
);
4836 Tcl_SetObjResult(interp
, Tcl_NewDoubleObj(rVal
));
4841 ** Usage: sqlite3_data_count STMT
4843 ** Return the number of columns returned by the sql statement STMT.
4845 static int SQLITE_TCLAPI
test_data_count(
4849 Tcl_Obj
*CONST objv
[]
4851 sqlite3_stmt
*pStmt
;
4854 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4855 Tcl_GetString(objv
[0]), " STMT column", 0);
4859 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
4861 Tcl_SetObjResult(interp
, Tcl_NewIntObj(sqlite3_data_count(pStmt
)));
4866 ** Usage: sqlite3_column_text STMT column
4868 ** Usage: sqlite3_column_decltype STMT column
4870 ** Usage: sqlite3_column_name STMT column
4872 static int SQLITE_TCLAPI
test_stmt_utf8(
4873 void * clientData
, /* Pointer to SQLite API function to be invoke */
4876 Tcl_Obj
*CONST objv
[]
4878 sqlite3_stmt
*pStmt
;
4880 const char *(*xFunc
)(sqlite3_stmt
*, int);
4883 xFunc
= (const char *(*)(sqlite3_stmt
*, int))clientData
;
4885 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4886 Tcl_GetString(objv
[0]), " STMT column", 0);
4890 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
4891 if( Tcl_GetIntFromObj(interp
, objv
[2], &col
) ) return TCL_ERROR
;
4892 zRet
= xFunc(pStmt
, col
);
4894 Tcl_SetResult(interp
, (char *)zRet
, 0);
4899 static int SQLITE_TCLAPI
test_global_recover(
4903 Tcl_Obj
*CONST objv
[]
4905 #ifndef SQLITE_OMIT_DEPRECATED
4908 Tcl_WrongNumArgs(interp
, 1, objv
, "");
4911 rc
= sqlite3_global_recover();
4912 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), TCL_STATIC
);
4918 ** Usage: sqlite3_column_text STMT column
4920 ** Usage: sqlite3_column_decltype STMT column
4922 ** Usage: sqlite3_column_name STMT column
4924 static int SQLITE_TCLAPI
test_stmt_utf16(
4925 void * clientData
, /* Pointer to SQLite API function to be invoked */
4928 Tcl_Obj
*CONST objv
[]
4930 #ifndef SQLITE_OMIT_UTF16
4931 sqlite3_stmt
*pStmt
;
4934 const void *zName16
;
4935 const void *(*xFunc
)(sqlite3_stmt
*, int);
4937 xFunc
= (const void *(*)(sqlite3_stmt
*, int))clientData
;
4939 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4940 Tcl_GetString(objv
[0]), " STMT column", 0);
4944 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
4945 if( Tcl_GetIntFromObj(interp
, objv
[2], &col
) ) return TCL_ERROR
;
4947 zName16
= xFunc(pStmt
, col
);
4950 const char *z
= zName16
;
4951 for(n
=0; z
[n
] || z
[n
+1]; n
+=2){}
4952 pRet
= Tcl_NewByteArrayObj(zName16
, n
+2);
4953 Tcl_SetObjResult(interp
, pRet
);
4955 #endif /* SQLITE_OMIT_UTF16 */
4961 ** Usage: sqlite3_column_int STMT column
4963 ** Usage: sqlite3_column_bytes STMT column
4965 ** Usage: sqlite3_column_bytes16 STMT column
4968 static int SQLITE_TCLAPI
test_stmt_int(
4969 void * clientData
, /* Pointer to SQLite API function to be invoked */
4972 Tcl_Obj
*CONST objv
[]
4974 sqlite3_stmt
*pStmt
;
4976 int (*xFunc
)(sqlite3_stmt
*, int);
4978 xFunc
= (int (*)(sqlite3_stmt
*, int))clientData
;
4980 Tcl_AppendResult(interp
, "wrong # args: should be \"",
4981 Tcl_GetString(objv
[0]), " STMT column", 0);
4985 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
4986 if( Tcl_GetIntFromObj(interp
, objv
[2], &col
) ) return TCL_ERROR
;
4988 Tcl_SetObjResult(interp
, Tcl_NewIntObj(xFunc(pStmt
, col
)));
4993 ** Usage: sqlite_set_magic DB MAGIC-NUMBER
4995 ** Set the db->magic value. This is used to test error recovery logic.
4997 static int SQLITE_TCLAPI
sqlite_set_magic(
5005 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
5009 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
5010 if( strcmp(argv
[2], "SQLITE_MAGIC_OPEN")==0 ){
5011 db
->magic
= SQLITE_MAGIC_OPEN
;
5012 }else if( strcmp(argv
[2], "SQLITE_MAGIC_CLOSED")==0 ){
5013 db
->magic
= SQLITE_MAGIC_CLOSED
;
5014 }else if( strcmp(argv
[2], "SQLITE_MAGIC_BUSY")==0 ){
5015 db
->magic
= SQLITE_MAGIC_BUSY
;
5016 }else if( strcmp(argv
[2], "SQLITE_MAGIC_ERROR")==0 ){
5017 db
->magic
= SQLITE_MAGIC_ERROR
;
5018 }else if( Tcl_GetInt(interp
, argv
[2], (int*)&db
->magic
) ){
5025 ** Usage: sqlite3_interrupt DB
5027 ** Trigger an interrupt on DB
5029 static int SQLITE_TCLAPI
test_interrupt(
5037 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0], " DB", 0);
5040 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
5041 sqlite3_interrupt(db
);
5046 ** Usage: sqlite_delete_function DB function-name
5048 ** Delete the user function 'function-name' from database handle DB. It
5049 ** is assumed that the user function was created as UTF8, any number of
5050 ** arguments (the way the TCL interface does it).
5052 static int SQLITE_TCLAPI
delete_function(
5061 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
5062 " DB function-name", 0);
5065 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
5066 rc
= sqlite3_create_function(db
, argv
[2], -1, SQLITE_UTF8
, 0, 0, 0, 0);
5067 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), TCL_STATIC
);
5072 ** Usage: sqlite_delete_collation DB collation-name
5074 ** Delete the collation sequence 'collation-name' from database handle
5075 ** DB. It is assumed that the collation sequence was created as UTF8 (the
5076 ** way the TCL interface does it).
5078 static int SQLITE_TCLAPI
delete_collation(
5087 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
5088 " DB function-name", 0);
5091 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
5092 rc
= sqlite3_create_collation(db
, argv
[2], SQLITE_UTF8
, 0, 0);
5093 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), TCL_STATIC
);
5098 ** Usage: sqlite3_get_autocommit DB
5100 ** Return true if the database DB is currently in auto-commit mode.
5101 ** Return false if not.
5103 static int SQLITE_TCLAPI
get_autocommit(
5112 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
5116 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
5117 sqlite3_snprintf(sizeof(zBuf
), zBuf
, "%d", sqlite3_get_autocommit(db
));
5118 Tcl_AppendResult(interp
, zBuf
, 0);
5123 ** Usage: sqlite3_busy_timeout DB MS
5125 ** Set the busy timeout. This is more easily done using the timeout
5126 ** method of the TCL interface. But we need a way to test the case
5127 ** where it returns SQLITE_MISUSE.
5129 static int SQLITE_TCLAPI
test_busy_timeout(
5138 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
5142 if( getDbPointer(interp
, argv
[1], &db
) ) return TCL_ERROR
;
5143 if( Tcl_GetInt(interp
, argv
[2], &ms
) ) return TCL_ERROR
;
5144 rc
= sqlite3_busy_timeout(db
, ms
);
5145 Tcl_AppendResult(interp
, sqlite3ErrName(rc
), 0);
5150 ** Usage: tcl_variable_type VARIABLENAME
5152 ** Return the name of the internal representation for the
5153 ** value of the given variable.
5155 static int SQLITE_TCLAPI
tcl_variable_type(
5159 Tcl_Obj
*CONST objv
[]
5163 Tcl_WrongNumArgs(interp
, 1, objv
, "VARIABLE");
5166 pVar
= Tcl_GetVar2Ex(interp
, Tcl_GetString(objv
[1]), 0, TCL_LEAVE_ERR_MSG
);
5167 if( pVar
==0 ) return TCL_ERROR
;
5168 if( pVar
->typePtr
){
5169 Tcl_SetObjResult(interp
, Tcl_NewStringObj(pVar
->typePtr
->name
, -1));
5175 ** Usage: sqlite3_release_memory ?N?
5177 ** Attempt to release memory currently held but not actually required.
5178 ** The integer N is the number of bytes we are trying to release. The
5179 ** return value is the amount of memory actually released.
5181 static int SQLITE_TCLAPI
test_release_memory(
5185 Tcl_Obj
*CONST objv
[]
5187 #if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
5190 if( objc
!=1 && objc
!=2 ){
5191 Tcl_WrongNumArgs(interp
, 1, objv
, "?N?");
5195 if( Tcl_GetIntFromObj(interp
, objv
[1], &N
) ) return TCL_ERROR
;
5199 amt
= sqlite3_release_memory(N
);
5200 Tcl_SetObjResult(interp
, Tcl_NewIntObj(amt
));
5207 ** Usage: sqlite3_db_release_memory DB
5209 ** Attempt to release memory currently held by database DB. Return the
5210 ** result code (which in the current implementation is always zero).
5212 static int SQLITE_TCLAPI
test_db_release_memory(
5216 Tcl_Obj
*CONST objv
[]
5221 Tcl_WrongNumArgs(interp
, 1, objv
, "DB");
5224 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
5225 rc
= sqlite3_db_release_memory(db
);
5226 Tcl_SetObjResult(interp
, Tcl_NewIntObj(rc
));
5231 ** Usage: sqlite3_db_cacheflush DB
5233 ** Attempt to flush any dirty pages to disk.
5235 static int SQLITE_TCLAPI
test_db_cacheflush(
5239 Tcl_Obj
*CONST objv
[]
5244 Tcl_WrongNumArgs(interp
, 1, objv
, "DB");
5247 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
5248 rc
= sqlite3_db_cacheflush(db
);
5250 Tcl_SetResult(interp
, (char *)sqlite3ErrStr(rc
), TCL_STATIC
);
5254 Tcl_ResetResult(interp
);
5259 ** Usage: sqlite3_system_errno DB
5261 ** Return the low-level system errno value.
5263 static int SQLITE_TCLAPI
test_system_errno(
5267 Tcl_Obj
*CONST objv
[]
5272 Tcl_WrongNumArgs(interp
, 1, objv
, "DB");
5275 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
5276 iErrno
= sqlite3_system_errno(db
);
5277 Tcl_SetObjResult(interp
, Tcl_NewIntObj(iErrno
));
5282 ** Usage: sqlite3_db_filename DB DBNAME
5284 ** Return the name of a file associated with a database.
5286 static int SQLITE_TCLAPI
test_db_filename(
5290 Tcl_Obj
*CONST objv
[]
5293 const char *zDbName
;
5295 Tcl_WrongNumArgs(interp
, 1, objv
, "DB DBNAME");
5298 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
5299 zDbName
= Tcl_GetString(objv
[2]);
5300 Tcl_AppendResult(interp
, sqlite3_db_filename(db
, zDbName
), (void*)0);
5305 ** Usage: sqlite3_db_readonly DB DBNAME
5307 ** Return 1 or 0 if DBNAME is readonly or not. Return -1 if DBNAME does
5310 static int SQLITE_TCLAPI
test_db_readonly(
5314 Tcl_Obj
*CONST objv
[]
5317 const char *zDbName
;
5319 Tcl_WrongNumArgs(interp
, 1, objv
, "DB DBNAME");
5322 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
5323 zDbName
= Tcl_GetString(objv
[2]);
5324 Tcl_SetObjResult(interp
, Tcl_NewIntObj(sqlite3_db_readonly(db
, zDbName
)));
5329 ** Usage: sqlite3_soft_heap_limit ?N?
5331 ** Query or set the soft heap limit for the current thread. The
5332 ** limit is only changed if the N is present. The previous limit
5335 static int SQLITE_TCLAPI
test_soft_heap_limit(
5339 Tcl_Obj
*CONST objv
[]
5343 if( objc
!=1 && objc
!=2 ){
5344 Tcl_WrongNumArgs(interp
, 1, objv
, "?N?");
5348 if( Tcl_GetWideIntFromObj(interp
, objv
[1], &N
) ) return TCL_ERROR
;
5350 amt
= sqlite3_soft_heap_limit64(N
);
5351 Tcl_SetObjResult(interp
, Tcl_NewWideIntObj(amt
));
5356 ** Usage: sqlite3_thread_cleanup
5358 ** Call the sqlite3_thread_cleanup API.
5360 static int SQLITE_TCLAPI
test_thread_cleanup(
5364 Tcl_Obj
*CONST objv
[]
5366 #ifndef SQLITE_OMIT_DEPRECATED
5367 sqlite3_thread_cleanup();
5373 ** Usage: sqlite3_pager_refcounts DB
5375 ** Return a list of numbers which are the PagerRefcount for all
5376 ** pagers on each database connection.
5378 static int SQLITE_TCLAPI
test_pager_refcounts(
5382 Tcl_Obj
*CONST objv
[]
5390 Tcl_AppendResult(interp
, "wrong # args: should be \"",
5391 Tcl_GetStringFromObj(objv
[0], 0), " DB", 0);
5394 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
5395 pResult
= Tcl_NewObj();
5396 for(i
=0; i
<db
->nDb
; i
++){
5397 if( db
->aDb
[i
].pBt
==0 ){
5400 sqlite3_mutex_enter(db
->mutex
);
5401 a
= sqlite3PagerStats(sqlite3BtreePager(db
->aDb
[i
].pBt
));
5403 sqlite3_mutex_leave(db
->mutex
);
5405 Tcl_ListObjAppendElement(0, pResult
, Tcl_NewIntObj(v
));
5407 Tcl_SetObjResult(interp
, pResult
);
5413 ** tclcmd: working_64bit_int
5415 ** Some TCL builds (ex: cygwin) do not support 64-bit integers. This
5416 ** leads to a number of test failures. The present command checks the
5417 ** TCL build to see whether or not it supports 64-bit integers. It
5418 ** returns TRUE if it does and FALSE if not.
5420 ** This command is used to warn users that their TCL build is defective
5421 ** and that the errors they are seeing in the test scripts might be
5422 ** a result of their defective TCL rather than problems in SQLite.
5424 static int SQLITE_TCLAPI
working_64bit_int(
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 */
5433 pTestObj
= Tcl_NewWideIntObj(1000000*(i64
)1234567890);
5434 working
= strcmp(Tcl_GetString(pTestObj
), "1234567890000000")==0;
5435 Tcl_DecrRefCount(pTestObj
);
5436 Tcl_SetObjResult(interp
, Tcl_NewBooleanObj(working
));
5442 ** tclcmd: vfs_unlink_test
5444 ** This TCL command unregisters the primary VFS and then registers
5445 ** it back again. This is used to test the ability to register a
5446 ** VFS when none are previously registered, and the ability to
5447 ** unregister the only available VFS. Ticket #2738
5449 static int SQLITE_TCLAPI
vfs_unlink_test(
5450 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
5451 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
5452 int objc
, /* Number of arguments */
5453 Tcl_Obj
*CONST objv
[] /* Command arguments */
5457 sqlite3_vfs
*apVfs
[20];
5458 sqlite3_vfs one
, two
;
5460 sqlite3_vfs_unregister(0); /* Unregister of NULL is harmless */
5461 one
.zName
= "__one";
5462 two
.zName
= "__two";
5464 /* Calling sqlite3_vfs_register with 2nd argument of 0 does not
5465 ** change the default VFS
5467 pMain
= sqlite3_vfs_find(0);
5468 sqlite3_vfs_register(&one
, 0);
5469 assert( pMain
==0 || pMain
==sqlite3_vfs_find(0) );
5470 sqlite3_vfs_register(&two
, 0);
5471 assert( pMain
==0 || pMain
==sqlite3_vfs_find(0) );
5473 /* We can find a VFS by its name */
5474 assert( sqlite3_vfs_find("__one")==&one
);
5475 assert( sqlite3_vfs_find("__two")==&two
);
5477 /* Calling sqlite_vfs_register with non-zero second parameter changes the
5478 ** default VFS, even if the 1st parameter is an existig VFS that is
5479 ** previously registered as the non-default.
5481 sqlite3_vfs_register(&one
, 1);
5482 assert( sqlite3_vfs_find("__one")==&one
);
5483 assert( sqlite3_vfs_find("__two")==&two
);
5484 assert( sqlite3_vfs_find(0)==&one
);
5485 sqlite3_vfs_register(&two
, 1);
5486 assert( sqlite3_vfs_find("__one")==&one
);
5487 assert( sqlite3_vfs_find("__two")==&two
);
5488 assert( sqlite3_vfs_find(0)==&two
);
5490 sqlite3_vfs_register(pMain
, 1);
5491 assert( sqlite3_vfs_find("__one")==&one
);
5492 assert( sqlite3_vfs_find("__two")==&two
);
5493 assert( sqlite3_vfs_find(0)==pMain
);
5496 /* Unlink the default VFS. Repeat until there are no more VFSes
5499 for(i
=0; i
<sizeof(apVfs
)/sizeof(apVfs
[0]); i
++){
5500 apVfs
[i
] = sqlite3_vfs_find(0);
5502 assert( apVfs
[i
]==sqlite3_vfs_find(apVfs
[i
]->zName
) );
5503 sqlite3_vfs_unregister(apVfs
[i
]);
5504 assert( 0==sqlite3_vfs_find(apVfs
[i
]->zName
) );
5507 assert( 0==sqlite3_vfs_find(0) );
5509 /* Register the main VFS as non-default (will be made default, since
5510 ** it'll be the only one in existence).
5512 sqlite3_vfs_register(pMain
, 0);
5513 assert( sqlite3_vfs_find(0)==pMain
);
5515 /* Un-register the main VFS again to restore an empty VFS list */
5516 sqlite3_vfs_unregister(pMain
);
5517 assert( 0==sqlite3_vfs_find(0) );
5519 /* Relink all VFSes in reverse order. */
5520 for(i
=sizeof(apVfs
)/sizeof(apVfs
[0])-1; i
>=0; i
--){
5522 sqlite3_vfs_register(apVfs
[i
], 1);
5523 assert( apVfs
[i
]==sqlite3_vfs_find(0) );
5524 assert( apVfs
[i
]==sqlite3_vfs_find(apVfs
[i
]->zName
) );
5528 /* Unregister out sample VFSes. */
5529 sqlite3_vfs_unregister(&one
);
5530 sqlite3_vfs_unregister(&two
);
5532 /* Unregistering a VFS that is not currently registered is harmless */
5533 sqlite3_vfs_unregister(&one
);
5534 sqlite3_vfs_unregister(&two
);
5535 assert( sqlite3_vfs_find("__one")==0 );
5536 assert( sqlite3_vfs_find("__two")==0 );
5538 /* We should be left with the original default VFS back as the
5540 assert( sqlite3_vfs_find(0)==pMain
);
5546 ** tclcmd: vfs_initfail_test
5548 ** This TCL command attempts to vfs_find and vfs_register when the
5549 ** sqlite3_initialize() interface is failing. All calls should fail.
5551 static int SQLITE_TCLAPI
vfs_initfail_test(
5552 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
5553 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
5554 int objc
, /* Number of arguments */
5555 Tcl_Obj
*CONST objv
[] /* Command arguments */
5558 one
.zName
= "__one";
5560 if( sqlite3_vfs_find(0) ) return TCL_ERROR
;
5561 sqlite3_vfs_register(&one
, 0);
5562 if( sqlite3_vfs_find(0) ) return TCL_ERROR
;
5563 sqlite3_vfs_register(&one
, 1);
5564 if( sqlite3_vfs_find(0) ) return TCL_ERROR
;
5571 static sqlite3_vfs
*apVfs
[20];
5572 static int nVfs
= 0;
5575 ** tclcmd: vfs_unregister_all
5577 ** Unregister all VFSes.
5579 static int SQLITE_TCLAPI
vfs_unregister_all(
5580 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
5581 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
5582 int objc
, /* Number of arguments */
5583 Tcl_Obj
*CONST objv
[] /* Command arguments */
5586 for(i
=0; i
<ArraySize(apVfs
); i
++){
5587 apVfs
[i
] = sqlite3_vfs_find(0);
5588 if( apVfs
[i
]==0 ) break;
5589 sqlite3_vfs_unregister(apVfs
[i
]);
5595 ** tclcmd: vfs_reregister_all
5597 ** Restore all VFSes that were removed using vfs_unregister_all. Taking
5598 ** care to put the linked list back together in the same order as it was
5599 ** in before vfs_unregister_all was invoked.
5601 static int SQLITE_TCLAPI
vfs_reregister_all(
5602 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
5603 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
5604 int objc
, /* Number of arguments */
5605 Tcl_Obj
*CONST objv
[] /* Command arguments */
5608 for(i
=nVfs
-1; i
>=0; i
--){
5609 sqlite3_vfs_register(apVfs
[i
], 1);
5616 ** tclcmd: file_control_test DB
5618 ** This TCL command runs the sqlite3_file_control interface and
5619 ** verifies correct operation of the same.
5621 static int SQLITE_TCLAPI
file_control_test(
5622 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
5623 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
5624 int objc
, /* Number of arguments */
5625 Tcl_Obj
*CONST objv
[] /* Command arguments */
5632 Tcl_AppendResult(interp
, "wrong # args: should be \"",
5633 Tcl_GetStringFromObj(objv
[0], 0), " DB", 0);
5636 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
5637 rc
= sqlite3_file_control(db
, 0, 0, &iArg
);
5638 assert( rc
==SQLITE_NOTFOUND
);
5639 rc
= sqlite3_file_control(db
, "notadatabase", SQLITE_FCNTL_LOCKSTATE
, &iArg
);
5640 assert( rc
==SQLITE_ERROR
);
5641 rc
= sqlite3_file_control(db
, "main", -1, &iArg
);
5642 assert( rc
==SQLITE_NOTFOUND
);
5643 rc
= sqlite3_file_control(db
, "temp", -1, &iArg
);
5644 assert( rc
==SQLITE_NOTFOUND
|| rc
==SQLITE_ERROR
);
5651 ** tclcmd: file_control_lasterrno_test DB
5653 ** This TCL command runs the sqlite3_file_control interface and
5654 ** verifies correct operation of the SQLITE_LAST_ERRNO verb.
5656 static int SQLITE_TCLAPI
file_control_lasterrno_test(
5657 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
5658 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
5659 int objc
, /* Number of arguments */
5660 Tcl_Obj
*CONST objv
[] /* Command arguments */
5667 Tcl_AppendResult(interp
, "wrong # args: should be \"",
5668 Tcl_GetStringFromObj(objv
[0], 0), " DB", 0);
5671 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ){
5674 rc
= sqlite3_file_control(db
, NULL
, SQLITE_LAST_ERRNO
, &iArg
);
5676 Tcl_SetObjResult(interp
, Tcl_NewIntObj(rc
));
5680 Tcl_AppendResult(interp
, "Unexpected non-zero errno: ",
5681 Tcl_GetStringFromObj(Tcl_NewIntObj(iArg
), 0), " ", 0);
5688 ** tclcmd: file_control_chunksize_test DB DBNAME SIZE
5690 ** This TCL command runs the sqlite3_file_control interface and
5691 ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
5692 ** SQLITE_SET_LOCKPROXYFILE verbs.
5694 static int SQLITE_TCLAPI
file_control_chunksize_test(
5695 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
5696 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
5697 int objc
, /* Number of arguments */
5698 Tcl_Obj
*CONST objv
[] /* Command arguments */
5700 int nSize
; /* New chunk size */
5701 char *zDb
; /* Db name ("main", "temp" etc.) */
5702 sqlite3
*db
; /* Database handle */
5703 int rc
; /* file_control() return code */
5706 Tcl_WrongNumArgs(interp
, 1, objv
, "DB DBNAME SIZE");
5709 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
)
5710 || Tcl_GetIntFromObj(interp
, objv
[3], &nSize
)
5714 zDb
= Tcl_GetString(objv
[2]);
5715 if( zDb
[0]=='\0' ) zDb
= NULL
;
5717 rc
= sqlite3_file_control(db
, zDb
, SQLITE_FCNTL_CHUNK_SIZE
, (void *)&nSize
);
5719 Tcl_SetResult(interp
, (char *)sqlite3ErrName(rc
), TCL_STATIC
);
5726 ** tclcmd: file_control_sizehint_test DB DBNAME SIZE
5728 ** This TCL command runs the sqlite3_file_control interface
5729 ** with SQLITE_FCNTL_SIZE_HINT
5731 static int SQLITE_TCLAPI
file_control_sizehint_test(
5732 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
5733 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
5734 int objc
, /* Number of arguments */
5735 Tcl_Obj
*CONST objv
[] /* Command arguments */
5737 Tcl_WideInt nSize
; /* Hinted size */
5738 char *zDb
; /* Db name ("main", "temp" etc.) */
5739 sqlite3
*db
; /* Database handle */
5740 int rc
; /* file_control() return code */
5743 Tcl_WrongNumArgs(interp
, 1, objv
, "DB DBNAME SIZE");
5746 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
)
5747 || Tcl_GetWideIntFromObj(interp
, objv
[3], &nSize
)
5751 zDb
= Tcl_GetString(objv
[2]);
5752 if( zDb
[0]=='\0' ) zDb
= NULL
;
5754 rc
= sqlite3_file_control(db
, zDb
, SQLITE_FCNTL_SIZE_HINT
, (void *)&nSize
);
5756 Tcl_SetResult(interp
, (char *)sqlite3ErrName(rc
), TCL_STATIC
);
5763 ** tclcmd: file_control_lockproxy_test DB PWD
5765 ** This TCL command runs the sqlite3_file_control interface and
5766 ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
5767 ** SQLITE_SET_LOCKPROXYFILE verbs.
5769 static int SQLITE_TCLAPI
file_control_lockproxy_test(
5770 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
5771 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
5772 int objc
, /* Number of arguments */
5773 Tcl_Obj
*CONST objv
[] /* Command arguments */
5778 Tcl_AppendResult(interp
, "wrong # args: should be \"",
5779 Tcl_GetStringFromObj(objv
[0], 0), " DB PWD", 0);
5782 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ){
5786 #if !defined(SQLITE_ENABLE_LOCKING_STYLE)
5787 # if defined(__APPLE__)
5788 # define SQLITE_ENABLE_LOCKING_STYLE 1
5790 # define SQLITE_ENABLE_LOCKING_STYLE 0
5793 #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
5799 char proxyPath
[400];
5801 zPwd
= Tcl_GetStringFromObj(objv
[2], &nPwd
);
5802 if( sizeof(proxyPath
)<nPwd
+20 ){
5803 Tcl_AppendResult(interp
, "PWD too big", (void*)0);
5806 sqlite3_snprintf(sizeof(proxyPath
), proxyPath
, "%s/test.proxy", zPwd
);
5807 rc
= sqlite3_file_control(db
, NULL
, SQLITE_SET_LOCKPROXYFILE
, proxyPath
);
5809 Tcl_SetObjResult(interp
, Tcl_NewIntObj(rc
));
5812 rc
= sqlite3_file_control(db
, NULL
, SQLITE_GET_LOCKPROXYFILE
, &testPath
);
5813 if( strncmp(proxyPath
,testPath
,11) ){
5814 Tcl_AppendResult(interp
, "Lock proxy file did not match the "
5815 "previously assigned value", 0);
5819 Tcl_SetObjResult(interp
, Tcl_NewIntObj(rc
));
5822 rc
= sqlite3_file_control(db
, NULL
, SQLITE_SET_LOCKPROXYFILE
, proxyPath
);
5824 Tcl_SetObjResult(interp
, Tcl_NewIntObj(rc
));
5834 ** tclcmd: file_control_win32_av_retry DB NRETRY DELAY
5836 ** This TCL command runs the sqlite3_file_control interface with
5837 ** the SQLITE_FCNTL_WIN32_AV_RETRY opcode.
5839 static int SQLITE_TCLAPI
file_control_win32_av_retry(
5840 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
5841 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
5842 int objc
, /* Number of arguments */
5843 Tcl_Obj
*CONST objv
[] /* Command arguments */
5851 Tcl_AppendResult(interp
, "wrong # args: should be \"",
5852 Tcl_GetStringFromObj(objv
[0], 0), " DB NRETRY DELAY", 0);
5855 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ){
5858 if( Tcl_GetIntFromObj(interp
, objv
[2], &a
[0]) ) return TCL_ERROR
;
5859 if( Tcl_GetIntFromObj(interp
, objv
[3], &a
[1]) ) return TCL_ERROR
;
5860 rc
= sqlite3_file_control(db
, NULL
, SQLITE_FCNTL_WIN32_AV_RETRY
, (void*)a
);
5861 sqlite3_snprintf(sizeof(z
), z
, "%d %d %d", rc
, a
[0], a
[1]);
5862 Tcl_AppendResult(interp
, z
, (char*)0);
5867 ** tclcmd: file_control_win32_get_handle DB
5869 ** This TCL command runs the sqlite3_file_control interface with
5870 ** the SQLITE_FCNTL_WIN32_GET_HANDLE opcode.
5872 static int file_control_win32_get_handle(
5873 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
5874 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
5875 int objc
, /* Number of arguments */
5876 Tcl_Obj
*CONST objv
[] /* Command arguments */
5880 HANDLE hFile
= NULL
;
5884 Tcl_AppendResult(interp
, "wrong # args: should be \"",
5885 Tcl_GetStringFromObj(objv
[0], 0), " DB", 0);
5888 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ){
5891 rc
= sqlite3_file_control(db
, NULL
, SQLITE_FCNTL_WIN32_GET_HANDLE
,
5893 sqlite3_snprintf(sizeof(z
), z
, "%d %p", rc
, (void*)hFile
);
5894 Tcl_AppendResult(interp
, z
, (char*)0);
5899 ** tclcmd: file_control_win32_set_handle DB HANDLE
5901 ** This TCL command runs the sqlite3_file_control interface with
5902 ** the SQLITE_FCNTL_WIN32_SET_HANDLE opcode.
5904 static int SQLITE_TCLAPI
file_control_win32_set_handle(
5905 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
5906 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
5907 int objc
, /* Number of arguments */
5908 Tcl_Obj
*CONST objv
[] /* Command arguments */
5912 HANDLE hFile
= NULL
;
5916 Tcl_AppendResult(interp
, "wrong # args: should be \"",
5917 Tcl_GetStringFromObj(objv
[0], 0), " DB HANDLE", 0);
5920 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ){
5923 if( getWin32Handle(interp
, Tcl_GetString(objv
[2]), &hFile
) ){
5926 rc
= sqlite3_file_control(db
, NULL
, SQLITE_FCNTL_WIN32_SET_HANDLE
,
5928 sqlite3_snprintf(sizeof(z
), z
, "%d %p", rc
, (void*)hFile
);
5929 Tcl_AppendResult(interp
, z
, (char*)0);
5935 ** tclcmd: file_control_persist_wal DB PERSIST-FLAG
5937 ** This TCL command runs the sqlite3_file_control interface with
5938 ** the SQLITE_FCNTL_PERSIST_WAL opcode.
5940 static int SQLITE_TCLAPI
file_control_persist_wal(
5941 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
5942 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
5943 int objc
, /* Number of arguments */
5944 Tcl_Obj
*CONST objv
[] /* Command arguments */
5952 Tcl_AppendResult(interp
, "wrong # args: should be \"",
5953 Tcl_GetStringFromObj(objv
[0], 0), " DB FLAG", 0);
5956 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ){
5959 if( Tcl_GetIntFromObj(interp
, objv
[2], &bPersist
) ) return TCL_ERROR
;
5960 rc
= sqlite3_file_control(db
, NULL
, SQLITE_FCNTL_PERSIST_WAL
, (void*)&bPersist
);
5961 sqlite3_snprintf(sizeof(z
), z
, "%d %d", rc
, bPersist
);
5962 Tcl_AppendResult(interp
, z
, (char*)0);
5967 ** tclcmd: file_control_powersafe_overwrite DB PSOW-FLAG
5969 ** This TCL command runs the sqlite3_file_control interface with
5970 ** the SQLITE_FCNTL_POWERSAFE_OVERWRITE opcode.
5972 static int SQLITE_TCLAPI
file_control_powersafe_overwrite(
5973 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
5974 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
5975 int objc
, /* Number of arguments */
5976 Tcl_Obj
*CONST objv
[] /* Command arguments */
5984 Tcl_AppendResult(interp
, "wrong # args: should be \"",
5985 Tcl_GetStringFromObj(objv
[0], 0), " DB FLAG", 0);
5988 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ){
5991 if( Tcl_GetIntFromObj(interp
, objv
[2], &b
) ) return TCL_ERROR
;
5992 rc
= sqlite3_file_control(db
,NULL
,SQLITE_FCNTL_POWERSAFE_OVERWRITE
,(void*)&b
);
5993 sqlite3_snprintf(sizeof(z
), z
, "%d %d", rc
, b
);
5994 Tcl_AppendResult(interp
, z
, (char*)0);
6000 ** tclcmd: file_control_vfsname DB ?AUXDB?
6002 ** Return a string that describes the stack of VFSes.
6004 static int SQLITE_TCLAPI
file_control_vfsname(
6005 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
6006 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
6007 int objc
, /* Number of arguments */
6008 Tcl_Obj
*CONST objv
[] /* Command arguments */
6011 const char *zDbName
= "main";
6014 if( objc
!=2 && objc
!=3 ){
6015 Tcl_AppendResult(interp
, "wrong # args: should be \"",
6016 Tcl_GetStringFromObj(objv
[0], 0), " DB ?AUXDB?", 0);
6019 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ){
6023 zDbName
= Tcl_GetString(objv
[2]);
6025 sqlite3_file_control(db
, zDbName
, SQLITE_FCNTL_VFSNAME
,(void*)&zVfsName
);
6026 Tcl_AppendResult(interp
, zVfsName
, (char*)0);
6027 sqlite3_free(zVfsName
);
6032 ** tclcmd: file_control_tempfilename DB ?AUXDB?
6034 ** Return a string that is a temporary filename
6036 static int SQLITE_TCLAPI
file_control_tempfilename(
6037 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
6038 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
6039 int objc
, /* Number of arguments */
6040 Tcl_Obj
*CONST objv
[] /* Command arguments */
6043 const char *zDbName
= "main";
6046 if( objc
!=2 && objc
!=3 ){
6047 Tcl_AppendResult(interp
, "wrong # args: should be \"",
6048 Tcl_GetStringFromObj(objv
[0], 0), " DB ?AUXDB?", 0);
6051 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ){
6055 zDbName
= Tcl_GetString(objv
[2]);
6057 sqlite3_file_control(db
, zDbName
, SQLITE_FCNTL_TEMPFILENAME
, (void*)&zTName
);
6058 Tcl_AppendResult(interp
, zTName
, (char*)0);
6059 sqlite3_free(zTName
);
6065 ** tclcmd: sqlite3_vfs_list
6067 ** Return a tcl list containing the names of all registered vfs's.
6069 static int SQLITE_TCLAPI
vfs_list(
6070 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
6071 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
6072 int objc
, /* Number of arguments */
6073 Tcl_Obj
*CONST objv
[] /* Command arguments */
6076 Tcl_Obj
*pRet
= Tcl_NewObj();
6078 Tcl_WrongNumArgs(interp
, 1, objv
, "");
6081 for(pVfs
=sqlite3_vfs_find(0); pVfs
; pVfs
=pVfs
->pNext
){
6082 Tcl_ListObjAppendElement(interp
, pRet
, Tcl_NewStringObj(pVfs
->zName
, -1));
6084 Tcl_SetObjResult(interp
, pRet
);
6089 ** tclcmd: sqlite3_limit DB ID VALUE
6091 ** This TCL command runs the sqlite3_limit interface and
6092 ** verifies correct operation of the same.
6094 static int SQLITE_TCLAPI
test_limit(
6095 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
6096 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
6097 int objc
, /* Number of arguments */
6098 Tcl_Obj
*CONST objv
[] /* Command arguments */
6102 static const struct {
6106 { "SQLITE_LIMIT_LENGTH", SQLITE_LIMIT_LENGTH
},
6107 { "SQLITE_LIMIT_SQL_LENGTH", SQLITE_LIMIT_SQL_LENGTH
},
6108 { "SQLITE_LIMIT_COLUMN", SQLITE_LIMIT_COLUMN
},
6109 { "SQLITE_LIMIT_EXPR_DEPTH", SQLITE_LIMIT_EXPR_DEPTH
},
6110 { "SQLITE_LIMIT_COMPOUND_SELECT", SQLITE_LIMIT_COMPOUND_SELECT
},
6111 { "SQLITE_LIMIT_VDBE_OP", SQLITE_LIMIT_VDBE_OP
},
6112 { "SQLITE_LIMIT_FUNCTION_ARG", SQLITE_LIMIT_FUNCTION_ARG
},
6113 { "SQLITE_LIMIT_ATTACHED", SQLITE_LIMIT_ATTACHED
},
6114 { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH
},
6115 { "SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER
},
6116 { "SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH
},
6117 { "SQLITE_LIMIT_WORKER_THREADS", SQLITE_LIMIT_WORKER_THREADS
},
6119 /* Out of range test cases */
6120 { "SQLITE_LIMIT_TOOSMALL", -1, },
6121 { "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_WORKER_THREADS
+1 },
6128 Tcl_AppendResult(interp
, "wrong # args: should be \"",
6129 Tcl_GetStringFromObj(objv
[0], 0), " DB ID VALUE", 0);
6132 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
6133 zId
= Tcl_GetString(objv
[2]);
6134 for(i
=0; i
<sizeof(aId
)/sizeof(aId
[0]); i
++){
6135 if( strcmp(zId
, aId
[i
].zName
)==0 ){
6140 if( i
>=sizeof(aId
)/sizeof(aId
[0]) ){
6141 Tcl_AppendResult(interp
, "unknown limit type: ", zId
, (char*)0);
6144 if( Tcl_GetIntFromObj(interp
, objv
[3], &val
) ) return TCL_ERROR
;
6145 rc
= sqlite3_limit(db
, id
, val
);
6146 Tcl_SetObjResult(interp
, Tcl_NewIntObj(rc
));
6151 ** tclcmd: save_prng_state
6153 ** Save the state of the pseudo-random number generator.
6154 ** At the same time, verify that sqlite3_test_control works even when
6155 ** called with an out-of-range opcode.
6157 static int SQLITE_TCLAPI
save_prng_state(
6158 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
6159 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
6160 int objc
, /* Number of arguments */
6161 Tcl_Obj
*CONST objv
[] /* Command arguments */
6163 int rc
= sqlite3_test_control(9999);
6165 rc
= sqlite3_test_control(-1);
6167 sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SAVE
);
6171 ** tclcmd: restore_prng_state
6173 static int SQLITE_TCLAPI
restore_prng_state(
6174 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
6175 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
6176 int objc
, /* Number of arguments */
6177 Tcl_Obj
*CONST objv
[] /* Command arguments */
6179 sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESTORE
);
6183 ** tclcmd: reset_prng_state
6185 static int SQLITE_TCLAPI
reset_prng_state(
6186 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
6187 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
6188 int objc
, /* Number of arguments */
6189 Tcl_Obj
*CONST objv
[] /* Command arguments */
6191 sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESET
);
6196 ** tclcmd: database_may_be_corrupt
6198 ** Indicate that database files might be corrupt. In other words, set the normal
6199 ** state of operation.
6201 static int SQLITE_TCLAPI
database_may_be_corrupt(
6202 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
6203 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
6204 int objc
, /* Number of arguments */
6205 Tcl_Obj
*CONST objv
[] /* Command arguments */
6207 sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT
, 0);
6211 ** tclcmd: database_never_corrupt
6213 ** Indicate that database files are always well-formed. This enables extra assert()
6214 ** statements that test conditions that are always true for well-formed databases.
6216 static int SQLITE_TCLAPI
database_never_corrupt(
6217 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
6218 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
6219 int objc
, /* Number of arguments */
6220 Tcl_Obj
*CONST objv
[] /* Command arguments */
6222 sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT
, 1);
6227 ** tclcmd: pcache_stats
6229 static int SQLITE_TCLAPI
test_pcache_stats(
6230 ClientData clientData
, /* Pointer to sqlite3_enable_XXX function */
6231 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
6232 int objc
, /* Number of arguments */
6233 Tcl_Obj
*CONST objv
[] /* Command arguments */
6241 sqlite3PcacheStats(&nCurrent
, &nMax
, &nMin
, &nRecyclable
);
6243 pRet
= Tcl_NewObj();
6244 Tcl_ListObjAppendElement(interp
, pRet
, Tcl_NewStringObj("current", -1));
6245 Tcl_ListObjAppendElement(interp
, pRet
, Tcl_NewIntObj(nCurrent
));
6246 Tcl_ListObjAppendElement(interp
, pRet
, Tcl_NewStringObj("max", -1));
6247 Tcl_ListObjAppendElement(interp
, pRet
, Tcl_NewIntObj(nMax
));
6248 Tcl_ListObjAppendElement(interp
, pRet
, Tcl_NewStringObj("min", -1));
6249 Tcl_ListObjAppendElement(interp
, pRet
, Tcl_NewIntObj(nMin
));
6250 Tcl_ListObjAppendElement(interp
, pRet
, Tcl_NewStringObj("recyclable", -1));
6251 Tcl_ListObjAppendElement(interp
, pRet
, Tcl_NewIntObj(nRecyclable
));
6253 Tcl_SetObjResult(interp
, pRet
);
6258 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
6259 static void test_unlock_notify_cb(void **aArg
, int nArg
){
6261 for(ii
=0; ii
<nArg
; ii
++){
6262 Tcl_EvalEx((Tcl_Interp
*)aArg
[ii
], "unlock_notify", -1, TCL_EVAL_GLOBAL
);
6265 #endif /* SQLITE_ENABLE_UNLOCK_NOTIFY */
6268 ** tclcmd: sqlite3_unlock_notify db
6270 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
6271 static int SQLITE_TCLAPI
test_unlock_notify(
6272 ClientData clientData
, /* Unused */
6273 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
6274 int objc
, /* Number of arguments */
6275 Tcl_Obj
*CONST objv
[] /* Command arguments */
6281 Tcl_WrongNumArgs(interp
, 1, objv
, "DB");
6285 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ){
6288 rc
= sqlite3_unlock_notify(db
, test_unlock_notify_cb
, (void *)interp
);
6289 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), TCL_STATIC
);
6295 ** tclcmd: sqlite3_wal_checkpoint db ?NAME?
6297 static int SQLITE_TCLAPI
test_wal_checkpoint(
6298 ClientData clientData
, /* Unused */
6299 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
6300 int objc
, /* Number of arguments */
6301 Tcl_Obj
*CONST objv
[] /* Command arguments */
6307 if( objc
!=3 && objc
!=2 ){
6308 Tcl_WrongNumArgs(interp
, 1, objv
, "DB ?NAME?");
6312 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ){
6316 zDb
= Tcl_GetString(objv
[2]);
6318 rc
= sqlite3_wal_checkpoint(db
, zDb
);
6319 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), TCL_STATIC
);
6324 ** tclcmd: sqlite3_wal_checkpoint_v2 db MODE ?NAME?
6326 ** This command calls the wal_checkpoint_v2() function with the specified
6327 ** mode argument (passive, full or restart). If present, the database name
6328 ** NAME is passed as the second argument to wal_checkpoint_v2(). If it the
6329 ** NAME argument is not present, a NULL pointer is passed instead.
6331 ** If wal_checkpoint_v2() returns any value other than SQLITE_BUSY or
6332 ** SQLITE_OK, then this command returns TCL_ERROR. The Tcl result is set
6333 ** to the error message obtained from sqlite3_errmsg().
6335 ** Otherwise, this command returns a list of three integers. The first integer
6336 ** is 1 if SQLITE_BUSY was returned, or 0 otherwise. The following two integers
6337 ** are the values returned via the output parameters by wal_checkpoint_v2() -
6338 ** the number of frames in the log and the number of frames in the log
6339 ** that have been checkpointed.
6341 static int SQLITE_TCLAPI
test_wal_checkpoint_v2(
6342 ClientData clientData
, /* Unused */
6343 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
6344 int objc
, /* Number of arguments */
6345 Tcl_Obj
*CONST objv
[] /* Command arguments */
6356 const char * aMode
[] = { "passive", "full", "restart", "truncate", 0 };
6357 assert( SQLITE_CHECKPOINT_PASSIVE
==0 );
6358 assert( SQLITE_CHECKPOINT_FULL
==1 );
6359 assert( SQLITE_CHECKPOINT_RESTART
==2 );
6360 assert( SQLITE_CHECKPOINT_TRUNCATE
==3 );
6362 if( objc
!=3 && objc
!=4 ){
6363 Tcl_WrongNumArgs(interp
, 1, objv
, "DB MODE ?NAME?");
6368 zDb
= Tcl_GetString(objv
[3]);
6370 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) || (
6371 TCL_OK
!=Tcl_GetIntFromObj(0, objv
[2], &eMode
)
6372 && TCL_OK
!=Tcl_GetIndexFromObj(interp
, objv
[2], aMode
, "mode", 0, &eMode
)
6377 rc
= sqlite3_wal_checkpoint_v2(db
, zDb
, eMode
, &nLog
, &nCkpt
);
6378 if( rc
!=SQLITE_OK
&& rc
!=SQLITE_BUSY
){
6379 const char *zErrCode
= sqlite3ErrName(rc
);
6380 Tcl_ResetResult(interp
);
6381 Tcl_AppendResult(interp
, zErrCode
, " - ", (char *)sqlite3_errmsg(db
), 0);
6385 pRet
= Tcl_NewObj();
6386 Tcl_ListObjAppendElement(interp
, pRet
, Tcl_NewIntObj(rc
==SQLITE_BUSY
?1:0));
6387 Tcl_ListObjAppendElement(interp
, pRet
, Tcl_NewIntObj(nLog
));
6388 Tcl_ListObjAppendElement(interp
, pRet
, Tcl_NewIntObj(nCkpt
));
6389 Tcl_SetObjResult(interp
, pRet
);
6395 ** tclcmd: sqlite3_wal_autocheckpoint db VALUE
6397 static int SQLITE_TCLAPI
test_wal_autocheckpoint(
6398 ClientData clientData
, /* Unused */
6399 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
6400 int objc
, /* Number of arguments */
6401 Tcl_Obj
*CONST objv
[] /* Command arguments */
6409 Tcl_WrongNumArgs(interp
, 1, objv
, "DB VALUE");
6413 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
)
6414 || Tcl_GetIntFromObj(0, objv
[2], &iVal
)
6419 rc
= sqlite3_wal_autocheckpoint(db
, iVal
);
6420 Tcl_ResetResult(interp
);
6421 if( rc
!=SQLITE_OK
){
6422 const char *zErrCode
= sqlite3ErrName(rc
);
6423 Tcl_SetObjResult(interp
, Tcl_NewStringObj(zErrCode
, -1));
6432 ** tclcmd: test_sqlite3_log ?SCRIPT?
6434 static struct LogCallback
{
6435 Tcl_Interp
*pInterp
;
6437 } logcallback
= {0, 0};
6438 static void xLogcallback(void *unused
, int err
, char *zMsg
){
6439 Tcl_Obj
*pNew
= Tcl_DuplicateObj(logcallback
.pObj
);
6440 Tcl_IncrRefCount(pNew
);
6441 Tcl_ListObjAppendElement(
6442 0, pNew
, Tcl_NewStringObj(sqlite3ErrName(err
), -1)
6444 Tcl_ListObjAppendElement(0, pNew
, Tcl_NewStringObj(zMsg
, -1));
6445 Tcl_EvalObjEx(logcallback
.pInterp
, pNew
, TCL_EVAL_GLOBAL
|TCL_EVAL_DIRECT
);
6446 Tcl_DecrRefCount(pNew
);
6448 static int SQLITE_TCLAPI
test_sqlite3_log(
6449 ClientData clientData
,
6450 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
6451 int objc
, /* Number of arguments */
6452 Tcl_Obj
*CONST objv
[] /* Command arguments */
6455 Tcl_WrongNumArgs(interp
, 1, objv
, "SCRIPT");
6458 if( logcallback
.pObj
){
6459 Tcl_DecrRefCount(logcallback
.pObj
);
6460 logcallback
.pObj
= 0;
6461 logcallback
.pInterp
= 0;
6462 sqlite3_config(SQLITE_CONFIG_LOG
, (void*)0, (void*)0);
6465 logcallback
.pObj
= objv
[1];
6466 Tcl_IncrRefCount(logcallback
.pObj
);
6467 logcallback
.pInterp
= interp
;
6468 sqlite3_config(SQLITE_CONFIG_LOG
, xLogcallback
, (void*)0);
6474 ** tcl_objproc COMMANDNAME ARGS...
6476 ** Run a TCL command using its objProc interface. Throw an error if
6477 ** the command has no objProc interface.
6479 static int SQLITE_TCLAPI
runAsObjProc(
6483 Tcl_Obj
*CONST objv
[]
6485 Tcl_CmdInfo cmdInfo
;
6487 Tcl_WrongNumArgs(interp
, 1, objv
, "COMMAND ...");
6490 if( !Tcl_GetCommandInfo(interp
, Tcl_GetString(objv
[1]), &cmdInfo
) ){
6491 Tcl_AppendResult(interp
, "command not found: ",
6492 Tcl_GetString(objv
[1]), (char*)0);
6495 if( cmdInfo
.objProc
==0 ){
6496 Tcl_AppendResult(interp
, "command has no objProc: ",
6497 Tcl_GetString(objv
[1]), (char*)0);
6500 return cmdInfo
.objProc(cmdInfo
.objClientData
, interp
, objc
-1, objv
+1);
6503 #ifndef SQLITE_OMIT_EXPLAIN
6505 ** WARNING: The following function, printExplainQueryPlan() is an exact
6506 ** copy of example code from eqp.in (eqp.html). If this code is modified,
6507 ** then the documentation copy needs to be modified as well.
6510 ** Argument pStmt is a prepared SQL statement. This function compiles
6511 ** an EXPLAIN QUERY PLAN command to report on the prepared statement,
6512 ** and prints the report to stdout using printf().
6514 int printExplainQueryPlan(sqlite3_stmt
*pStmt
){
6515 const char *zSql
; /* Input SQL */
6516 char *zExplain
; /* SQL with EXPLAIN QUERY PLAN prepended */
6517 sqlite3_stmt
*pExplain
; /* Compiled EXPLAIN QUERY PLAN command */
6518 int rc
; /* Return code from sqlite3_prepare_v2() */
6520 zSql
= sqlite3_sql(pStmt
);
6521 if( zSql
==0 ) return SQLITE_ERROR
;
6523 zExplain
= sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zSql
);
6524 if( zExplain
==0 ) return SQLITE_NOMEM
;
6526 rc
= sqlite3_prepare_v2(sqlite3_db_handle(pStmt
), zExplain
, -1, &pExplain
, 0);
6527 sqlite3_free(zExplain
);
6528 if( rc
!=SQLITE_OK
) return rc
;
6530 while( SQLITE_ROW
==sqlite3_step(pExplain
) ){
6531 int iSelectid
= sqlite3_column_int(pExplain
, 0);
6532 int iOrder
= sqlite3_column_int(pExplain
, 1);
6533 int iFrom
= sqlite3_column_int(pExplain
, 2);
6534 const char *zDetail
= (const char *)sqlite3_column_text(pExplain
, 3);
6536 printf("%d %d %d %s\n", iSelectid
, iOrder
, iFrom
, zDetail
);
6539 return sqlite3_finalize(pExplain
);
6542 static int SQLITE_TCLAPI
test_print_eqp(
6546 Tcl_Obj
*CONST objv
[]
6549 sqlite3_stmt
*pStmt
;
6552 Tcl_WrongNumArgs(interp
, 1, objv
, "STMT");
6555 if( getStmtPointer(interp
, Tcl_GetString(objv
[1]), &pStmt
) ) return TCL_ERROR
;
6556 rc
= printExplainQueryPlan(pStmt
);
6557 /* This is needed on Windows so that a test case using this
6558 ** function can open a read pipe and get the output of
6559 ** printExplainQueryPlan() immediately.
6562 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), 0);
6565 #endif /* SQLITE_OMIT_EXPLAIN */
6568 ** sqlite3_test_control VERB ARGS...
6570 static int SQLITE_TCLAPI
test_test_control(
6574 Tcl_Obj
*CONST objv
[]
6580 { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT
},
6581 { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP
},
6582 { "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER
},
6589 Tcl_WrongNumArgs(interp
, 1, objv
, "VERB ARGS...");
6593 rc
= Tcl_GetIndexFromObjStruct(
6594 interp
, objv
[1], aVerb
, sizeof(aVerb
[0]), "VERB", 0, &iVerb
6596 if( rc
!=TCL_OK
) return rc
;
6598 iFlag
= aVerb
[iVerb
].i
;
6600 case SQLITE_TESTCTRL_LOCALTIME_FAULT
: {
6603 Tcl_WrongNumArgs(interp
, 2, objv
, "ONOFF");
6606 if( Tcl_GetBooleanFromObj(interp
, objv
[2], &val
) ) return TCL_ERROR
;
6607 sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT
, val
);
6611 case SQLITE_TESTCTRL_SORTER_MMAP
: {
6615 Tcl_WrongNumArgs(interp
, 2, objv
, "DB LIMIT");
6618 if( getDbPointer(interp
, Tcl_GetString(objv
[2]), &db
) ) return TCL_ERROR
;
6619 if( Tcl_GetIntFromObj(interp
, objv
[3], &val
) ) return TCL_ERROR
;
6620 sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP
, db
, val
);
6624 case SQLITE_TESTCTRL_IMPOSTER
: {
6626 const char *zDbName
;
6629 Tcl_WrongNumArgs(interp
, 2, objv
, "DB dbName onOff tnum");
6632 if( getDbPointer(interp
, Tcl_GetString(objv
[2]), &db
) ) return TCL_ERROR
;
6633 zDbName
= Tcl_GetString(objv
[3]);
6634 if( Tcl_GetIntFromObj(interp
, objv
[4], &onOff
) ) return TCL_ERROR
;
6635 if( Tcl_GetIntFromObj(interp
, objv
[5], &tnum
) ) return TCL_ERROR
;
6636 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER
, db
, zDbName
, onOff
, tnum
);
6641 Tcl_ResetResult(interp
);
6646 #include <sys/time.h>
6647 #include <sys/resource.h>
6649 static int SQLITE_TCLAPI
test_getrusage(
6653 Tcl_Obj
*CONST objv
[]
6657 memset(&r
, 0, sizeof(r
));
6658 getrusage(RUSAGE_SELF
, &r
);
6660 sqlite3_snprintf(sizeof(buf
), buf
,
6661 "ru_utime=%d.%06d ru_stime=%d.%06d ru_minflt=%d ru_majflt=%d",
6662 (int)r
.ru_utime
.tv_sec
, (int)r
.ru_utime
.tv_usec
,
6663 (int)r
.ru_stime
.tv_sec
, (int)r
.ru_stime
.tv_usec
,
6664 (int)r
.ru_minflt
, (int)r
.ru_majflt
6666 Tcl_SetObjResult(interp
, Tcl_NewStringObj(buf
, -1));
6673 ** Information passed from the main thread into the windows file locker
6674 ** background thread.
6676 struct win32FileLocker
{
6677 char *evName
; /* Name of event to signal thread startup */
6678 HANDLE h
; /* Handle of the file to be locked */
6679 int delay1
; /* Delay before locking */
6680 int delay2
; /* Delay before unlocking */
6681 int ok
; /* Finished ok */
6682 int err
; /* True if an error occurs */
6688 #include <process.h>
6690 ** The background thread that does file locking.
6692 static void SQLITE_CDECL
win32_file_locker(void *pAppData
){
6693 struct win32FileLocker
*p
= (struct win32FileLocker
*)pAppData
;
6695 HANDLE ev
= OpenEvent(EVENT_MODIFY_STATE
, FALSE
, p
->evName
);
6701 if( p
->delay1
) Sleep(p
->delay1
);
6702 if( LockFile(p
->h
, 0, 0, 100000000, 0) ){
6704 UnlockFile(p
->h
, 0, 0, 100000000, 0);
6718 ** lock_win32_file FILENAME DELAY1 DELAY2
6720 ** Get an exclusive manditory lock on file for DELAY2 milliseconds.
6721 ** Wait DELAY1 milliseconds before acquiring the lock.
6723 static int SQLITE_TCLAPI
win32_file_lock(
6727 Tcl_Obj
*CONST objv
[]
6729 static struct win32FileLocker x
= { "win32_file_lock", 0, 0, 0, 0, 0 };
6730 const char *zFilename
;
6736 if( objc
!=4 && objc
!=1 ){
6737 Tcl_WrongNumArgs(interp
, 1, objv
, "FILENAME DELAY1 DELAY2");
6741 sqlite3_snprintf(sizeof(zBuf
), zBuf
, "%d %d %d %d %d",
6742 x
.ok
, x
.err
, x
.delay1
, x
.delay2
, x
.h
);
6743 Tcl_AppendResult(interp
, zBuf
, (char*)0);
6746 while( x
.h
&& retry
<30 ){
6751 Tcl_AppendResult(interp
, "busy", (char*)0);
6754 if( Tcl_GetIntFromObj(interp
, objv
[2], &x
.delay1
) ) return TCL_ERROR
;
6755 if( Tcl_GetIntFromObj(interp
, objv
[3], &x
.delay2
) ) return TCL_ERROR
;
6756 zFilename
= Tcl_GetString(objv
[1]);
6757 x
.h
= CreateFile(zFilename
, GENERIC_READ
|GENERIC_WRITE
,
6758 FILE_SHARE_READ
|FILE_SHARE_WRITE
, 0, OPEN_ALWAYS
,
6759 FILE_ATTRIBUTE_NORMAL
, 0);
6761 Tcl_AppendResult(interp
, "cannot open file: ", zFilename
, (char*)0);
6764 ev
= CreateEvent(NULL
, TRUE
, FALSE
, x
.evName
);
6766 Tcl_AppendResult(interp
, "cannot create event: ", x
.evName
, (char*)0);
6769 _beginthread(win32_file_locker
, 0, (void*)&x
);
6771 if ( (wResult
= WaitForSingleObject(ev
, 10000))!=WAIT_OBJECT_0
){
6772 sqlite3_snprintf(sizeof(zBuf
), zBuf
, "0x%x", wResult
);
6773 Tcl_AppendResult(interp
, "wait failed: ", zBuf
, (char*)0);
6782 ** exists_win32_path PATH
6784 ** Returns non-zero if the specified path exists, whose fully qualified name
6785 ** may exceed 260 characters if it is prefixed with "\\?\".
6787 static int SQLITE_TCLAPI
win32_exists_path(
6791 Tcl_Obj
*CONST objv
[]
6794 Tcl_WrongNumArgs(interp
, 1, objv
, "PATH");
6797 Tcl_SetObjResult(interp
, Tcl_NewBooleanObj(
6798 GetFileAttributesW( Tcl_GetUnicode(objv
[1]))!=INVALID_FILE_ATTRIBUTES
));
6803 ** find_win32_file PATTERN
6805 ** Returns a list of entries in a directory that match the specified pattern,
6806 ** whose fully qualified name may exceed 248 characters if it is prefixed with
6809 static int SQLITE_TCLAPI
win32_find_file(
6813 Tcl_Obj
*CONST objv
[]
6815 HANDLE hFindFile
= INVALID_HANDLE_VALUE
;
6816 WIN32_FIND_DATAW findData
;
6820 Tcl_WrongNumArgs(interp
, 1, objv
, "PATTERN");
6823 hFindFile
= FindFirstFileW(Tcl_GetUnicode(objv
[1]), &findData
);
6824 if( hFindFile
==INVALID_HANDLE_VALUE
){
6825 Tcl_SetObjResult(interp
, Tcl_NewWideIntObj(GetLastError()));
6828 listObj
= Tcl_NewObj();
6829 Tcl_IncrRefCount(listObj
);
6831 Tcl_ListObjAppendElement(interp
, listObj
, Tcl_NewUnicodeObj(
6832 findData
.cFileName
, -1));
6833 Tcl_ListObjAppendElement(interp
, listObj
, Tcl_NewWideIntObj(
6834 findData
.dwFileAttributes
));
6835 } while( FindNextFileW(hFindFile
, &findData
) );
6836 lastErrno
= GetLastError();
6837 if( lastErrno
!=NO_ERROR
&& lastErrno
!=ERROR_NO_MORE_FILES
){
6838 FindClose(hFindFile
);
6839 Tcl_DecrRefCount(listObj
);
6840 Tcl_SetObjResult(interp
, Tcl_NewWideIntObj(GetLastError()));
6843 FindClose(hFindFile
);
6844 Tcl_SetObjResult(interp
, listObj
);
6849 ** delete_win32_file FILENAME
6851 ** Deletes the specified file, whose fully qualified name may exceed 260
6852 ** characters if it is prefixed with "\\?\".
6854 static int SQLITE_TCLAPI
win32_delete_file(
6858 Tcl_Obj
*CONST objv
[]
6861 Tcl_WrongNumArgs(interp
, 1, objv
, "FILENAME");
6864 if( !DeleteFileW(Tcl_GetUnicode(objv
[1])) ){
6865 Tcl_SetObjResult(interp
, Tcl_NewWideIntObj(GetLastError()));
6868 Tcl_ResetResult(interp
);
6873 ** make_win32_dir DIRECTORY
6875 ** Creates the specified directory, whose fully qualified name may exceed 248
6876 ** characters if it is prefixed with "\\?\".
6878 static int SQLITE_TCLAPI
win32_mkdir(
6882 Tcl_Obj
*CONST objv
[]
6885 Tcl_WrongNumArgs(interp
, 1, objv
, "DIRECTORY");
6888 if( !CreateDirectoryW(Tcl_GetUnicode(objv
[1]), NULL
) ){
6889 Tcl_SetObjResult(interp
, Tcl_NewWideIntObj(GetLastError()));
6892 Tcl_ResetResult(interp
);
6897 ** remove_win32_dir DIRECTORY
6899 ** Removes the specified directory, whose fully qualified name may exceed 248
6900 ** characters if it is prefixed with "\\?\".
6902 static int SQLITE_TCLAPI
win32_rmdir(
6906 Tcl_Obj
*CONST objv
[]
6909 Tcl_WrongNumArgs(interp
, 1, objv
, "DIRECTORY");
6912 if( !RemoveDirectoryW(Tcl_GetUnicode(objv
[1])) ){
6913 Tcl_SetObjResult(interp
, Tcl_NewWideIntObj(GetLastError()));
6916 Tcl_ResetResult(interp
);
6923 ** optimization_control DB OPT BOOLEAN
6925 ** Enable or disable query optimizations using the sqlite3_test_control()
6926 ** interface. Disable if BOOLEAN is false and enable if BOOLEAN is true.
6927 ** OPT is the name of the optimization to be disabled.
6929 static int SQLITE_TCLAPI
optimization_control(
6933 Tcl_Obj
*CONST objv
[]
6940 static const struct {
6941 const char *zOptName
;
6944 { "all", SQLITE_AllOpts
},
6946 { "query-flattener", SQLITE_QueryFlattener
},
6947 { "column-cache", SQLITE_ColumnCache
},
6948 { "groupby-order", SQLITE_GroupByOrder
},
6949 { "factor-constants", SQLITE_FactorOutConst
},
6950 { "distinct-opt", SQLITE_DistinctOpt
},
6951 { "cover-idx-scan", SQLITE_CoverIdxScan
},
6952 { "order-by-idx-join", SQLITE_OrderByIdxJoin
},
6953 { "transitive", SQLITE_Transitive
},
6954 { "omit-noop-join", SQLITE_OmitNoopJoin
},
6955 { "stat3", SQLITE_Stat34
},
6956 { "stat4", SQLITE_Stat34
},
6960 Tcl_WrongNumArgs(interp
, 1, objv
, "DB OPT BOOLEAN");
6963 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
6964 if( Tcl_GetBooleanFromObj(interp
, objv
[3], &onoff
) ) return TCL_ERROR
;
6965 zOpt
= Tcl_GetString(objv
[2]);
6966 for(i
=0; i
<sizeof(aOpt
)/sizeof(aOpt
[0]); i
++){
6967 if( strcmp(zOpt
, aOpt
[i
].zOptName
)==0 ){
6968 mask
= aOpt
[i
].mask
;
6972 if( onoff
) mask
= ~mask
;
6973 if( i
>=sizeof(aOpt
)/sizeof(aOpt
[0]) ){
6974 Tcl_AppendResult(interp
, "unknown optimization - should be one of:",
6976 for(i
=0; i
<sizeof(aOpt
)/sizeof(aOpt
[0]); i
++){
6977 Tcl_AppendResult(interp
, " ", aOpt
[i
].zOptName
, (char*)0);
6981 sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS
, db
, mask
);
6986 ** load_static_extension DB NAME ...
6988 ** Load one or more statically linked extensions.
6990 static int SQLITE_TCLAPI
tclLoadStaticExtensionCmd(
6994 Tcl_Obj
*CONST objv
[]
6996 extern int sqlite3_amatch_init(sqlite3
*,char**,const sqlite3_api_routines
*);
6997 extern int sqlite3_carray_init(sqlite3
*,char**,const sqlite3_api_routines
*);
6998 extern int sqlite3_closure_init(sqlite3
*,char**,const sqlite3_api_routines
*);
6999 extern int sqlite3_csv_init(sqlite3
*,char**,const sqlite3_api_routines
*);
7000 extern int sqlite3_eval_init(sqlite3
*,char**,const sqlite3_api_routines
*);
7001 extern int sqlite3_fileio_init(sqlite3
*,char**,const sqlite3_api_routines
*);
7002 extern int sqlite3_fuzzer_init(sqlite3
*,char**,const sqlite3_api_routines
*);
7003 extern int sqlite3_ieee_init(sqlite3
*,char**,const sqlite3_api_routines
*);
7004 extern int sqlite3_nextchar_init(sqlite3
*,char**,const sqlite3_api_routines
*);
7005 extern int sqlite3_percentile_init(sqlite3
*,char**,const sqlite3_api_routines
*);
7006 extern int sqlite3_regexp_init(sqlite3
*,char**,const sqlite3_api_routines
*);
7007 extern int sqlite3_remember_init(sqlite3
*,char**,const sqlite3_api_routines
*);
7008 extern int sqlite3_series_init(sqlite3
*,char**,const sqlite3_api_routines
*);
7009 extern int sqlite3_spellfix_init(sqlite3
*,char**,const sqlite3_api_routines
*);
7010 extern int sqlite3_totype_init(sqlite3
*,char**,const sqlite3_api_routines
*);
7011 extern int sqlite3_wholenumber_init(sqlite3
*,char**,const sqlite3_api_routines
*);
7012 extern int sqlite3_unionvtab_init(sqlite3
*,char**,const sqlite3_api_routines
*);
7013 #ifdef SQLITE_HAVE_ZLIB
7014 extern int sqlite3_zipfile_init(sqlite3
*,char**,const sqlite3_api_routines
*);
7016 static const struct {
7017 const char *zExtName
;
7018 int (*pInit
)(sqlite3
*,char**,const sqlite3_api_routines
*);
7020 { "amatch", sqlite3_amatch_init
},
7021 { "carray", sqlite3_carray_init
},
7022 { "closure", sqlite3_closure_init
},
7023 { "csv", sqlite3_csv_init
},
7024 { "eval", sqlite3_eval_init
},
7025 { "fileio", sqlite3_fileio_init
},
7026 { "fuzzer", sqlite3_fuzzer_init
},
7027 { "ieee754", sqlite3_ieee_init
},
7028 { "nextchar", sqlite3_nextchar_init
},
7029 { "percentile", sqlite3_percentile_init
},
7030 { "regexp", sqlite3_regexp_init
},
7031 { "remember", sqlite3_remember_init
},
7032 { "series", sqlite3_series_init
},
7033 { "spellfix", sqlite3_spellfix_init
},
7034 { "totype", sqlite3_totype_init
},
7035 { "unionvtab", sqlite3_unionvtab_init
},
7036 { "wholenumber", sqlite3_wholenumber_init
},
7037 #ifdef SQLITE_HAVE_ZLIB
7038 { "zipfile", sqlite3_zipfile_init
},
7046 Tcl_WrongNumArgs(interp
, 1, objv
, "DB NAME ...");
7049 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
7050 for(j
=2; j
<objc
; j
++){
7051 zName
= Tcl_GetString(objv
[j
]);
7052 for(i
=0; i
<ArraySize(aExtension
); i
++){
7053 if( strcmp(zName
, aExtension
[i
].zExtName
)==0 ) break;
7055 if( i
>=ArraySize(aExtension
) ){
7056 Tcl_AppendResult(interp
, "no such extension: ", zName
, (char*)0);
7059 if( aExtension
[i
].pInit
){
7060 rc
= aExtension
[i
].pInit(db
, &zErrMsg
, 0);
7064 if( rc
!=SQLITE_OK
|| zErrMsg
){
7065 Tcl_AppendResult(interp
, "initialization of ", zName
, " failed: ", zErrMsg
,
7067 sqlite3_free(zErrMsg
);
7075 ** sorter_test_fakeheap BOOL
7078 static int SQLITE_TCLAPI
sorter_test_fakeheap(
7082 Tcl_Obj
*CONST objv
[]
7086 Tcl_WrongNumArgs(interp
, 1, objv
, "BOOL");
7090 if( Tcl_GetBooleanFromObj(interp
, objv
[1], &bArg
) ){
7095 if( sqlite3GlobalConfig
.pHeap
==0 ){
7096 sqlite3GlobalConfig
.pHeap
= SQLITE_INT_TO_PTR(-1);
7099 if( sqlite3GlobalConfig
.pHeap
==SQLITE_INT_TO_PTR(-1) ){
7100 sqlite3GlobalConfig
.pHeap
= 0;
7104 Tcl_ResetResult(interp
);
7109 ** sorter_test_sort4_helper DB SQL1 NSTEP SQL2
7111 ** Compile SQL statement $SQL1 and step it $NSTEP times. For each row,
7112 ** check that the leftmost and rightmost columns returned are both integers,
7113 ** and that both contain the same value.
7115 ** Then execute statement $SQL2. Check that the statement returns the same
7116 ** set of integers in the same order as in the previous step (using $SQL1).
7118 static int SQLITE_TCLAPI
sorter_test_sort4_helper(
7122 Tcl_Obj
*CONST objv
[]
7128 unsigned int iCksum1
= 0;
7129 unsigned int iCksum2
= 0;
7133 sqlite3_stmt
*pStmt
;
7136 Tcl_WrongNumArgs(interp
, 1, objv
, "DB SQL1 NSTEP SQL2");
7140 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
7141 zSql1
= Tcl_GetString(objv
[2]);
7142 if( Tcl_GetIntFromObj(interp
, objv
[3], &nStep
) ) return TCL_ERROR
;
7143 zSql2
= Tcl_GetString(objv
[4]);
7145 rc
= sqlite3_prepare_v2(db
, zSql1
, -1, &pStmt
, 0);
7146 if( rc
!=SQLITE_OK
) goto sql_error
;
7148 iB
= sqlite3_column_count(pStmt
)-1;
7149 for(iStep
=0; iStep
<nStep
&& SQLITE_ROW
==sqlite3_step(pStmt
); iStep
++){
7150 int a
= sqlite3_column_int(pStmt
, 0);
7151 if( a
!=sqlite3_column_int(pStmt
, iB
) ){
7152 Tcl_AppendResult(interp
, "data error: (a!=b)", 0);
7156 iCksum1
+= (iCksum1
<< 3) + (unsigned int)a
;
7158 rc
= sqlite3_finalize(pStmt
);
7159 if( rc
!=SQLITE_OK
) goto sql_error
;
7161 rc
= sqlite3_prepare_v2(db
, zSql2
, -1, &pStmt
, 0);
7162 if( rc
!=SQLITE_OK
) goto sql_error
;
7163 for(iStep
=0; SQLITE_ROW
==sqlite3_step(pStmt
); iStep
++){
7164 int a
= sqlite3_column_int(pStmt
, 0);
7165 iCksum2
+= (iCksum2
<< 3) + (unsigned int)a
;
7167 rc
= sqlite3_finalize(pStmt
);
7168 if( rc
!=SQLITE_OK
) goto sql_error
;
7170 if( iCksum1
!=iCksum2
){
7171 Tcl_AppendResult(interp
, "checksum mismatch", 0);
7177 Tcl_AppendResult(interp
, "sql error: ", sqlite3_errmsg(db
), 0);
7182 #ifdef SQLITE_USER_AUTHENTICATION
7183 #include "sqlite3userauth.h"
7185 ** tclcmd: sqlite3_user_authenticate DB USERNAME PASSWORD
7187 static int SQLITE_TCLAPI
test_user_authenticate(
7188 ClientData clientData
, /* Unused */
7189 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
7190 int objc
, /* Number of arguments */
7191 Tcl_Obj
*CONST objv
[] /* Command arguments */
7200 Tcl_WrongNumArgs(interp
, 1, objv
, "DB USERNAME PASSWORD");
7203 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ){
7206 zUser
= Tcl_GetString(objv
[2]);
7207 zPasswd
= Tcl_GetStringFromObj(objv
[3], &nPasswd
);
7208 rc
= sqlite3_user_authenticate(db
, zUser
, zPasswd
, nPasswd
);
7209 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), TCL_STATIC
);
7212 #endif /* SQLITE_USER_AUTHENTICATION */
7214 #ifdef SQLITE_USER_AUTHENTICATION
7216 ** tclcmd: sqlite3_user_add DB USERNAME PASSWORD ISADMIN
7218 static int SQLITE_TCLAPI
test_user_add(
7219 ClientData clientData
, /* Unused */
7220 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
7221 int objc
, /* Number of arguments */
7222 Tcl_Obj
*CONST objv
[] /* Command arguments */
7232 Tcl_WrongNumArgs(interp
, 1, objv
, "DB USERNAME PASSWORD ISADMIN");
7235 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ){
7238 zUser
= Tcl_GetString(objv
[2]);
7239 zPasswd
= Tcl_GetStringFromObj(objv
[3], &nPasswd
);
7240 Tcl_GetBooleanFromObj(interp
, objv
[4], &isAdmin
);
7241 rc
= sqlite3_user_add(db
, zUser
, zPasswd
, nPasswd
, isAdmin
);
7242 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), TCL_STATIC
);
7245 #endif /* SQLITE_USER_AUTHENTICATION */
7247 #ifdef SQLITE_USER_AUTHENTICATION
7249 ** tclcmd: sqlite3_user_change DB USERNAME PASSWORD ISADMIN
7251 static int SQLITE_TCLAPI
test_user_change(
7252 ClientData clientData
, /* Unused */
7253 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
7254 int objc
, /* Number of arguments */
7255 Tcl_Obj
*CONST objv
[] /* Command arguments */
7265 Tcl_WrongNumArgs(interp
, 1, objv
, "DB USERNAME PASSWORD ISADMIN");
7268 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ){
7271 zUser
= Tcl_GetString(objv
[2]);
7272 zPasswd
= Tcl_GetStringFromObj(objv
[3], &nPasswd
);
7273 Tcl_GetBooleanFromObj(interp
, objv
[4], &isAdmin
);
7274 rc
= sqlite3_user_change(db
, zUser
, zPasswd
, nPasswd
, isAdmin
);
7275 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), TCL_STATIC
);
7278 #endif /* SQLITE_USER_AUTHENTICATION */
7280 #ifdef SQLITE_USER_AUTHENTICATION
7282 ** tclcmd: sqlite3_user_delete DB USERNAME
7284 static int SQLITE_TCLAPI
test_user_delete(
7285 ClientData clientData
, /* Unused */
7286 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
7287 int objc
, /* Number of arguments */
7288 Tcl_Obj
*CONST objv
[] /* Command arguments */
7295 Tcl_WrongNumArgs(interp
, 1, objv
, "DB USERNAME");
7298 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ){
7301 zUser
= Tcl_GetString(objv
[2]);
7302 rc
= sqlite3_user_delete(db
, zUser
);
7303 Tcl_SetResult(interp
, (char *)t1ErrorName(rc
), TCL_STATIC
);
7306 #endif /* SQLITE_USER_AUTHENTICATION */
7309 ** tclcmd: bad_behavior TYPE
7311 ** Do some things that should trigger a valgrind or -fsanitize=undefined
7312 ** warning. This is used to verify that errors and warnings output by those
7313 ** tools are detected by the test scripts.
7316 ** 1 Overflow a signed integer
7317 ** 2 Jump based on an uninitialized variable
7318 ** 3 Read after free
7321 static int SQLITE_TCLAPI
test_bad_behavior(
7322 ClientData clientData
, /* Pointer to an integer containing zero */
7323 Tcl_Interp
*interp
, /* The TCL interpreter that invoked this command */
7324 int objc
, /* Number of arguments */
7325 Tcl_Obj
*CONST objv
[] /* Command arguments */
7329 int i
= *(int*)clientData
;
7334 Tcl_WrongNumArgs(interp
, 1, objv
, "TYPE");
7337 if( Tcl_GetIntFromObj(interp
, objv
[1], &iType
) ) return TCL_ERROR
;
7340 xyz
= 0x7fffff00 - i
;
7342 Tcl_SetObjResult(interp
, Tcl_NewIntObj(xyz
));
7347 if( w
[i
]>0 ) w
[1]++;
7348 Tcl_SetObjResult(interp
, Tcl_NewIntObj(w
[1]));
7352 a
= malloc( sizeof(int)*10 );
7353 for(j
=0; j
<10; j
++) a
[j
] = j
;
7355 Tcl_SetObjResult(interp
, Tcl_NewIntObj(a
[i
]));
7359 Tcl_Panic("Deliberate panic");
7367 ** tclcmd: register_dbstat_vtab DB
7369 ** Cause the dbstat virtual table to be available on the connection DB
7371 static int SQLITE_TCLAPI
test_register_dbstat_vtab(
7375 Tcl_Obj
*CONST objv
[]
7377 #ifdef SQLITE_OMIT_VIRTUALTABLE
7378 Tcl_AppendResult(interp
, "dbstat not available because of "
7379 "SQLITE_OMIT_VIRTUALTABLE", (void*)0);
7382 struct SqliteDb
{ sqlite3
*db
; };
7384 Tcl_CmdInfo cmdInfo
;
7387 Tcl_WrongNumArgs(interp
, 1, objv
, "DB");
7391 zDb
= Tcl_GetString(objv
[1]);
7392 if( Tcl_GetCommandInfo(interp
, zDb
, &cmdInfo
) ){
7393 sqlite3
* db
= ((struct SqliteDb
*)cmdInfo
.objClientData
)->db
;
7394 sqlite3DbstatRegister(db
);
7397 #endif /* SQLITE_OMIT_VIRTUALTABLE */
7401 ** tclcmd: sqlite3_db_config DB SETTING VALUE
7403 ** Invoke sqlite3_db_config() for one of the setting values.
7405 static int SQLITE_TCLAPI
test_sqlite3_db_config(
7409 Tcl_Obj
*CONST objv
[]
7411 static const struct {
7415 { "FKEY", SQLITE_DBCONFIG_ENABLE_FKEY
},
7416 { "TRIGGER", SQLITE_DBCONFIG_ENABLE_TRIGGER
},
7417 { "FTS3_TOKENIZER", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
},
7418 { "LOAD_EXTENSION", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION
},
7419 { "NO_CKPT_ON_CLOSE",SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
},
7420 { "QPSG", SQLITE_DBCONFIG_ENABLE_QPSG
},
7421 { "TRIGGER_EQP", SQLITE_DBCONFIG_TRIGGER_EQP
},
7422 { "RESET_DB", SQLITE_DBCONFIG_RESET_DATABASE
},
7426 const char *zSetting
;
7430 Tcl_WrongNumArgs(interp
, 1, objv
, "DB SETTING VALUE");
7433 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
7434 zSetting
= Tcl_GetString(objv
[2]);
7435 if( sqlite3_strglob("SQLITE_*", zSetting
)==0 ) zSetting
+= 7;
7436 if( sqlite3_strglob("DBCONFIG_*", zSetting
)==0 ) zSetting
+= 9;
7437 if( sqlite3_strglob("ENABLE_*", zSetting
)==0 ) zSetting
+= 7;
7438 for(i
=0; i
<ArraySize(aSetting
); i
++){
7439 if( strcmp(zSetting
, aSetting
[i
].zName
)==0 ) break;
7441 if( i
>=ArraySize(aSetting
) ){
7442 Tcl_SetObjResult(interp
,
7443 Tcl_NewStringObj("unknown sqlite3_db_config setting", -1));
7446 if( Tcl_GetIntFromObj(interp
, objv
[3], &v
) ) return TCL_ERROR
;
7447 sqlite3_db_config(db
, aSetting
[i
].eVal
, v
, &v
);
7448 Tcl_SetObjResult(interp
, Tcl_NewIntObj(v
));
7453 ** Change the name of the main database schema from "main" to "icecube".
7455 static int SQLITE_TCLAPI
test_dbconfig_maindbname_icecube(
7459 Tcl_Obj
*CONST objv
[]
7463 extern int getDbPointer(Tcl_Interp
*, const char*, sqlite3
**);
7465 Tcl_WrongNumArgs(interp
, 1, objv
, "DB");
7468 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
7469 rc
= sqlite3_db_config(db
, SQLITE_DBCONFIG_MAINDBNAME
, "icecube");
7470 Tcl_SetObjResult(interp
, Tcl_NewIntObj(rc
));
7476 ** Usage: sqlite3_mmap_warm DB DBNAME
7478 static int SQLITE_TCLAPI
test_mmap_warm(
7482 Tcl_Obj
*CONST objv
[]
7484 extern int getDbPointer(Tcl_Interp
*, const char*, sqlite3
**);
7485 extern int sqlite3_mmap_warm(sqlite3
*db
, const char *);
7487 if( objc
!=2 && objc
!=3 ){
7488 Tcl_WrongNumArgs(interp
, 1, objv
, "DB ?DBNAME?");
7493 const char *zDb
= 0;
7494 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
7496 zDb
= Tcl_GetString(objv
[2]);
7498 rc
= sqlite3_mmap_warm(db
, zDb
);
7499 Tcl_SetObjResult(interp
, Tcl_NewStringObj(sqlite3ErrName(rc
), -1));
7505 ** Register commands with the TCL interpreter.
7507 int Sqlitetest1_Init(Tcl_Interp
*interp
){
7508 extern int sqlite3_search_count
;
7509 extern int sqlite3_found_count
;
7510 extern int sqlite3_interrupt_count
;
7511 extern int sqlite3_open_file_count
;
7512 extern int sqlite3_sort_count
;
7513 extern int sqlite3_current_time
;
7514 #if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
7515 extern int sqlite3_hostid_num
;
7517 extern int sqlite3_max_blobsize
;
7518 extern int SQLITE_TCLAPI
sqlite3BtreeSharedCacheReport(void*,
7519 Tcl_Interp
*,int,Tcl_Obj
*CONST
*);
7520 static int iZero
= 0;
7525 { "db_enter", (Tcl_CmdProc
*)db_enter
},
7526 { "db_leave", (Tcl_CmdProc
*)db_leave
},
7527 { "sqlite3_mprintf_int", (Tcl_CmdProc
*)sqlite3_mprintf_int
},
7528 { "sqlite3_mprintf_int64", (Tcl_CmdProc
*)sqlite3_mprintf_int64
},
7529 { "sqlite3_mprintf_long", (Tcl_CmdProc
*)sqlite3_mprintf_long
},
7530 { "sqlite3_mprintf_str", (Tcl_CmdProc
*)sqlite3_mprintf_str
},
7531 { "sqlite3_snprintf_str", (Tcl_CmdProc
*)sqlite3_snprintf_str
},
7532 { "sqlite3_mprintf_stronly", (Tcl_CmdProc
*)sqlite3_mprintf_stronly
},
7533 { "sqlite3_mprintf_double", (Tcl_CmdProc
*)sqlite3_mprintf_double
},
7534 { "sqlite3_mprintf_scaled", (Tcl_CmdProc
*)sqlite3_mprintf_scaled
},
7535 { "sqlite3_mprintf_hexdouble", (Tcl_CmdProc
*)sqlite3_mprintf_hexdouble
},
7536 { "sqlite3_mprintf_z_test", (Tcl_CmdProc
*)test_mprintf_z
},
7537 { "sqlite3_mprintf_n_test", (Tcl_CmdProc
*)test_mprintf_n
},
7538 { "sqlite3_snprintf_int", (Tcl_CmdProc
*)test_snprintf_int
},
7539 { "sqlite3_last_insert_rowid", (Tcl_CmdProc
*)test_last_rowid
},
7540 { "sqlite3_exec_printf", (Tcl_CmdProc
*)test_exec_printf
},
7541 { "sqlite3_exec_hex", (Tcl_CmdProc
*)test_exec_hex
},
7542 { "sqlite3_exec", (Tcl_CmdProc
*)test_exec
},
7543 { "sqlite3_exec_nr", (Tcl_CmdProc
*)test_exec_nr
},
7544 #ifndef SQLITE_OMIT_GET_TABLE
7545 { "sqlite3_get_table_printf", (Tcl_CmdProc
*)test_get_table_printf
},
7547 { "sqlite3_close", (Tcl_CmdProc
*)sqlite_test_close
},
7548 { "sqlite3_close_v2", (Tcl_CmdProc
*)sqlite_test_close_v2
},
7549 { "sqlite3_create_function", (Tcl_CmdProc
*)test_create_function
},
7550 { "sqlite3_create_aggregate", (Tcl_CmdProc
*)test_create_aggregate
},
7551 { "sqlite_register_test_function", (Tcl_CmdProc
*)test_register_func
},
7552 { "sqlite_abort", (Tcl_CmdProc
*)sqlite_abort
},
7553 { "sqlite_bind", (Tcl_CmdProc
*)test_bind
},
7554 { "breakpoint", (Tcl_CmdProc
*)test_breakpoint
},
7555 { "sqlite3_key", (Tcl_CmdProc
*)test_key
},
7556 { "sqlite3_rekey", (Tcl_CmdProc
*)test_rekey
},
7557 { "sqlite_set_magic", (Tcl_CmdProc
*)sqlite_set_magic
},
7558 { "sqlite3_interrupt", (Tcl_CmdProc
*)test_interrupt
},
7559 { "sqlite_delete_function", (Tcl_CmdProc
*)delete_function
},
7560 { "sqlite_delete_collation", (Tcl_CmdProc
*)delete_collation
},
7561 { "sqlite3_get_autocommit", (Tcl_CmdProc
*)get_autocommit
},
7562 { "sqlite3_busy_timeout", (Tcl_CmdProc
*)test_busy_timeout
},
7563 { "printf", (Tcl_CmdProc
*)test_printf
},
7564 { "sqlite3IoTrace", (Tcl_CmdProc
*)test_io_trace
},
7565 { "clang_sanitize_address", (Tcl_CmdProc
*)clang_sanitize_address
},
7569 Tcl_ObjCmdProc
*xProc
;
7572 { "sqlite3_db_config", test_sqlite3_db_config
, 0 },
7573 { "bad_behavior", test_bad_behavior
, (void*)&iZero
},
7574 { "register_dbstat_vtab", test_register_dbstat_vtab
},
7575 { "sqlite3_connection_pointer", get_sqlite_pointer
, 0 },
7576 { "intarray_addr", test_intarray_addr
, 0 },
7577 { "int64array_addr", test_int64array_addr
, 0 },
7578 { "doublearray_addr", test_doublearray_addr
, 0 },
7579 { "textarray_addr", test_textarray_addr
, 0 },
7580 { "sqlite3_bind_int", test_bind_int
, 0 },
7581 { "sqlite3_bind_zeroblob", test_bind_zeroblob
, 0 },
7582 { "sqlite3_bind_zeroblob64", test_bind_zeroblob64
, 0 },
7583 { "sqlite3_bind_int64", test_bind_int64
, 0 },
7584 { "sqlite3_bind_double", test_bind_double
, 0 },
7585 { "sqlite3_bind_null", test_bind_null
,0 },
7586 { "sqlite3_bind_text", test_bind_text
,0 },
7587 { "sqlite3_bind_text16", test_bind_text16
,0 },
7588 { "sqlite3_bind_blob", test_bind_blob
,0 },
7589 { "sqlite3_bind_parameter_count", test_bind_parameter_count
, 0},
7590 { "sqlite3_bind_parameter_name", test_bind_parameter_name
, 0},
7591 { "sqlite3_bind_parameter_index", test_bind_parameter_index
, 0},
7592 { "sqlite3_clear_bindings", test_clear_bindings
, 0},
7593 { "sqlite3_sleep", test_sleep
, 0},
7594 { "sqlite3_errcode", test_errcode
,0 },
7595 { "sqlite3_extended_errcode", test_ex_errcode
,0 },
7596 { "sqlite3_errmsg", test_errmsg
,0 },
7597 { "sqlite3_errmsg16", test_errmsg16
,0 },
7598 { "sqlite3_open", test_open
,0 },
7599 { "sqlite3_open16", test_open16
,0 },
7600 { "sqlite3_open_v2", test_open_v2
,0 },
7601 { "sqlite3_complete16", test_complete16
,0 },
7602 { "sqlite3_normalize", test_normalize
,0 },
7604 { "sqlite3_prepare", test_prepare
,0 },
7605 { "sqlite3_prepare16", test_prepare16
,0 },
7606 { "sqlite3_prepare_v2", test_prepare_v2
,0 },
7607 { "sqlite3_prepare_tkt3134", test_prepare_tkt3134
, 0},
7608 { "sqlite3_prepare16_v2", test_prepare16_v2
,0 },
7609 { "sqlite3_finalize", test_finalize
,0 },
7610 { "sqlite3_stmt_status", test_stmt_status
,0 },
7611 { "sqlite3_reset", test_reset
,0 },
7612 { "sqlite3_expired", test_expired
,0 },
7613 { "sqlite3_transfer_bindings", test_transfer_bind
,0 },
7614 { "sqlite3_changes", test_changes
,0 },
7615 { "sqlite3_step", test_step
,0 },
7616 { "sqlite3_sql", test_sql
,0 },
7617 { "sqlite3_expanded_sql", test_ex_sql
,0 },
7618 { "sqlite3_next_stmt", test_next_stmt
,0 },
7619 { "sqlite3_stmt_readonly", test_stmt_readonly
,0 },
7620 { "sqlite3_stmt_busy", test_stmt_busy
,0 },
7621 { "uses_stmt_journal", uses_stmt_journal
,0 },
7623 { "sqlite3_release_memory", test_release_memory
, 0},
7624 { "sqlite3_db_release_memory", test_db_release_memory
, 0},
7625 { "sqlite3_db_cacheflush", test_db_cacheflush
, 0},
7626 { "sqlite3_system_errno", test_system_errno
, 0},
7627 { "sqlite3_db_filename", test_db_filename
, 0},
7628 { "sqlite3_db_readonly", test_db_readonly
, 0},
7629 { "sqlite3_soft_heap_limit", test_soft_heap_limit
, 0},
7630 { "sqlite3_thread_cleanup", test_thread_cleanup
, 0},
7631 { "sqlite3_pager_refcounts", test_pager_refcounts
, 0},
7633 { "sqlite3_load_extension", test_load_extension
, 0},
7634 { "sqlite3_enable_load_extension", test_enable_load
, 0},
7635 { "sqlite3_extended_result_codes", test_extended_result_codes
, 0},
7636 { "sqlite3_limit", test_limit
, 0},
7637 { "dbconfig_maindbname_icecube", test_dbconfig_maindbname_icecube
},
7639 { "save_prng_state", save_prng_state
, 0 },
7640 { "restore_prng_state", restore_prng_state
, 0 },
7641 { "reset_prng_state", reset_prng_state
, 0 },
7642 { "database_never_corrupt", database_never_corrupt
, 0},
7643 { "database_may_be_corrupt", database_may_be_corrupt
, 0},
7644 { "optimization_control", optimization_control
,0},
7646 { "lock_win32_file", win32_file_lock
, 0 },
7647 { "exists_win32_path", win32_exists_path
, 0 },
7648 { "find_win32_file", win32_find_file
, 0 },
7649 { "delete_win32_file", win32_delete_file
, 0 },
7650 { "make_win32_dir", win32_mkdir
, 0 },
7651 { "remove_win32_dir", win32_rmdir
, 0 },
7653 { "tcl_objproc", runAsObjProc
, 0 },
7655 /* sqlite3_column_*() API */
7656 { "sqlite3_column_count", test_column_count
,0 },
7657 { "sqlite3_data_count", test_data_count
,0 },
7658 { "sqlite3_column_type", test_column_type
,0 },
7659 { "sqlite3_column_blob", test_column_blob
,0 },
7660 { "sqlite3_column_double", test_column_double
,0 },
7661 { "sqlite3_column_int64", test_column_int64
,0 },
7662 { "sqlite3_column_text", test_stmt_utf8
, (void*)sqlite3_column_text
},
7663 { "sqlite3_column_name", test_stmt_utf8
, (void*)sqlite3_column_name
},
7664 { "sqlite3_column_int", test_stmt_int
, (void*)sqlite3_column_int
},
7665 { "sqlite3_column_bytes", test_stmt_int
, (void*)sqlite3_column_bytes
},
7666 #ifndef SQLITE_OMIT_DECLTYPE
7667 { "sqlite3_column_decltype",test_stmt_utf8
,(void*)sqlite3_column_decltype
},
7669 #ifdef SQLITE_ENABLE_COLUMN_METADATA
7670 { "sqlite3_column_database_name",test_stmt_utf8
,(void*)sqlite3_column_database_name
},
7671 { "sqlite3_column_table_name",test_stmt_utf8
,(void*)sqlite3_column_table_name
},
7672 { "sqlite3_column_origin_name",test_stmt_utf8
,(void*)sqlite3_column_origin_name
},
7675 #ifndef SQLITE_OMIT_UTF16
7676 { "sqlite3_column_bytes16", test_stmt_int
, (void*)sqlite3_column_bytes16
},
7677 { "sqlite3_column_text16", test_stmt_utf16
, (void*)sqlite3_column_text16
},
7678 { "sqlite3_column_name16", test_stmt_utf16
, (void*)sqlite3_column_name16
},
7679 { "add_alignment_test_collations", add_alignment_test_collations
, 0 },
7680 #ifndef SQLITE_OMIT_DECLTYPE
7681 { "sqlite3_column_decltype16",test_stmt_utf16
,(void*)sqlite3_column_decltype16
},
7683 #ifdef SQLITE_ENABLE_COLUMN_METADATA
7684 {"sqlite3_column_database_name16",
7685 test_stmt_utf16
, (void*)sqlite3_column_database_name16
},
7686 {"sqlite3_column_table_name16", test_stmt_utf16
, (void*)sqlite3_column_table_name16
},
7687 {"sqlite3_column_origin_name16", test_stmt_utf16
, (void*)sqlite3_column_origin_name16
},
7690 { "sqlite3_create_collation_v2", test_create_collation_v2
, 0 },
7691 { "sqlite3_global_recover", test_global_recover
, 0 },
7692 { "working_64bit_int", working_64bit_int
, 0 },
7693 { "vfs_unlink_test", vfs_unlink_test
, 0 },
7694 { "vfs_initfail_test", vfs_initfail_test
, 0 },
7695 { "vfs_unregister_all", vfs_unregister_all
, 0 },
7696 { "vfs_reregister_all", vfs_reregister_all
, 0 },
7697 { "file_control_test", file_control_test
, 0 },
7698 { "file_control_lasterrno_test", file_control_lasterrno_test
, 0 },
7699 { "file_control_lockproxy_test", file_control_lockproxy_test
, 0 },
7700 { "file_control_chunksize_test", file_control_chunksize_test
, 0 },
7701 { "file_control_sizehint_test", file_control_sizehint_test
, 0 },
7703 { "file_control_win32_av_retry", file_control_win32_av_retry
, 0 },
7704 { "file_control_win32_get_handle", file_control_win32_get_handle
, 0 },
7705 { "file_control_win32_set_handle", file_control_win32_set_handle
, 0 },
7707 { "file_control_persist_wal", file_control_persist_wal
, 0 },
7708 { "file_control_powersafe_overwrite",file_control_powersafe_overwrite
,0},
7709 { "file_control_vfsname", file_control_vfsname
, 0 },
7710 { "file_control_tempfilename", file_control_tempfilename
, 0 },
7711 { "sqlite3_vfs_list", vfs_list
, 0 },
7712 { "sqlite3_create_function_v2", test_create_function_v2
, 0 },
7714 /* Functions from os.h */
7715 #ifndef SQLITE_OMIT_UTF16
7716 { "add_test_collate", test_collate
, 0 },
7717 { "add_test_collate_needed", test_collate_needed
, 0 },
7718 { "add_test_function", test_function
, 0 },
7719 { "add_test_utf16bin_collate", test_utf16bin_collate
, 0 },
7721 { "sqlite3_test_errstr", test_errstr
, 0 },
7722 { "tcl_variable_type", tcl_variable_type
, 0 },
7723 #ifndef SQLITE_OMIT_SHARED_CACHE
7724 { "sqlite3_enable_shared_cache", test_enable_shared
, 0 },
7725 { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport
, 0},
7727 { "sqlite3_libversion_number", test_libversion_number
, 0 },
7728 { "sqlite3_table_column_metadata", test_table_column_metadata
, 0 },
7729 #ifndef SQLITE_OMIT_INCRBLOB
7730 { "sqlite3_blob_reopen", test_blob_reopen
, 0 },
7732 { "pcache_stats", test_pcache_stats
, 0 },
7733 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
7734 { "sqlite3_unlock_notify", test_unlock_notify
, 0 },
7736 { "sqlite3_wal_checkpoint", test_wal_checkpoint
, 0 },
7737 { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2
, 0 },
7738 { "sqlite3_wal_autocheckpoint",test_wal_autocheckpoint
, 0 },
7739 { "test_sqlite3_log", test_sqlite3_log
, 0 },
7740 #ifndef SQLITE_OMIT_EXPLAIN
7741 { "print_explain_query_plan", test_print_eqp
, 0 },
7743 { "sqlite3_test_control", test_test_control
},
7745 { "getrusage", test_getrusage
},
7747 { "load_static_extension", tclLoadStaticExtensionCmd
},
7748 { "sorter_test_fakeheap", sorter_test_fakeheap
},
7749 { "sorter_test_sort4_helper", sorter_test_sort4_helper
},
7750 #ifdef SQLITE_USER_AUTHENTICATION
7751 { "sqlite3_user_authenticate", test_user_authenticate
, 0 },
7752 { "sqlite3_user_add", test_user_add
, 0 },
7753 { "sqlite3_user_change", test_user_change
, 0 },
7754 { "sqlite3_user_delete", test_user_delete
, 0 },
7756 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
7757 { "sqlite3_stmt_scanstatus", test_stmt_scanstatus
, 0 },
7758 { "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset
, 0 },
7760 #ifdef SQLITE_ENABLE_SQLLOG
7761 { "sqlite3_config_sqllog", test_config_sqllog
, 0 },
7763 { "vfs_current_time_int64", vfsCurrentTimeInt64
, 0 },
7764 #ifdef SQLITE_ENABLE_SNAPSHOT
7765 { "sqlite3_snapshot_get", test_snapshot_get
, 0 },
7766 { "sqlite3_snapshot_open", test_snapshot_open
, 0 },
7767 { "sqlite3_snapshot_free", test_snapshot_free
, 0 },
7768 { "sqlite3_snapshot_cmp", test_snapshot_cmp
, 0 },
7769 { "sqlite3_snapshot_recover", test_snapshot_recover
, 0 },
7770 { "sqlite3_snapshot_get_blob", test_snapshot_get_blob
, 0 },
7771 { "sqlite3_snapshot_open_blob", test_snapshot_open_blob
, 0 },
7772 { "sqlite3_snapshot_cmp_blob", test_snapshot_cmp_blob
, 0 },
7774 { "sqlite3_delete_database", test_delete_database
, 0 },
7775 { "atomic_batch_write", test_atomic_batch_write
, 0 },
7776 { "sqlite3_mmap_warm", test_mmap_warm
, 0 },
7777 { "sqlite3_config_sorterref", test_config_sorterref
, 0 },
7779 static int bitmask_size
= sizeof(Bitmask
)*8;
7780 static int longdouble_size
= sizeof(LONGDOUBLE_TYPE
);
7782 extern int sqlite3_sync_count
, sqlite3_fullsync_count
;
7783 extern int sqlite3_opentemp_count
;
7784 extern int sqlite3_like_count
;
7785 extern int sqlite3_xferopt_count
;
7786 extern int sqlite3_pager_readdb_count
;
7787 extern int sqlite3_pager_writedb_count
;
7788 extern int sqlite3_pager_writej_count
;
7790 extern LONG
volatile sqlite3_os_type
;
7793 extern int sqlite3WhereTrace
;
7794 extern int sqlite3OSTrace
;
7795 extern int sqlite3WalTrace
;
7798 #ifdef SQLITE_ENABLE_FTS3
7799 extern int sqlite3_fts3_enable_parentheses
;
7802 #if defined(SQLITE_ENABLE_SELECTTRACE)
7803 extern int sqlite3SelectTrace
;
7806 for(i
=0; i
<sizeof(aCmd
)/sizeof(aCmd
[0]); i
++){
7807 Tcl_CreateCommand(interp
, aCmd
[i
].zName
, aCmd
[i
].xProc
, 0, 0);
7809 for(i
=0; i
<sizeof(aObjCmd
)/sizeof(aObjCmd
[0]); i
++){
7810 Tcl_CreateObjCommand(interp
, aObjCmd
[i
].zName
,
7811 aObjCmd
[i
].xProc
, aObjCmd
[i
].clientData
, 0);
7813 Tcl_LinkVar(interp
, "sqlite_search_count",
7814 (char*)&sqlite3_search_count
, TCL_LINK_INT
);
7815 Tcl_LinkVar(interp
, "sqlite_found_count",
7816 (char*)&sqlite3_found_count
, TCL_LINK_INT
);
7817 Tcl_LinkVar(interp
, "sqlite_sort_count",
7818 (char*)&sqlite3_sort_count
, TCL_LINK_INT
);
7819 Tcl_LinkVar(interp
, "sqlite3_max_blobsize",
7820 (char*)&sqlite3_max_blobsize
, TCL_LINK_INT
);
7821 Tcl_LinkVar(interp
, "sqlite_like_count",
7822 (char*)&sqlite3_like_count
, TCL_LINK_INT
);
7823 Tcl_LinkVar(interp
, "sqlite_interrupt_count",
7824 (char*)&sqlite3_interrupt_count
, TCL_LINK_INT
);
7825 Tcl_LinkVar(interp
, "sqlite_open_file_count",
7826 (char*)&sqlite3_open_file_count
, TCL_LINK_INT
);
7827 Tcl_LinkVar(interp
, "sqlite_current_time",
7828 (char*)&sqlite3_current_time
, TCL_LINK_INT
);
7829 #if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
7830 Tcl_LinkVar(interp
, "sqlite_hostid_num",
7831 (char*)&sqlite3_hostid_num
, TCL_LINK_INT
);
7833 Tcl_LinkVar(interp
, "sqlite3_xferopt_count",
7834 (char*)&sqlite3_xferopt_count
, TCL_LINK_INT
);
7835 Tcl_LinkVar(interp
, "sqlite3_pager_readdb_count",
7836 (char*)&sqlite3_pager_readdb_count
, TCL_LINK_INT
);
7837 Tcl_LinkVar(interp
, "sqlite3_pager_writedb_count",
7838 (char*)&sqlite3_pager_writedb_count
, TCL_LINK_INT
);
7839 Tcl_LinkVar(interp
, "sqlite3_pager_writej_count",
7840 (char*)&sqlite3_pager_writej_count
, TCL_LINK_INT
);
7841 #ifndef SQLITE_OMIT_UTF16
7842 Tcl_LinkVar(interp
, "unaligned_string_counter",
7843 (char*)&unaligned_string_counter
, TCL_LINK_INT
);
7845 #ifndef SQLITE_OMIT_UTF16
7846 Tcl_LinkVar(interp
, "sqlite_last_needed_collation",
7847 (char*)&pzNeededCollation
, TCL_LINK_STRING
|TCL_LINK_READ_ONLY
);
7850 Tcl_LinkVar(interp
, "sqlite_os_type",
7851 (char*)&sqlite3_os_type
, TCL_LINK_LONG
);
7855 static const char *query_plan
= "*** OBSOLETE VARIABLE ***";
7856 Tcl_LinkVar(interp
, "sqlite_query_plan",
7857 (char*)&query_plan
, TCL_LINK_STRING
|TCL_LINK_READ_ONLY
);
7861 Tcl_LinkVar(interp
, "sqlite_where_trace",
7862 (char*)&sqlite3WhereTrace
, TCL_LINK_INT
);
7863 Tcl_LinkVar(interp
, "sqlite_os_trace",
7864 (char*)&sqlite3OSTrace
, TCL_LINK_INT
);
7865 #ifndef SQLITE_OMIT_WAL
7866 Tcl_LinkVar(interp
, "sqlite_wal_trace",
7867 (char*)&sqlite3WalTrace
, TCL_LINK_INT
);
7870 #ifndef SQLITE_OMIT_DISKIO
7871 Tcl_LinkVar(interp
, "sqlite_opentemp_count",
7872 (char*)&sqlite3_opentemp_count
, TCL_LINK_INT
);
7874 Tcl_LinkVar(interp
, "sqlite_static_bind_value",
7875 (char*)&sqlite_static_bind_value
, TCL_LINK_STRING
);
7876 Tcl_LinkVar(interp
, "sqlite_static_bind_nbyte",
7877 (char*)&sqlite_static_bind_nbyte
, TCL_LINK_INT
);
7878 Tcl_LinkVar(interp
, "sqlite_temp_directory",
7879 (char*)&sqlite3_temp_directory
, TCL_LINK_STRING
);
7880 Tcl_LinkVar(interp
, "sqlite_data_directory",
7881 (char*)&sqlite3_data_directory
, TCL_LINK_STRING
);
7882 Tcl_LinkVar(interp
, "bitmask_size",
7883 (char*)&bitmask_size
, TCL_LINK_INT
|TCL_LINK_READ_ONLY
);
7884 Tcl_LinkVar(interp
, "longdouble_size",
7885 (char*)&longdouble_size
, TCL_LINK_INT
|TCL_LINK_READ_ONLY
);
7886 Tcl_LinkVar(interp
, "sqlite_sync_count",
7887 (char*)&sqlite3_sync_count
, TCL_LINK_INT
);
7888 Tcl_LinkVar(interp
, "sqlite_fullsync_count",
7889 (char*)&sqlite3_fullsync_count
, TCL_LINK_INT
);
7890 #if defined(SQLITE_ENABLE_SELECTTRACE)
7891 Tcl_LinkVar(interp
, "sqlite3SelectTrace",
7892 (char*)&sqlite3SelectTrace
, TCL_LINK_INT
);
7894 #if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST)
7895 Tcl_LinkVar(interp
, "sqlite_fts3_enable_parentheses",
7896 (char*)&sqlite3_fts3_enable_parentheses
, TCL_LINK_INT
);