xref: /sqlite-3.40.0/src/test1.c (revision aef0bf64)
1d1bf3512Sdrh /*
2b19a2bc6Sdrh ** 2001 September 15
3d1bf3512Sdrh **
4b19a2bc6Sdrh ** The author disclaims copyright to this source code.  In place of
5b19a2bc6Sdrh ** a legal notice, here is a blessing:
6d1bf3512Sdrh **
7b19a2bc6Sdrh **    May you do good and not evil.
8b19a2bc6Sdrh **    May you find forgiveness for yourself and forgive others.
9b19a2bc6Sdrh **    May you share freely, never taking more than you give.
10d1bf3512Sdrh **
11d1bf3512Sdrh *************************************************************************
12d1bf3512Sdrh ** Code for testing the printf() interface to SQLite.  This code
13d1bf3512Sdrh ** is not included in the SQLite library.  It is used for automated
14d1bf3512Sdrh ** testing of the SQLite library.
15d1bf3512Sdrh **
16*aef0bf64Sdanielk1977 ** $Id: test1.c,v 1.178 2005/12/30 16:28:02 danielk1977 Exp $
17d1bf3512Sdrh */
18d1bf3512Sdrh #include "sqliteInt.h"
19d1bf3512Sdrh #include "tcl.h"
2094e92032Sdrh #include "os.h"
21d1bf3512Sdrh #include <stdlib.h>
22d1bf3512Sdrh #include <string.h>
23d1bf3512Sdrh 
242e66f0b9Sdrh const char *sqlite3TestErrorName(int rc){
256622cce3Sdanielk1977   const char *zName = 0;
266622cce3Sdanielk1977   switch( rc ){
276622cce3Sdanielk1977     case SQLITE_OK:         zName = "SQLITE_OK";          break;
286622cce3Sdanielk1977     case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break;
296622cce3Sdanielk1977     case SQLITE_PERM:       zName = "SQLITE_PERM";        break;
306622cce3Sdanielk1977     case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break;
316622cce3Sdanielk1977     case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break;
326622cce3Sdanielk1977     case SQLITE_LOCKED:     zName = "SQLITE_LOCKED";      break;
336622cce3Sdanielk1977     case SQLITE_NOMEM:      zName = "SQLITE_NOMEM";       break;
346622cce3Sdanielk1977     case SQLITE_READONLY:   zName = "SQLITE_READONLY";    break;
356622cce3Sdanielk1977     case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break;
366622cce3Sdanielk1977     case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break;
376622cce3Sdanielk1977     case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break;
386622cce3Sdanielk1977     case SQLITE_FULL:       zName = "SQLITE_FULL";        break;
396622cce3Sdanielk1977     case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break;
406622cce3Sdanielk1977     case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break;
416622cce3Sdanielk1977     case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break;
426622cce3Sdanielk1977     case SQLITE_SCHEMA:     zName = "SQLITE_SCHEMA";      break;
436622cce3Sdanielk1977     case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT";  break;
446622cce3Sdanielk1977     case SQLITE_MISMATCH:   zName = "SQLITE_MISMATCH";    break;
456622cce3Sdanielk1977     case SQLITE_MISUSE:     zName = "SQLITE_MISUSE";      break;
466622cce3Sdanielk1977     case SQLITE_NOLFS:      zName = "SQLITE_NOLFS";       break;
476622cce3Sdanielk1977     case SQLITE_AUTH:       zName = "SQLITE_AUTH";        break;
486622cce3Sdanielk1977     case SQLITE_FORMAT:     zName = "SQLITE_FORMAT";      break;
496622cce3Sdanielk1977     case SQLITE_RANGE:      zName = "SQLITE_RANGE";       break;
506622cce3Sdanielk1977     case SQLITE_ROW:        zName = "SQLITE_ROW";         break;
516622cce3Sdanielk1977     case SQLITE_DONE:       zName = "SQLITE_DONE";        break;
52312d6b36Sdanielk1977     case SQLITE_NOTADB:     zName = "SQLITE_NOTADB";      break;
536622cce3Sdanielk1977     default:                zName = "SQLITE_Unknown";     break;
546622cce3Sdanielk1977   }
556622cce3Sdanielk1977   return zName;
566622cce3Sdanielk1977 }
572e66f0b9Sdrh #define errorName sqlite3TestErrorName
586622cce3Sdanielk1977 
59d1bf3512Sdrh /*
60c60d0446Sdrh ** Convert an sqlite3_stmt* into an sqlite3*.  This depends on the
61c60d0446Sdrh ** fact that the sqlite3* is the first field in the Vdbe structure.
62c60d0446Sdrh */
6351942bc3Sdrh #define StmtToDb(X)   sqlite3_db_handle(X)
64c60d0446Sdrh 
65c60d0446Sdrh /*
66c60d0446Sdrh ** Check a return value to make sure it agrees with the results
67c60d0446Sdrh ** from sqlite3_errcode.
68c60d0446Sdrh */
69c60d0446Sdrh int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
70c60d0446Sdrh   if( rc!=SQLITE_MISUSE && rc!=SQLITE_OK && sqlite3_errcode(db)!=rc ){
71c60d0446Sdrh     char zBuf[200];
72c60d0446Sdrh     int r2 = sqlite3_errcode(db);
73c60d0446Sdrh     sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)",
74c60d0446Sdrh        errorName(rc), rc, errorName(r2), r2);
75c60d0446Sdrh     Tcl_ResetResult(interp);
76c60d0446Sdrh     Tcl_AppendResult(interp, zBuf, 0);
77c60d0446Sdrh     return 1;
78c60d0446Sdrh   }
79c60d0446Sdrh   return 0;
80c60d0446Sdrh }
81c60d0446Sdrh 
82c60d0446Sdrh /*
839bb575fdSdrh ** Decode a pointer to an sqlite3 object.
84b86ccfb2Sdrh */
859bb575fdSdrh static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
86fe63d1c9Sdrh   *ppDb = (sqlite3*)sqlite3TextToPtr(zA);
87b86ccfb2Sdrh   return TCL_OK;
88b86ccfb2Sdrh }
89b86ccfb2Sdrh 
90b86ccfb2Sdrh /*
9151e3d8e2Sdanielk1977 ** Decode a pointer to an sqlite3_stmt object.
9251e3d8e2Sdanielk1977 */
9351e3d8e2Sdanielk1977 static int getStmtPointer(
9451e3d8e2Sdanielk1977   Tcl_Interp *interp,
9551e3d8e2Sdanielk1977   const char *zArg,
9651e3d8e2Sdanielk1977   sqlite3_stmt **ppStmt
9751e3d8e2Sdanielk1977 ){
98fe63d1c9Sdrh   *ppStmt = (sqlite3_stmt*)sqlite3TextToPtr(zArg);
9951e3d8e2Sdanielk1977   return TCL_OK;
10051e3d8e2Sdanielk1977 }
10151e3d8e2Sdanielk1977 
10251e3d8e2Sdanielk1977 /*
1039a1d0abeSdanielk1977 ** Decode a pointer to an sqlite3_stmt object.
1049a1d0abeSdanielk1977 */
1059a1d0abeSdanielk1977 static int getFilePointer(
1069a1d0abeSdanielk1977   Tcl_Interp *interp,
1079a1d0abeSdanielk1977   const char *zArg,
1089a1d0abeSdanielk1977   OsFile **ppFile
1099a1d0abeSdanielk1977 ){
110fe63d1c9Sdrh   *ppFile = (OsFile*)sqlite3TextToPtr(zArg);
1119a1d0abeSdanielk1977   return TCL_OK;
1129a1d0abeSdanielk1977 }
1139a1d0abeSdanielk1977 
1149a1d0abeSdanielk1977 /*
1157d8085a8Sdrh ** Generate a text representation of a pointer that can be understood
1167d8085a8Sdrh ** by the getDbPointer and getVmPointer routines above.
1177d8085a8Sdrh **
1187d8085a8Sdrh ** The problem is, on some machines (Solaris) if you do a printf with
1197d8085a8Sdrh ** "%p" you cannot turn around and do a scanf with the same "%p" and
1207d8085a8Sdrh ** get your pointer back.  You have to prepend a "0x" before it will
1217d8085a8Sdrh ** work.  Or at least that is what is reported to me (drh).  But this
1227d8085a8Sdrh ** behavior varies from machine to machine.  The solution used her is
1237d8085a8Sdrh ** to test the string right after it is generated to see if it can be
1247d8085a8Sdrh ** understood by scanf, and if not, try prepending an "0x" to see if
1257d8085a8Sdrh ** that helps.  If nothing works, a fatal error is generated.
1267d8085a8Sdrh */
1277d8085a8Sdrh static int makePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
128fe63d1c9Sdrh   sqlite3_snprintf(100, zPtr, "%p", p);
1297d8085a8Sdrh   return TCL_OK;
1307d8085a8Sdrh }
1317d8085a8Sdrh 
1327d8085a8Sdrh /*
1336f8a503dSdanielk1977 ** The callback routine for sqlite3_exec_printf().
134d1bf3512Sdrh */
135d1bf3512Sdrh static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
136d1bf3512Sdrh   Tcl_DString *str = (Tcl_DString*)pArg;
137d1bf3512Sdrh   int i;
138d1bf3512Sdrh 
139d1bf3512Sdrh   if( Tcl_DStringLength(str)==0 ){
140d1bf3512Sdrh     for(i=0; i<argc; i++){
141d1bf3512Sdrh       Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
142d1bf3512Sdrh     }
143d1bf3512Sdrh   }
144d1bf3512Sdrh   for(i=0; i<argc; i++){
145d1bf3512Sdrh     Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
146d1bf3512Sdrh   }
147d1bf3512Sdrh   return 0;
148d1bf3512Sdrh }
149d1bf3512Sdrh 
150d1bf3512Sdrh /*
1516f8a503dSdanielk1977 ** Usage:  sqlite3_exec_printf  DB  FORMAT  STRING
152d1bf3512Sdrh **
1536f8a503dSdanielk1977 ** Invoke the sqlite3_exec_printf() interface using the open database
154d1bf3512Sdrh ** DB.  The SQL is the string FORMAT.  The format string should contain
155d1bf3512Sdrh ** one %s or %q.  STRING is the value inserted into %s or %q.
156d1bf3512Sdrh */
157d1bf3512Sdrh static int test_exec_printf(
158d1bf3512Sdrh   void *NotUsed,
159d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
160d1bf3512Sdrh   int argc,              /* Number of arguments */
161d1bf3512Sdrh   char **argv            /* Text of each argument */
162d1bf3512Sdrh ){
1639bb575fdSdrh   sqlite3 *db;
164d1bf3512Sdrh   Tcl_DString str;
165d1bf3512Sdrh   int rc;
166d1bf3512Sdrh   char *zErr = 0;
1671211de37Sdrh   char *zSql;
168d1bf3512Sdrh   char zBuf[30];
169d1bf3512Sdrh   if( argc!=4 ){
170d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
171d1bf3512Sdrh        " DB FORMAT STRING", 0);
172d1bf3512Sdrh     return TCL_ERROR;
173d1bf3512Sdrh   }
174b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
175d1bf3512Sdrh   Tcl_DStringInit(&str);
1761211de37Sdrh   zSql = sqlite3_mprintf(argv[2], argv[3]);
1771211de37Sdrh   rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
1781211de37Sdrh   sqlite3_free(zSql);
179d1bf3512Sdrh   sprintf(zBuf, "%d", rc);
180d1bf3512Sdrh   Tcl_AppendElement(interp, zBuf);
181d1bf3512Sdrh   Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
182d1bf3512Sdrh   Tcl_DStringFree(&str);
183d1bf3512Sdrh   if( zErr ) free(zErr);
184c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
185d1bf3512Sdrh   return TCL_OK;
186d1bf3512Sdrh }
187d1bf3512Sdrh 
188d1bf3512Sdrh /*
1896f8a503dSdanielk1977 ** Usage:  sqlite3_mprintf_z_test  SEPARATOR  ARG0  ARG1 ...
190d93d8a81Sdrh **
191d93d8a81Sdrh ** Test the %z format of mprintf().  Use multiple mprintf() calls to
192d93d8a81Sdrh ** concatenate arg0 through argn using separator as the separator.
193d93d8a81Sdrh ** Return the result.
194d93d8a81Sdrh */
195d93d8a81Sdrh static int test_mprintf_z(
196d93d8a81Sdrh   void *NotUsed,
197d93d8a81Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
198d93d8a81Sdrh   int argc,              /* Number of arguments */
199d93d8a81Sdrh   char **argv            /* Text of each argument */
200d93d8a81Sdrh ){
201d93d8a81Sdrh   char *zResult = 0;
202d93d8a81Sdrh   int i;
203d93d8a81Sdrh 
204d93d8a81Sdrh   for(i=2; i<argc; i++){
2054adee20fSdanielk1977     zResult = sqlite3MPrintf("%z%s%s", zResult, argv[1], argv[i]);
206d93d8a81Sdrh   }
207d93d8a81Sdrh   Tcl_AppendResult(interp, zResult, 0);
2085f968436Sdrh   sqliteFree(zResult);
209d93d8a81Sdrh   return TCL_OK;
210d93d8a81Sdrh }
211d93d8a81Sdrh 
212d93d8a81Sdrh /*
2136f8a503dSdanielk1977 ** Usage:  sqlite3_get_table_printf  DB  FORMAT  STRING
214d1bf3512Sdrh **
2156f8a503dSdanielk1977 ** Invoke the sqlite3_get_table_printf() interface using the open database
216d1bf3512Sdrh ** DB.  The SQL is the string FORMAT.  The format string should contain
217d1bf3512Sdrh ** one %s or %q.  STRING is the value inserted into %s or %q.
218d1bf3512Sdrh */
219d1bf3512Sdrh static int test_get_table_printf(
220d1bf3512Sdrh   void *NotUsed,
221d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
222d1bf3512Sdrh   int argc,              /* Number of arguments */
223d1bf3512Sdrh   char **argv            /* Text of each argument */
224d1bf3512Sdrh ){
2259bb575fdSdrh   sqlite3 *db;
226d1bf3512Sdrh   Tcl_DString str;
227d1bf3512Sdrh   int rc;
228d1bf3512Sdrh   char *zErr = 0;
229d1bf3512Sdrh   int nRow, nCol;
230d1bf3512Sdrh   char **aResult;
231d1bf3512Sdrh   int i;
232d1bf3512Sdrh   char zBuf[30];
2331211de37Sdrh   char *zSql;
234d1bf3512Sdrh   if( argc!=4 ){
235d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
236d1bf3512Sdrh        " DB FORMAT STRING", 0);
237d1bf3512Sdrh     return TCL_ERROR;
238d1bf3512Sdrh   }
239b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
240d1bf3512Sdrh   Tcl_DStringInit(&str);
2411211de37Sdrh   zSql = sqlite3_mprintf(argv[2],argv[3]);
2421211de37Sdrh   rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
2431211de37Sdrh   sqlite3_free(zSql);
244d1bf3512Sdrh   sprintf(zBuf, "%d", rc);
245d1bf3512Sdrh   Tcl_AppendElement(interp, zBuf);
246d1bf3512Sdrh   if( rc==SQLITE_OK ){
247d1bf3512Sdrh     sprintf(zBuf, "%d", nRow);
248d1bf3512Sdrh     Tcl_AppendElement(interp, zBuf);
249d1bf3512Sdrh     sprintf(zBuf, "%d", nCol);
250d1bf3512Sdrh     Tcl_AppendElement(interp, zBuf);
251d1bf3512Sdrh     for(i=0; i<(nRow+1)*nCol; i++){
252d1bf3512Sdrh       Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
253d1bf3512Sdrh     }
254d1bf3512Sdrh   }else{
255d1bf3512Sdrh     Tcl_AppendElement(interp, zErr);
256d1bf3512Sdrh   }
2576f8a503dSdanielk1977   sqlite3_free_table(aResult);
258d1bf3512Sdrh   if( zErr ) free(zErr);
259c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
260d1bf3512Sdrh   return TCL_OK;
261d1bf3512Sdrh }
262d1bf3512Sdrh 
263af9ff33aSdrh 
264af9ff33aSdrh /*
2656f8a503dSdanielk1977 ** Usage:  sqlite3_last_insert_rowid DB
266af9ff33aSdrh **
267af9ff33aSdrh ** Returns the integer ROWID of the most recent insert.
268af9ff33aSdrh */
269af9ff33aSdrh static int test_last_rowid(
270af9ff33aSdrh   void *NotUsed,
271af9ff33aSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
272af9ff33aSdrh   int argc,              /* Number of arguments */
273af9ff33aSdrh   char **argv            /* Text of each argument */
274af9ff33aSdrh ){
2759bb575fdSdrh   sqlite3 *db;
276af9ff33aSdrh   char zBuf[30];
277af9ff33aSdrh 
278af9ff33aSdrh   if( argc!=2 ){
279af9ff33aSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
280af9ff33aSdrh     return TCL_ERROR;
281af9ff33aSdrh   }
282b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
283c572ef7fSdanielk1977   sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db));
284af9ff33aSdrh   Tcl_AppendResult(interp, zBuf, 0);
285af9ff33aSdrh   return SQLITE_OK;
286af9ff33aSdrh }
287af9ff33aSdrh 
288d1bf3512Sdrh /*
28925d6543dSdrh ** Usage:  sqlite3_key DB KEY
29025d6543dSdrh **
29125d6543dSdrh ** Set the codec key.
29225d6543dSdrh */
29325d6543dSdrh static int test_key(
29425d6543dSdrh   void *NotUsed,
29525d6543dSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
29625d6543dSdrh   int argc,              /* Number of arguments */
29725d6543dSdrh   char **argv            /* Text of each argument */
29825d6543dSdrh ){
2999bb575fdSdrh   sqlite3 *db;
30025d6543dSdrh   const char *zKey;
30125d6543dSdrh   int nKey;
30225d6543dSdrh   if( argc!=3 ){
30325d6543dSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
30425d6543dSdrh        " FILENAME\"", 0);
30525d6543dSdrh     return TCL_ERROR;
30625d6543dSdrh   }
30725d6543dSdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
30825d6543dSdrh   zKey = argv[2];
30925d6543dSdrh   nKey = strlen(zKey);
31025d6543dSdrh #ifdef SQLITE_HAS_CODEC
31125d6543dSdrh   sqlite3_key(db, zKey, nKey);
31225d6543dSdrh #endif
31325d6543dSdrh   return TCL_OK;
31425d6543dSdrh }
31525d6543dSdrh 
31625d6543dSdrh /*
31725d6543dSdrh ** Usage:  sqlite3_rekey DB KEY
31825d6543dSdrh **
31925d6543dSdrh ** Change the codec key.
32025d6543dSdrh */
32125d6543dSdrh static int test_rekey(
32225d6543dSdrh   void *NotUsed,
32325d6543dSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
32425d6543dSdrh   int argc,              /* Number of arguments */
32525d6543dSdrh   char **argv            /* Text of each argument */
32625d6543dSdrh ){
3279bb575fdSdrh   sqlite3 *db;
32825d6543dSdrh   const char *zKey;
32925d6543dSdrh   int nKey;
33025d6543dSdrh   if( argc!=3 ){
33125d6543dSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
33225d6543dSdrh        " FILENAME\"", 0);
33325d6543dSdrh     return TCL_ERROR;
33425d6543dSdrh   }
33525d6543dSdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
33625d6543dSdrh   zKey = argv[2];
33725d6543dSdrh   nKey = strlen(zKey);
33825d6543dSdrh #ifdef SQLITE_HAS_CODEC
33925d6543dSdrh   sqlite3_rekey(db, zKey, nKey);
34025d6543dSdrh #endif
34125d6543dSdrh   return TCL_OK;
34225d6543dSdrh }
34325d6543dSdrh 
34425d6543dSdrh /*
3456f8a503dSdanielk1977 ** Usage:  sqlite3_close DB
346d1bf3512Sdrh **
3476f8a503dSdanielk1977 ** Closes the database opened by sqlite3_open.
348d1bf3512Sdrh */
349d1bf3512Sdrh static int sqlite_test_close(
350d1bf3512Sdrh   void *NotUsed,
351d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
352d1bf3512Sdrh   int argc,              /* Number of arguments */
353d1bf3512Sdrh   char **argv            /* Text of each argument */
354d1bf3512Sdrh ){
3559bb575fdSdrh   sqlite3 *db;
35696d81f99Sdanielk1977   int rc;
357d1bf3512Sdrh   if( argc!=2 ){
358d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
359d1bf3512Sdrh        " FILENAME\"", 0);
360d1bf3512Sdrh     return TCL_ERROR;
361d1bf3512Sdrh   }
362b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
36396d81f99Sdanielk1977   rc = sqlite3_close(db);
364f9d64d2cSdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
365d1bf3512Sdrh   return TCL_OK;
366d1bf3512Sdrh }
367d1bf3512Sdrh 
368d1bf3512Sdrh /*
369c22bd47dSdrh ** Implementation of the x_coalesce() function.
370c22bd47dSdrh ** Return the first argument non-NULL argument.
371c22bd47dSdrh */
3720ae8b831Sdanielk1977 static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
373c22bd47dSdrh   int i;
374c22bd47dSdrh   for(i=0; i<argc; i++){
3759c054830Sdrh     if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
37603d847eaSdrh       sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]),
3775c434b72Sdrh           sqlite3_value_bytes(argv[i]), SQLITE_TRANSIENT);
378c22bd47dSdrh       break;
379c22bd47dSdrh     }
380c22bd47dSdrh   }
381c22bd47dSdrh }
382c22bd47dSdrh 
383c22bd47dSdrh /*
384d1d9fc33Sdrh ** A structure into which to accumulate text.
385d1d9fc33Sdrh */
386d1d9fc33Sdrh struct dstr {
387d1d9fc33Sdrh   int nAlloc;  /* Space allocated */
388d1d9fc33Sdrh   int nUsed;   /* Space used */
389d1d9fc33Sdrh   char *z;     /* The space */
390d1d9fc33Sdrh };
391d1d9fc33Sdrh 
392d1d9fc33Sdrh /*
393d1d9fc33Sdrh ** Append text to a dstr
394d1d9fc33Sdrh */
395d1d9fc33Sdrh static void dstrAppend(struct dstr *p, const char *z, int divider){
396d1d9fc33Sdrh   int n = strlen(z);
397d1d9fc33Sdrh   if( p->nUsed + n + 2 > p->nAlloc ){
398d1d9fc33Sdrh     char *zNew;
399d1d9fc33Sdrh     p->nAlloc = p->nAlloc*2 + n + 200;
400d1d9fc33Sdrh     zNew = sqliteRealloc(p->z, p->nAlloc);
401d1d9fc33Sdrh     if( zNew==0 ){
402d1d9fc33Sdrh       sqliteFree(p->z);
403d1d9fc33Sdrh       memset(p, 0, sizeof(*p));
404d1d9fc33Sdrh       return;
405d1d9fc33Sdrh     }
406d1d9fc33Sdrh     p->z = zNew;
407d1d9fc33Sdrh   }
408d1d9fc33Sdrh   if( divider && p->nUsed>0 ){
409d1d9fc33Sdrh     p->z[p->nUsed++] = divider;
410d1d9fc33Sdrh   }
411d1d9fc33Sdrh   memcpy(&p->z[p->nUsed], z, n+1);
412d1d9fc33Sdrh   p->nUsed += n;
413d1d9fc33Sdrh }
414d1d9fc33Sdrh 
415d1d9fc33Sdrh /*
4164adee20fSdanielk1977 ** Invoked for each callback from sqlite3ExecFunc
417d1d9fc33Sdrh */
418d1d9fc33Sdrh static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
419d1d9fc33Sdrh   struct dstr *p = (struct dstr*)pData;
420d1d9fc33Sdrh   int i;
421d1d9fc33Sdrh   for(i=0; i<argc; i++){
422d1d9fc33Sdrh     if( argv[i]==0 ){
423d1d9fc33Sdrh       dstrAppend(p, "NULL", ' ');
424d1d9fc33Sdrh     }else{
425d1d9fc33Sdrh       dstrAppend(p, argv[i], ' ');
426d1d9fc33Sdrh     }
427d1d9fc33Sdrh   }
428d1d9fc33Sdrh   return 0;
429d1d9fc33Sdrh }
430d1d9fc33Sdrh 
431d1d9fc33Sdrh /*
432e35ee196Sdanielk1977 ** Implementation of the x_sqlite_exec() function.  This function takes
433c22bd47dSdrh ** a single argument and attempts to execute that argument as SQL code.
4346cbe1f1bSdrh ** This is illegal and should set the SQLITE_MISUSE flag on the database.
435c22bd47dSdrh **
4366f8a503dSdanielk1977 ** 2004-Jan-07:  We have changed this to make it legal to call sqlite3_exec()
437d1d9fc33Sdrh ** from within a function call.
438d1d9fc33Sdrh **
439c22bd47dSdrh ** This routine simulates the effect of having two threads attempt to
440c22bd47dSdrh ** use the same database at the same time.
441c22bd47dSdrh */
44251ad0ecdSdanielk1977 static void sqlite3ExecFunc(
4430ae8b831Sdanielk1977   sqlite3_context *context,
44451ad0ecdSdanielk1977   int argc,
44551ad0ecdSdanielk1977   sqlite3_value **argv
44651ad0ecdSdanielk1977 ){
447d1d9fc33Sdrh   struct dstr x;
448d1d9fc33Sdrh   memset(&x, 0, sizeof(x));
4499bb575fdSdrh   sqlite3_exec((sqlite3*)sqlite3_user_data(context),
45003d847eaSdrh       (char*)sqlite3_value_text(argv[0]),
451d1d9fc33Sdrh       execFuncCallback, &x, 0);
452d8123366Sdanielk1977   sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
453d1d9fc33Sdrh   sqliteFree(x.z);
454c22bd47dSdrh }
455c22bd47dSdrh 
456c22bd47dSdrh /*
457c22bd47dSdrh ** Usage:  sqlite_test_create_function DB
458c22bd47dSdrh **
4596f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order
460c22bd47dSdrh ** to create a function named "x_coalesce".  This function does the same thing
461c22bd47dSdrh ** as the "coalesce" function.  This function also registers an SQL function
462e35ee196Sdanielk1977 ** named "x_sqlite_exec" that invokes sqlite3_exec().  Invoking sqlite3_exec()
463c22bd47dSdrh ** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
464c22bd47dSdrh ** The effect is similar to trying to use the same database connection from
465c22bd47dSdrh ** two threads at the same time.
466c22bd47dSdrh **
467c22bd47dSdrh ** The original motivation for this routine was to be able to call the
4686f8a503dSdanielk1977 ** sqlite3_create_function function while a query is in progress in order
469c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic.
470c22bd47dSdrh */
471c2eef3b3Sdrh static int test_create_function(
472c22bd47dSdrh   void *NotUsed,
473c22bd47dSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
474c22bd47dSdrh   int argc,              /* Number of arguments */
475c22bd47dSdrh   char **argv            /* Text of each argument */
476c22bd47dSdrh ){
477c60d0446Sdrh   int rc;
4789bb575fdSdrh   sqlite3 *db;
4799bb575fdSdrh   extern void Md5_Register(sqlite3*);
480312d6b36Sdanielk1977 
481c22bd47dSdrh   if( argc!=2 ){
482c22bd47dSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4834397de57Sdanielk1977        " DB\"", 0);
484c22bd47dSdrh     return TCL_ERROR;
485c22bd47dSdrh   }
486b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
487c60d0446Sdrh   rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,
488d8123366Sdanielk1977         ifnullFunc, 0, 0);
489312d6b36Sdanielk1977 
4905436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
491312d6b36Sdanielk1977   /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
492312d6b36Sdanielk1977   ** because it is not tested anywhere else. */
493c60d0446Sdrh   if( rc==SQLITE_OK ){
494576ec6b3Sdanielk1977     sqlite3_value *pVal;
495312d6b36Sdanielk1977     pVal = sqlite3ValueNew();
496312d6b36Sdanielk1977     sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
497c60d0446Sdrh     rc = sqlite3_create_function16(db,
498c60d0446Sdrh               sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),
499312d6b36Sdanielk1977               1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
500312d6b36Sdanielk1977     sqlite3ValueFree(pVal);
501c60d0446Sdrh   }
5025436dc2dSdrh #endif
5035436dc2dSdrh 
504c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
5054397de57Sdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), 0);
506c22bd47dSdrh   return TCL_OK;
507c22bd47dSdrh }
508c22bd47dSdrh 
509c22bd47dSdrh /*
510c22bd47dSdrh ** Routines to implement the x_count() aggregate function.
511c22bd47dSdrh */
512c22bd47dSdrh typedef struct CountCtx CountCtx;
513c22bd47dSdrh struct CountCtx {
514c22bd47dSdrh   int n;
515c22bd47dSdrh };
5160ae8b831Sdanielk1977 static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
517c22bd47dSdrh   CountCtx *p;
5184f26d6c4Sdrh   p = sqlite3_aggregate_context(context, sizeof(*p));
5199c054830Sdrh   if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
520c22bd47dSdrh     p->n++;
521c22bd47dSdrh   }
522c22bd47dSdrh }
5230ae8b831Sdanielk1977 static void countFinalize(sqlite3_context *context){
524c22bd47dSdrh   CountCtx *p;
5254f26d6c4Sdrh   p = sqlite3_aggregate_context(context, sizeof(*p));
526c572ef7fSdanielk1977   sqlite3_result_int(context, p ? p->n : 0);
527c22bd47dSdrh }
528c22bd47dSdrh 
529c22bd47dSdrh /*
530c22bd47dSdrh ** Usage:  sqlite_test_create_aggregate DB
531c22bd47dSdrh **
5326f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order
533c22bd47dSdrh ** to create a function named "x_count".  This function does the same thing
534c22bd47dSdrh ** as the "md5sum" function.
535c22bd47dSdrh **
536c22bd47dSdrh ** The original motivation for this routine was to be able to call the
5376f8a503dSdanielk1977 ** sqlite3_create_aggregate function while a query is in progress in order
538c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic.
539c22bd47dSdrh */
540c2eef3b3Sdrh static int test_create_aggregate(
541c22bd47dSdrh   void *NotUsed,
542c22bd47dSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
543c22bd47dSdrh   int argc,              /* Number of arguments */
544c22bd47dSdrh   char **argv            /* Text of each argument */
545c22bd47dSdrh ){
5469bb575fdSdrh   sqlite3 *db;
547c60d0446Sdrh   int rc;
548c22bd47dSdrh   if( argc!=2 ){
549c22bd47dSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
550c22bd47dSdrh        " FILENAME\"", 0);
551c22bd47dSdrh     return TCL_ERROR;
552c22bd47dSdrh   }
553b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
554c60d0446Sdrh   rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
555d8123366Sdanielk1977       countStep,countFinalize);
556c60d0446Sdrh   if( rc==SQLITE_OK ){
557f9d64d2cSdanielk1977     sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
558d8123366Sdanielk1977         countStep,countFinalize);
559c60d0446Sdrh   }
560c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
561c22bd47dSdrh   return TCL_OK;
562c22bd47dSdrh }
563c22bd47dSdrh 
564c22bd47dSdrh 
565c22bd47dSdrh 
566c22bd47dSdrh /*
5676f8a503dSdanielk1977 ** Usage:  sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
568d1bf3512Sdrh **
569d1bf3512Sdrh ** Call mprintf with three integer arguments
570d1bf3512Sdrh */
5716f8a503dSdanielk1977 static int sqlite3_mprintf_int(
572d1bf3512Sdrh   void *NotUsed,
573d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
574d1bf3512Sdrh   int argc,              /* Number of arguments */
575d1bf3512Sdrh   char **argv            /* Text of each argument */
576d1bf3512Sdrh ){
577d1bf3512Sdrh   int a[3], i;
578d1bf3512Sdrh   char *z;
579d1bf3512Sdrh   if( argc!=5 ){
580d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
581d1bf3512Sdrh        " FORMAT INT INT INT\"", 0);
582d1bf3512Sdrh     return TCL_ERROR;
583d1bf3512Sdrh   }
584d1bf3512Sdrh   for(i=2; i<5; i++){
585d1bf3512Sdrh     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
586d1bf3512Sdrh   }
5876f8a503dSdanielk1977   z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
588d1bf3512Sdrh   Tcl_AppendResult(interp, z, 0);
5893f4fedb2Sdrh   sqlite3_free(z);
590d1bf3512Sdrh   return TCL_OK;
591d1bf3512Sdrh }
592d1bf3512Sdrh 
593d1bf3512Sdrh /*
5949d213ef0Sdrh ** If zNum represents an integer that will fit in 64-bits, then set
5959d213ef0Sdrh ** *pValue to that integer and return true.  Otherwise return false.
5969d213ef0Sdrh */
5979d213ef0Sdrh static int sqlite3GetInt64(const char *zNum, i64 *pValue){
5989d213ef0Sdrh   if( sqlite3FitsIn64Bits(zNum) ){
5999d213ef0Sdrh     sqlite3atoi64(zNum, pValue);
6009d213ef0Sdrh     return 1;
6019d213ef0Sdrh   }
6029d213ef0Sdrh   return 0;
6039d213ef0Sdrh }
6049d213ef0Sdrh 
6059d213ef0Sdrh /*
606e9707671Sdrh ** Usage:  sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
607e9707671Sdrh **
608e9707671Sdrh ** Call mprintf with three 64-bit integer arguments
609e9707671Sdrh */
610e9707671Sdrh static int sqlite3_mprintf_int64(
611e9707671Sdrh   void *NotUsed,
612e9707671Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
613e9707671Sdrh   int argc,              /* Number of arguments */
614e9707671Sdrh   char **argv            /* Text of each argument */
615e9707671Sdrh ){
616e9707671Sdrh   int i;
617e9707671Sdrh   sqlite_int64 a[3];
618e9707671Sdrh   char *z;
619e9707671Sdrh   if( argc!=5 ){
620e9707671Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
621e9707671Sdrh        " FORMAT INT INT INT\"", 0);
622e9707671Sdrh     return TCL_ERROR;
623e9707671Sdrh   }
624e9707671Sdrh   for(i=2; i<5; i++){
625e9707671Sdrh     if( !sqlite3GetInt64(argv[i], &a[i-2]) ){
626e9707671Sdrh       Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
627e9707671Sdrh       return TCL_ERROR;
628e9707671Sdrh     }
629e9707671Sdrh   }
630e9707671Sdrh   z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
631e9707671Sdrh   Tcl_AppendResult(interp, z, 0);
632e9707671Sdrh   sqlite3_free(z);
633e9707671Sdrh   return TCL_OK;
634e9707671Sdrh }
635e9707671Sdrh 
636e9707671Sdrh /*
6376f8a503dSdanielk1977 ** Usage:  sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
638d1bf3512Sdrh **
639d1bf3512Sdrh ** Call mprintf with two integer arguments and one string argument
640d1bf3512Sdrh */
6416f8a503dSdanielk1977 static int sqlite3_mprintf_str(
642d1bf3512Sdrh   void *NotUsed,
643d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
644d1bf3512Sdrh   int argc,              /* Number of arguments */
645d1bf3512Sdrh   char **argv            /* Text of each argument */
646d1bf3512Sdrh ){
647d1bf3512Sdrh   int a[3], i;
648d1bf3512Sdrh   char *z;
649f220b24fSchw   if( argc<4 || argc>5 ){
650d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
651f220b24fSchw        " FORMAT INT INT ?STRING?\"", 0);
652d1bf3512Sdrh     return TCL_ERROR;
653d1bf3512Sdrh   }
654d1bf3512Sdrh   for(i=2; i<4; i++){
655d1bf3512Sdrh     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
656d1bf3512Sdrh   }
6576f8a503dSdanielk1977   z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
658d1bf3512Sdrh   Tcl_AppendResult(interp, z, 0);
6593f4fedb2Sdrh   sqlite3_free(z);
660d1bf3512Sdrh   return TCL_OK;
661d1bf3512Sdrh }
662d1bf3512Sdrh 
663d1bf3512Sdrh /*
66463782855Sdrh ** Usage:  sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE
665d1bf3512Sdrh **
666d1bf3512Sdrh ** Call mprintf with two integer arguments and one double argument
667d1bf3512Sdrh */
6686f8a503dSdanielk1977 static int sqlite3_mprintf_double(
669d1bf3512Sdrh   void *NotUsed,
670d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
671d1bf3512Sdrh   int argc,              /* Number of arguments */
672d1bf3512Sdrh   char **argv            /* Text of each argument */
673d1bf3512Sdrh ){
674d1bf3512Sdrh   int a[3], i;
675d1bf3512Sdrh   double r;
676d1bf3512Sdrh   char *z;
677d1bf3512Sdrh   if( argc!=5 ){
678d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
67963782855Sdrh        " FORMAT INT INT DOUBLE\"", 0);
680d1bf3512Sdrh     return TCL_ERROR;
681d1bf3512Sdrh   }
682d1bf3512Sdrh   for(i=2; i<4; i++){
683d1bf3512Sdrh     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
684d1bf3512Sdrh   }
685d1bf3512Sdrh   if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
6866f8a503dSdanielk1977   z = sqlite3_mprintf(argv[1], a[0], a[1], r);
687d1bf3512Sdrh   Tcl_AppendResult(interp, z, 0);
6883f4fedb2Sdrh   sqlite3_free(z);
689d1bf3512Sdrh   return TCL_OK;
690d1bf3512Sdrh }
691d1bf3512Sdrh 
692d1bf3512Sdrh /*
69363782855Sdrh ** Usage:  sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE
694b621c237Sdrh **
695b621c237Sdrh ** Call mprintf with a single double argument which is the product of the
696b621c237Sdrh ** two arguments given above.  This is used to generate overflow and underflow
697b621c237Sdrh ** doubles to test that they are converted properly.
698b621c237Sdrh */
6996f8a503dSdanielk1977 static int sqlite3_mprintf_scaled(
700b621c237Sdrh   void *NotUsed,
701b621c237Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
702b621c237Sdrh   int argc,              /* Number of arguments */
703b621c237Sdrh   char **argv            /* Text of each argument */
704b621c237Sdrh ){
705b621c237Sdrh   int i;
706b621c237Sdrh   double r[2];
707b621c237Sdrh   char *z;
708b621c237Sdrh   if( argc!=4 ){
709b621c237Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
710b621c237Sdrh        " FORMAT DOUBLE DOUBLE\"", 0);
711b621c237Sdrh     return TCL_ERROR;
712b621c237Sdrh   }
713b621c237Sdrh   for(i=2; i<4; i++){
714b621c237Sdrh     if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
715b621c237Sdrh   }
7166f8a503dSdanielk1977   z = sqlite3_mprintf(argv[1], r[0]*r[1]);
717b621c237Sdrh   Tcl_AppendResult(interp, z, 0);
7183f4fedb2Sdrh   sqlite3_free(z);
719b621c237Sdrh   return TCL_OK;
720b621c237Sdrh }
721b621c237Sdrh 
722b621c237Sdrh /*
723e29b1a05Sdrh ** Usage:  sqlite3_mprintf_stronly FORMAT STRING
724e29b1a05Sdrh **
725e29b1a05Sdrh ** Call mprintf with a single double argument which is the product of the
726e29b1a05Sdrh ** two arguments given above.  This is used to generate overflow and underflow
727e29b1a05Sdrh ** doubles to test that they are converted properly.
728e29b1a05Sdrh */
729e29b1a05Sdrh static int sqlite3_mprintf_stronly(
730e29b1a05Sdrh   void *NotUsed,
731e29b1a05Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
732e29b1a05Sdrh   int argc,              /* Number of arguments */
733e29b1a05Sdrh   char **argv            /* Text of each argument */
734e29b1a05Sdrh ){
735e29b1a05Sdrh   char *z;
736e29b1a05Sdrh   if( argc!=3 ){
737e29b1a05Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
738e29b1a05Sdrh        " FORMAT STRING\"", 0);
739e29b1a05Sdrh     return TCL_ERROR;
740e29b1a05Sdrh   }
741e29b1a05Sdrh   z = sqlite3_mprintf(argv[1], argv[2]);
742e29b1a05Sdrh   Tcl_AppendResult(interp, z, 0);
743e29b1a05Sdrh   sqlite3_free(z);
744e29b1a05Sdrh   return TCL_OK;
745e29b1a05Sdrh }
746e29b1a05Sdrh 
747e29b1a05Sdrh /*
74863782855Sdrh ** Usage:  sqlite3_mprintf_hexdouble FORMAT HEX
74963782855Sdrh **
75063782855Sdrh ** Call mprintf with a single double argument which is derived from the
75163782855Sdrh ** hexadecimal encoding of an IEEE double.
75263782855Sdrh */
75363782855Sdrh static int sqlite3_mprintf_hexdouble(
75463782855Sdrh   void *NotUsed,
75563782855Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
75663782855Sdrh   int argc,              /* Number of arguments */
75763782855Sdrh   char **argv            /* Text of each argument */
75863782855Sdrh ){
75963782855Sdrh   char *z;
76063782855Sdrh   double r;
76163782855Sdrh   unsigned  x1, x2;
76263782855Sdrh   long long unsigned d;
76363782855Sdrh   if( argc!=3 ){
76463782855Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
76563782855Sdrh        " FORMAT STRING\"", 0);
76663782855Sdrh     return TCL_ERROR;
76763782855Sdrh   }
76863782855Sdrh   if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){
76963782855Sdrh     Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0);
77063782855Sdrh     return TCL_ERROR;
77163782855Sdrh   }
77263782855Sdrh   d = x2;
77363782855Sdrh   d = (d<<32) + x1;
77463782855Sdrh   memcpy(&r, &d, sizeof(r));
77563782855Sdrh   z = sqlite3_mprintf(argv[1], r);
77663782855Sdrh   Tcl_AppendResult(interp, z, 0);
77763782855Sdrh   sqlite3_free(z);
77863782855Sdrh   return TCL_OK;
77963782855Sdrh }
78063782855Sdrh 
78163782855Sdrh /*
7824693423bSdrh ** Usage: sqlite_malloc_fail N  ?REPEAT-INTERVAL?
783daffd0e5Sdrh **
7844693423bSdrh ** Rig sqliteMalloc() to fail on the N-th call and every REPEAT-INTERVAL call
7854693423bSdrh ** after that.  If REPEAT-INTERVAL is 0 or is omitted, then only a single
7864693423bSdrh ** malloc will fail.  If REPEAT-INTERVAL is 1 then all mallocs after the
7874693423bSdrh ** first failure will continue to fail on every call.  If REPEAT-INTERVAL is
7884693423bSdrh ** 2 then every other malloc will fail.  And so forth.
7894693423bSdrh **
790261919ccSdanielk1977 ** Turn off this mechanism and reset the sqlite3Tsd()->mallocFailed variable is N==0.
791daffd0e5Sdrh */
7922c336549Sdanielk1977 #ifdef SQLITE_MEMDEBUG
793daffd0e5Sdrh static int sqlite_malloc_fail(
794daffd0e5Sdrh   void *NotUsed,
795daffd0e5Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
796daffd0e5Sdrh   int argc,              /* Number of arguments */
797daffd0e5Sdrh   char **argv            /* Text of each argument */
798daffd0e5Sdrh ){
799daffd0e5Sdrh   int n;
8004693423bSdrh   int rep;
8014693423bSdrh   if( argc!=2 && argc!=3 ){
802daffd0e5Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0);
803daffd0e5Sdrh     return TCL_ERROR;
804daffd0e5Sdrh   }
805daffd0e5Sdrh   if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
8064693423bSdrh   if( argc==3 ){
8074693423bSdrh     if( Tcl_GetInt(interp, argv[2], &rep) ) return TCL_ERROR;
8084693423bSdrh   }else{
8094693423bSdrh     rep = 0;
8104693423bSdrh   }
8116f8a503dSdanielk1977   sqlite3_iMallocFail = n;
8124693423bSdrh   sqlite3_iMallocReset = rep;
813daffd0e5Sdrh   return TCL_OK;
814daffd0e5Sdrh }
815daffd0e5Sdrh #endif
816daffd0e5Sdrh 
817daffd0e5Sdrh /*
818daffd0e5Sdrh ** Usage: sqlite_malloc_stat
819daffd0e5Sdrh **
820daffd0e5Sdrh ** Return the number of prior calls to sqliteMalloc() and sqliteFree().
821daffd0e5Sdrh */
8222c336549Sdanielk1977 #ifdef SQLITE_MEMDEBUG
823daffd0e5Sdrh static int sqlite_malloc_stat(
824daffd0e5Sdrh   void *NotUsed,
825daffd0e5Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
826daffd0e5Sdrh   int argc,              /* Number of arguments */
827daffd0e5Sdrh   char **argv            /* Text of each argument */
828daffd0e5Sdrh ){
829daffd0e5Sdrh   char zBuf[200];
8306f8a503dSdanielk1977   sprintf(zBuf, "%d %d %d", sqlite3_nMalloc,sqlite3_nFree,sqlite3_iMallocFail);
831daffd0e5Sdrh   Tcl_AppendResult(interp, zBuf, 0);
832daffd0e5Sdrh   return TCL_OK;
833daffd0e5Sdrh }
8345591df55Sdanielk1977 
8355591df55Sdanielk1977 /*
8365591df55Sdanielk1977 ** This function implements a Tcl command that may be invoked using any of
8375591df55Sdanielk1977 ** the four forms enumerated below.
8385591df55Sdanielk1977 **
8395591df55Sdanielk1977 ** sqlite_malloc_outstanding
8405591df55Sdanielk1977 **     Return a summary of all unfreed blocks of memory allocated by the
8415591df55Sdanielk1977 **     current thread. See comments above function sqlite3OutstandingMallocs()
8425591df55Sdanielk1977 **     in util.c for a description of the returned value.
8435591df55Sdanielk1977 **
8445591df55Sdanielk1977 ** sqlite_malloc_outstanding -bytes
8455591df55Sdanielk1977 **     Return the total amount of unfreed memory (in bytes) allocated by
8465591df55Sdanielk1977 **     this thread.
8475591df55Sdanielk1977 **
8485591df55Sdanielk1977 ** sqlite_malloc_outstanding -maxbytes
8495591df55Sdanielk1977 **     Return the maximum amount of dynamic memory in use at one time
8505591df55Sdanielk1977 **     by this thread.
8515591df55Sdanielk1977 **
8525591df55Sdanielk1977 ** sqlite_malloc_outstanding -clearmaxbytes
8535591df55Sdanielk1977 **     Set the value returned by [sqlite_malloc_outstanding -maxbytes]
8545591df55Sdanielk1977 **     to the current value of [sqlite_malloc_outstanding -bytes].
8555591df55Sdanielk1977 */
8562e588c75Sdanielk1977 static int sqlite_malloc_outstanding(
8575591df55Sdanielk1977   ClientData clientData,
8582e588c75Sdanielk1977   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
8595591df55Sdanielk1977   int objc,              /* Number of arguments */
8605591df55Sdanielk1977   Tcl_Obj *CONST objv[]  /* Command arguments */
8612e588c75Sdanielk1977 ){
8622e588c75Sdanielk1977   extern int sqlite3OutstandingMallocs(Tcl_Interp *interp);
8635591df55Sdanielk1977 
8645591df55Sdanielk1977   if( objc!=1 && objc!=2 ){
8655591df55Sdanielk1977     Tcl_WrongNumArgs(interp, 1, objv, "?-bytes?");
8665591df55Sdanielk1977     return TCL_ERROR;
8675591df55Sdanielk1977   }
8685591df55Sdanielk1977 
8695591df55Sdanielk1977   if( objc==2 ){
8705591df55Sdanielk1977     const char *zArg = Tcl_GetString(objv[1]);
8715591df55Sdanielk1977     if( 0==strcmp(zArg, "-bytes") ){
8725591df55Sdanielk1977       Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3Tsd()->nAlloc));
8735591df55Sdanielk1977 #ifndef SQLITE_OMIT_MEMORY_MANAGEMENT
8745591df55Sdanielk1977     }else if( 0==strcmp(zArg, "-maxbytes") ){
8755591df55Sdanielk1977       Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3Tsd()->nMaxAlloc));
8765591df55Sdanielk1977     }else if( 0==strcmp(zArg, "-clearmaxbytes") ){
8775591df55Sdanielk1977       sqlite3Tsd()->nMaxAlloc = sqlite3Tsd()->nAlloc;
8785591df55Sdanielk1977 #endif
8795591df55Sdanielk1977     }else{
8805591df55Sdanielk1977       Tcl_AppendResult(interp, "bad option \"", zArg,
8815591df55Sdanielk1977         "\": must be -bytes, -maxbytes or -clearmaxbytes", 0
8825591df55Sdanielk1977       );
8835591df55Sdanielk1977       return TCL_ERROR;
8845591df55Sdanielk1977     }
8855591df55Sdanielk1977 
8865591df55Sdanielk1977     return TCL_OK;
8875591df55Sdanielk1977   }
8885591df55Sdanielk1977 
8892e588c75Sdanielk1977   return sqlite3OutstandingMallocs(interp);
8902e588c75Sdanielk1977 }
891daffd0e5Sdrh #endif
892daffd0e5Sdrh 
893daffd0e5Sdrh /*
894*aef0bf64Sdanielk1977 ** Usage: sqlite3_enable_shared_cache BOOLEAN
895*aef0bf64Sdanielk1977 **
896*aef0bf64Sdanielk1977 */
897*aef0bf64Sdanielk1977 #ifndef SQLITE_OMIT_SHARED_CACHE
898*aef0bf64Sdanielk1977 static int test_enable_shared_cache(
899*aef0bf64Sdanielk1977   ClientData clientData,
900*aef0bf64Sdanielk1977   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
901*aef0bf64Sdanielk1977   int objc,              /* Number of arguments */
902*aef0bf64Sdanielk1977   Tcl_Obj *CONST objv[]  /* Command arguments */
903*aef0bf64Sdanielk1977 ){
904*aef0bf64Sdanielk1977   int rc;
905*aef0bf64Sdanielk1977   int enable;
906*aef0bf64Sdanielk1977   SqliteTsd *pTsd = sqlite3Tsd();
907*aef0bf64Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewBooleanObj(pTsd->useSharedData));
908*aef0bf64Sdanielk1977 
909*aef0bf64Sdanielk1977   if( objc!=2 ){
910*aef0bf64Sdanielk1977     Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
911*aef0bf64Sdanielk1977     return TCL_ERROR;
912*aef0bf64Sdanielk1977   }
913*aef0bf64Sdanielk1977   if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){
914*aef0bf64Sdanielk1977     return TCL_ERROR;
915*aef0bf64Sdanielk1977   }
916*aef0bf64Sdanielk1977   rc = sqlite3_enable_shared_cache(enable);
917*aef0bf64Sdanielk1977   if( rc!=SQLITE_OK ){
918*aef0bf64Sdanielk1977     Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
919*aef0bf64Sdanielk1977     return TCL_ERROR;
920*aef0bf64Sdanielk1977   }
921*aef0bf64Sdanielk1977   return TCL_OK;
922*aef0bf64Sdanielk1977 }
923*aef0bf64Sdanielk1977 #endif
924*aef0bf64Sdanielk1977 
925*aef0bf64Sdanielk1977 /*
92628b4e489Sdrh ** Usage:  sqlite_abort
92728b4e489Sdrh **
92828b4e489Sdrh ** Shutdown the process immediately.  This is not a clean shutdown.
92928b4e489Sdrh ** This command is used to test the recoverability of a database in
93028b4e489Sdrh ** the event of a program crash.
93128b4e489Sdrh */
93228b4e489Sdrh static int sqlite_abort(
93328b4e489Sdrh   void *NotUsed,
93428b4e489Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
93528b4e489Sdrh   int argc,              /* Number of arguments */
93628b4e489Sdrh   char **argv            /* Text of each argument */
93728b4e489Sdrh ){
93828b4e489Sdrh   assert( interp==0 );   /* This will always fail */
93928b4e489Sdrh   return TCL_OK;
94028b4e489Sdrh }
94128b4e489Sdrh 
94228b4e489Sdrh /*
9436cbe1f1bSdrh ** The following routine is a user-defined SQL function whose purpose
9446cbe1f1bSdrh ** is to test the sqlite_set_result() API.
9456cbe1f1bSdrh */
9460ae8b831Sdanielk1977 static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
9476cbe1f1bSdrh   while( argc>=2 ){
94803d847eaSdrh     const char *zArg0 = (char*)sqlite3_value_text(argv[0]);
9496d88bad4Sdanielk1977     if( zArg0 ){
9506d88bad4Sdanielk1977       if( 0==sqlite3StrICmp(zArg0, "int") ){
9516d88bad4Sdanielk1977         sqlite3_result_int(context, sqlite3_value_int(argv[1]));
9526d88bad4Sdanielk1977       }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
9536d88bad4Sdanielk1977         sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
95451ad0ecdSdanielk1977       }else if( sqlite3StrICmp(zArg0,"string")==0 ){
95503d847eaSdrh         sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1,
956d8123366Sdanielk1977             SQLITE_TRANSIENT);
95751ad0ecdSdanielk1977       }else if( sqlite3StrICmp(zArg0,"double")==0 ){
9586d88bad4Sdanielk1977         sqlite3_result_double(context, sqlite3_value_double(argv[1]));
9596d88bad4Sdanielk1977       }else if( sqlite3StrICmp(zArg0,"null")==0 ){
9606d88bad4Sdanielk1977         sqlite3_result_null(context);
9616d88bad4Sdanielk1977       }else if( sqlite3StrICmp(zArg0,"value")==0 ){
9626d88bad4Sdanielk1977         sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
9636cbe1f1bSdrh       }else{
9646d88bad4Sdanielk1977         goto error_out;
9656d88bad4Sdanielk1977       }
9666d88bad4Sdanielk1977     }else{
9676d88bad4Sdanielk1977       goto error_out;
9686cbe1f1bSdrh     }
9696cbe1f1bSdrh     argc -= 2;
9706cbe1f1bSdrh     argv += 2;
9716cbe1f1bSdrh   }
9726d88bad4Sdanielk1977   return;
9736d88bad4Sdanielk1977 
9746d88bad4Sdanielk1977 error_out:
9756d88bad4Sdanielk1977   sqlite3_result_error(context,"first argument should be one of: "
9766d88bad4Sdanielk1977       "int int64 string double null value", -1);
9776cbe1f1bSdrh }
9786cbe1f1bSdrh 
9796cbe1f1bSdrh /*
9806cbe1f1bSdrh ** Usage:   sqlite_register_test_function  DB  NAME
9816cbe1f1bSdrh **
9826cbe1f1bSdrh ** Register the test SQL function on the database DB under the name NAME.
9836cbe1f1bSdrh */
984c2eef3b3Sdrh static int test_register_func(
9856cbe1f1bSdrh   void *NotUsed,
9866cbe1f1bSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
9876cbe1f1bSdrh   int argc,              /* Number of arguments */
9886cbe1f1bSdrh   char **argv            /* Text of each argument */
9896cbe1f1bSdrh ){
9909bb575fdSdrh   sqlite3 *db;
9916cbe1f1bSdrh   int rc;
9926cbe1f1bSdrh   if( argc!=3 ){
9936cbe1f1bSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
9946cbe1f1bSdrh        " DB FUNCTION-NAME", 0);
9956cbe1f1bSdrh     return TCL_ERROR;
9966cbe1f1bSdrh   }
997b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
998f9d64d2cSdanielk1977   rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
999d8123366Sdanielk1977       testFunc, 0, 0);
10006cbe1f1bSdrh   if( rc!=0 ){
1001f20b21c8Sdanielk1977     Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
10026cbe1f1bSdrh     return TCL_ERROR;
10036cbe1f1bSdrh   }
1004c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
10056cbe1f1bSdrh   return TCL_OK;
10066cbe1f1bSdrh }
10076cbe1f1bSdrh 
10086cbe1f1bSdrh /*
1009106bb236Sdanielk1977 ** Usage:  sqlite3_finalize  STMT
1010b86ccfb2Sdrh **
1011106bb236Sdanielk1977 ** Finalize a statement handle.
1012b86ccfb2Sdrh */
1013b86ccfb2Sdrh static int test_finalize(
1014106bb236Sdanielk1977   void * clientData,
1015106bb236Sdanielk1977   Tcl_Interp *interp,
1016106bb236Sdanielk1977   int objc,
1017106bb236Sdanielk1977   Tcl_Obj *CONST objv[]
1018b86ccfb2Sdrh ){
1019106bb236Sdanielk1977   sqlite3_stmt *pStmt;
1020b86ccfb2Sdrh   int rc;
1021c60d0446Sdrh   sqlite3 *db;
1022106bb236Sdanielk1977 
1023106bb236Sdanielk1977   if( objc!=2 ){
1024106bb236Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1025106bb236Sdanielk1977         Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
1026b86ccfb2Sdrh     return TCL_ERROR;
1027b86ccfb2Sdrh   }
1028106bb236Sdanielk1977 
1029106bb236Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1030106bb236Sdanielk1977 
10314397de57Sdanielk1977   if( pStmt ){
1032c60d0446Sdrh     db = StmtToDb(pStmt);
10334397de57Sdanielk1977   }
1034fc57d7bfSdanielk1977   rc = sqlite3_finalize(pStmt);
1035b77f5dadSdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
10364397de57Sdanielk1977   if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
1037106bb236Sdanielk1977   return TCL_OK;
1038106bb236Sdanielk1977 }
1039106bb236Sdanielk1977 
1040106bb236Sdanielk1977 /*
1041106bb236Sdanielk1977 ** Usage:  sqlite3_reset  STMT
1042106bb236Sdanielk1977 **
1043261919ccSdanielk1977 ** Reset a statement handle.
1044106bb236Sdanielk1977 */
1045106bb236Sdanielk1977 static int test_reset(
1046106bb236Sdanielk1977   void * clientData,
1047106bb236Sdanielk1977   Tcl_Interp *interp,
1048106bb236Sdanielk1977   int objc,
1049106bb236Sdanielk1977   Tcl_Obj *CONST objv[]
1050106bb236Sdanielk1977 ){
1051106bb236Sdanielk1977   sqlite3_stmt *pStmt;
1052106bb236Sdanielk1977   int rc;
1053106bb236Sdanielk1977 
1054106bb236Sdanielk1977   if( objc!=2 ){
1055106bb236Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1056106bb236Sdanielk1977         Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
1057106bb236Sdanielk1977     return TCL_ERROR;
1058106bb236Sdanielk1977   }
1059106bb236Sdanielk1977 
1060106bb236Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1061106bb236Sdanielk1977 
1062fc57d7bfSdanielk1977   rc = sqlite3_reset(pStmt);
1063261919ccSdanielk1977   if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){
1064261919ccSdanielk1977     return TCL_ERROR;
1065261919ccSdanielk1977   }
10664397de57Sdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
1067261919ccSdanielk1977 /*
1068106bb236Sdanielk1977   if( rc ){
1069b86ccfb2Sdrh     return TCL_ERROR;
1070b86ccfb2Sdrh   }
1071261919ccSdanielk1977 */
1072b86ccfb2Sdrh   return TCL_OK;
1073b86ccfb2Sdrh }
1074b86ccfb2Sdrh 
10755a38705eSdrh /*
1076d89bd007Sdrh ** Usage:  sqlite3_expired STMT
1077d89bd007Sdrh **
1078d89bd007Sdrh ** Return TRUE if a recompilation of the statement is recommended.
1079d89bd007Sdrh */
1080d89bd007Sdrh static int test_expired(
1081d89bd007Sdrh   void * clientData,
1082d89bd007Sdrh   Tcl_Interp *interp,
1083d89bd007Sdrh   int objc,
1084d89bd007Sdrh   Tcl_Obj *CONST objv[]
1085d89bd007Sdrh ){
1086d89bd007Sdrh   sqlite3_stmt *pStmt;
1087d89bd007Sdrh   if( objc!=2 ){
1088d89bd007Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"",
1089d89bd007Sdrh         Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
1090d89bd007Sdrh     return TCL_ERROR;
1091d89bd007Sdrh   }
1092d89bd007Sdrh   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1093d89bd007Sdrh   Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt)));
1094d89bd007Sdrh   return TCL_OK;
1095d89bd007Sdrh }
1096d89bd007Sdrh 
1097d89bd007Sdrh /*
1098f8db1bc0Sdrh ** Usage:  sqlite3_transfer_bindings FROMSTMT TOSTMT
1099f8db1bc0Sdrh **
1100f8db1bc0Sdrh ** Transfer all bindings from FROMSTMT over to TOSTMT
1101f8db1bc0Sdrh */
1102f8db1bc0Sdrh static int test_transfer_bind(
1103f8db1bc0Sdrh   void * clientData,
1104f8db1bc0Sdrh   Tcl_Interp *interp,
1105f8db1bc0Sdrh   int objc,
1106f8db1bc0Sdrh   Tcl_Obj *CONST objv[]
1107f8db1bc0Sdrh ){
1108f8db1bc0Sdrh   sqlite3_stmt *pStmt1, *pStmt2;
1109f8db1bc0Sdrh   if( objc!=3 ){
1110f8db1bc0Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"",
1111f8db1bc0Sdrh         Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0);
1112f8db1bc0Sdrh     return TCL_ERROR;
1113f8db1bc0Sdrh   }
1114f8db1bc0Sdrh   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR;
1115f8db1bc0Sdrh   if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR;
1116f8db1bc0Sdrh   Tcl_SetObjResult(interp,
1117f8db1bc0Sdrh      Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2)));
1118f8db1bc0Sdrh   return TCL_OK;
1119f8db1bc0Sdrh }
1120f8db1bc0Sdrh 
1121f8db1bc0Sdrh /*
1122fbcd585fSdanielk1977 ** Usage:  sqlite3_changes DB
112350457896Sdrh **
1124fbcd585fSdanielk1977 ** Return the number of changes made to the database by the last SQL
1125fbcd585fSdanielk1977 ** execution.
112650457896Sdrh */
1127fbcd585fSdanielk1977 static int test_changes(
1128fbcd585fSdanielk1977   void * clientData,
1129fbcd585fSdanielk1977   Tcl_Interp *interp,
1130fbcd585fSdanielk1977   int objc,
1131fbcd585fSdanielk1977   Tcl_Obj *CONST objv[]
1132fbcd585fSdanielk1977 ){
1133fbcd585fSdanielk1977   sqlite3 *db;
1134fbcd585fSdanielk1977   if( objc!=2 ){
1135fbcd585fSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1136fbcd585fSdanielk1977        Tcl_GetString(objv[0]), " DB", 0);
1137fbcd585fSdanielk1977     return TCL_ERROR;
1138fbcd585fSdanielk1977   }
1139fbcd585fSdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1140fbcd585fSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
1141fbcd585fSdanielk1977   return TCL_OK;
1142fbcd585fSdanielk1977 }
114350457896Sdrh 
114450457896Sdrh /*
11457c972decSdrh ** This is the "static_bind_value" that variables are bound to when
11466f8a503dSdanielk1977 ** the FLAG option of sqlite3_bind is "static"
114750457896Sdrh */
11487c972decSdrh static char *sqlite_static_bind_value = 0;
11497c972decSdrh 
11507c972decSdrh /*
11516f8a503dSdanielk1977 ** Usage:  sqlite3_bind  VM  IDX  VALUE  FLAGS
11527c972decSdrh **
11537c972decSdrh ** Sets the value of the IDX-th occurance of "?" in the original SQL
11547c972decSdrh ** string.  VALUE is the new value.  If FLAGS=="null" then VALUE is
11557c972decSdrh ** ignored and the value is set to NULL.  If FLAGS=="static" then
11567c972decSdrh ** the value is set to the value of a static variable named
11577c972decSdrh ** "sqlite_static_bind_value".  If FLAGS=="normal" then a copy
1158bf8aa2a6Sdrh ** of the VALUE is made.  If FLAGS=="blob10" then a VALUE is ignored
1159bf8aa2a6Sdrh ** an a 10-byte blob "abc\000xyz\000pq" is inserted.
11607c972decSdrh */
11617c972decSdrh static int test_bind(
116250457896Sdrh   void *NotUsed,
116350457896Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
116450457896Sdrh   int argc,              /* Number of arguments */
116550457896Sdrh   char **argv            /* Text of each argument */
116650457896Sdrh ){
1167fc57d7bfSdanielk1977   sqlite3_stmt *pStmt;
116850457896Sdrh   int rc;
11697c972decSdrh   int idx;
11707c972decSdrh   if( argc!=5 ){
117150457896Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
11727c972decSdrh        " VM IDX VALUE (null|static|normal)\"", 0);
117350457896Sdrh     return TCL_ERROR;
117450457896Sdrh   }
1175fc57d7bfSdanielk1977   if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
11767c972decSdrh   if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
11777c972decSdrh   if( strcmp(argv[4],"null")==0 ){
1178fc57d7bfSdanielk1977     rc = sqlite3_bind_null(pStmt, idx);
11797c972decSdrh   }else if( strcmp(argv[4],"static")==0 ){
1180fc57d7bfSdanielk1977     rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
11817c972decSdrh   }else if( strcmp(argv[4],"normal")==0 ){
1182d8123366Sdanielk1977     rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
1183bf8aa2a6Sdrh   }else if( strcmp(argv[4],"blob10")==0 ){
1184bf8aa2a6Sdrh     rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC);
11857c972decSdrh   }else{
11867c972decSdrh     Tcl_AppendResult(interp, "4th argument should be "
11877c972decSdrh         "\"null\" or \"static\" or \"normal\"", 0);
11887c972decSdrh     return TCL_ERROR;
11897c972decSdrh   }
1190c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
119150457896Sdrh   if( rc ){
119250457896Sdrh     char zBuf[50];
119350457896Sdrh     sprintf(zBuf, "(%d) ", rc);
1194f20b21c8Sdanielk1977     Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
119550457896Sdrh     return TCL_ERROR;
119650457896Sdrh   }
119750457896Sdrh   return TCL_OK;
119850457896Sdrh }
119950457896Sdrh 
12005436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
12014e6af134Sdanielk1977 /*
12024e6af134Sdanielk1977 ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
12034e6af134Sdanielk1977 **
12044e6af134Sdanielk1977 ** This function is used to test that SQLite selects the correct collation
12054e6af134Sdanielk1977 ** sequence callback when multiple versions (for different text encodings)
12064e6af134Sdanielk1977 ** are available.
12074e6af134Sdanielk1977 **
12084e6af134Sdanielk1977 ** Calling this routine registers the collation sequence "test_collate"
12094e6af134Sdanielk1977 ** with database handle <db>. The second argument must be a list of three
12104e6af134Sdanielk1977 ** boolean values. If the first is true, then a version of test_collate is
12114e6af134Sdanielk1977 ** registered for UTF-8, if the second is true, a version is registered for
12124e6af134Sdanielk1977 ** UTF-16le, if the third is true, a UTF-16be version is available.
12134e6af134Sdanielk1977 ** Previous versions of test_collate are deleted.
12144e6af134Sdanielk1977 **
12154e6af134Sdanielk1977 ** The collation sequence test_collate is implemented by calling the
12164e6af134Sdanielk1977 ** following TCL script:
12174e6af134Sdanielk1977 **
12184e6af134Sdanielk1977 **   "test_collate <enc> <lhs> <rhs>"
12194e6af134Sdanielk1977 **
12204e6af134Sdanielk1977 ** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
12214e6af134Sdanielk1977 ** The <enc> parameter is the encoding of the collation function that
12224e6af134Sdanielk1977 ** SQLite selected to call. The TCL test script implements the
12234e6af134Sdanielk1977 ** "test_collate" proc.
12244e6af134Sdanielk1977 **
12254e6af134Sdanielk1977 ** Note that this will only work with one intepreter at a time, as the
12264e6af134Sdanielk1977 ** interp pointer to use when evaluating the TCL script is stored in
12274e6af134Sdanielk1977 ** pTestCollateInterp.
12284e6af134Sdanielk1977 */
12294e6af134Sdanielk1977 static Tcl_Interp* pTestCollateInterp;
12304e6af134Sdanielk1977 static int test_collate_func(
12314e6af134Sdanielk1977   void *pCtx,
12324e6af134Sdanielk1977   int nA, const void *zA,
12334e6af134Sdanielk1977   int nB, const void *zB
12344e6af134Sdanielk1977 ){
12354e6af134Sdanielk1977   Tcl_Interp *i = pTestCollateInterp;
12364e6af134Sdanielk1977   int encin = (int)pCtx;
12374e6af134Sdanielk1977   int res;
12384db38a70Sdrh   int n;
12394e6af134Sdanielk1977 
12404e6af134Sdanielk1977   sqlite3_value *pVal;
12414e6af134Sdanielk1977   Tcl_Obj *pX;
12424e6af134Sdanielk1977 
12434e6af134Sdanielk1977   pX = Tcl_NewStringObj("test_collate", -1);
12444e6af134Sdanielk1977   Tcl_IncrRefCount(pX);
12454e6af134Sdanielk1977 
12464e6af134Sdanielk1977   switch( encin ){
12474e6af134Sdanielk1977     case SQLITE_UTF8:
12484e6af134Sdanielk1977       Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
12494e6af134Sdanielk1977       break;
12504e6af134Sdanielk1977     case SQLITE_UTF16LE:
12514e6af134Sdanielk1977       Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
12524e6af134Sdanielk1977       break;
12534e6af134Sdanielk1977     case SQLITE_UTF16BE:
12544e6af134Sdanielk1977       Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
12554e6af134Sdanielk1977       break;
12564e6af134Sdanielk1977     default:
12574e6af134Sdanielk1977       assert(0);
12584e6af134Sdanielk1977   }
12594e6af134Sdanielk1977 
12604e6af134Sdanielk1977   pVal = sqlite3ValueNew();
1261bfd6cce5Sdanielk1977   sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
12624db38a70Sdrh   n = sqlite3_value_bytes(pVal);
126303d847eaSdrh   Tcl_ListObjAppendElement(i,pX,
126403d847eaSdrh       Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
1265bfd6cce5Sdanielk1977   sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
12664db38a70Sdrh   n = sqlite3_value_bytes(pVal);
126703d847eaSdrh   Tcl_ListObjAppendElement(i,pX,
126803d847eaSdrh       Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
12694e6af134Sdanielk1977   sqlite3ValueFree(pVal);
12704e6af134Sdanielk1977 
12714e6af134Sdanielk1977   Tcl_EvalObjEx(i, pX, 0);
12724e6af134Sdanielk1977   Tcl_DecrRefCount(pX);
12734e6af134Sdanielk1977   Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
12744e6af134Sdanielk1977   return res;
12754e6af134Sdanielk1977 }
12764e6af134Sdanielk1977 static int test_collate(
12774e6af134Sdanielk1977   void * clientData,
12784e6af134Sdanielk1977   Tcl_Interp *interp,
12794e6af134Sdanielk1977   int objc,
12804e6af134Sdanielk1977   Tcl_Obj *CONST objv[]
12814e6af134Sdanielk1977 ){
12824e6af134Sdanielk1977   sqlite3 *db;
12834e6af134Sdanielk1977   int val;
1284312d6b36Sdanielk1977   sqlite3_value *pVal;
1285c60d0446Sdrh   int rc;
12864e6af134Sdanielk1977 
12874e6af134Sdanielk1977   if( objc!=5 ) goto bad_args;
12884e6af134Sdanielk1977   pTestCollateInterp = interp;
12894e6af134Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
12904e6af134Sdanielk1977 
12914e6af134Sdanielk1977   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
1292c60d0446Sdrh   rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
12934e6af134Sdanielk1977           (void *)SQLITE_UTF8, val?test_collate_func:0);
1294c60d0446Sdrh   if( rc==SQLITE_OK ){
12954e6af134Sdanielk1977     if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1296c60d0446Sdrh     rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
12974e6af134Sdanielk1977             (void *)SQLITE_UTF16LE, val?test_collate_func:0);
12984e6af134Sdanielk1977     if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
1299312d6b36Sdanielk1977 
1300312d6b36Sdanielk1977     pVal = sqlite3ValueNew();
1301312d6b36Sdanielk1977     sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
1302312d6b36Sdanielk1977     sqlite3_create_collation16(db, sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),
1303312d6b36Sdanielk1977           SQLITE_UTF16BE, (void *)SQLITE_UTF16BE, val?test_collate_func:0);
1304312d6b36Sdanielk1977     sqlite3ValueFree(pVal);
1305c60d0446Sdrh   }
1306c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
13074e6af134Sdanielk1977   return TCL_OK;
13084e6af134Sdanielk1977 
13094e6af134Sdanielk1977 bad_args:
13104e6af134Sdanielk1977   Tcl_AppendResult(interp, "wrong # args: should be \"",
13114e6af134Sdanielk1977       Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
13124e6af134Sdanielk1977   return TCL_ERROR;
13134e6af134Sdanielk1977 }
13144e6af134Sdanielk1977 
1315268803a9Sdrh /*
1316268803a9Sdrh ** When the collation needed callback is invoked, record the name of
1317268803a9Sdrh ** the requested collating function here.  The recorded name is linked
1318268803a9Sdrh ** to a TCL variable and used to make sure that the requested collation
1319268803a9Sdrh ** name is correct.
1320268803a9Sdrh */
1321268803a9Sdrh static char zNeededCollation[200];
1322268803a9Sdrh static char *pzNeededCollation = zNeededCollation;
1323268803a9Sdrh 
1324268803a9Sdrh 
1325268803a9Sdrh /*
1326268803a9Sdrh ** Called when a collating sequence is needed.  Registered using
1327268803a9Sdrh ** sqlite3_collation_needed16().
1328268803a9Sdrh */
1329312d6b36Sdanielk1977 static void test_collate_needed_cb(
1330312d6b36Sdanielk1977   void *pCtx,
1331312d6b36Sdanielk1977   sqlite3 *db,
1332312d6b36Sdanielk1977   int eTextRep,
1333268803a9Sdrh   const void *pName
1334312d6b36Sdanielk1977 ){
1335312d6b36Sdanielk1977   int enc = db->enc;
1336268803a9Sdrh   int i;
1337268803a9Sdrh   char *z;
1338268803a9Sdrh   for(z = (char*)pName, i=0; *z || z[1]; z++){
1339268803a9Sdrh     if( *z ) zNeededCollation[i++] = *z;
1340268803a9Sdrh   }
1341268803a9Sdrh   zNeededCollation[i] = 0;
1342312d6b36Sdanielk1977   sqlite3_create_collation(
1343312d6b36Sdanielk1977       db, "test_collate", db->enc, (void *)enc, test_collate_func);
1344312d6b36Sdanielk1977 }
1345312d6b36Sdanielk1977 
1346312d6b36Sdanielk1977 /*
1347312d6b36Sdanielk1977 ** Usage: add_test_collate_needed DB
1348312d6b36Sdanielk1977 */
1349312d6b36Sdanielk1977 static int test_collate_needed(
1350312d6b36Sdanielk1977   void * clientData,
1351312d6b36Sdanielk1977   Tcl_Interp *interp,
1352312d6b36Sdanielk1977   int objc,
1353312d6b36Sdanielk1977   Tcl_Obj *CONST objv[]
1354312d6b36Sdanielk1977 ){
1355312d6b36Sdanielk1977   sqlite3 *db;
1356c60d0446Sdrh   int rc;
1357312d6b36Sdanielk1977 
1358312d6b36Sdanielk1977   if( objc!=2 ) goto bad_args;
1359312d6b36Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1360c60d0446Sdrh   rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
1361268803a9Sdrh   zNeededCollation[0] = 0;
1362c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
1363312d6b36Sdanielk1977   return TCL_OK;
1364312d6b36Sdanielk1977 
1365312d6b36Sdanielk1977 bad_args:
1366312d6b36Sdanielk1977   Tcl_WrongNumArgs(interp, 1, objv, "DB");
1367312d6b36Sdanielk1977   return TCL_ERROR;
1368312d6b36Sdanielk1977 }
13695436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
1370312d6b36Sdanielk1977 
1371c8e9a2dfSdanielk1977 /*
1372c8e9a2dfSdanielk1977 ** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
1373c8e9a2dfSdanielk1977 **
1374c8e9a2dfSdanielk1977 ** This function is used to test that SQLite selects the correct user
1375c8e9a2dfSdanielk1977 ** function callback when multiple versions (for different text encodings)
1376c8e9a2dfSdanielk1977 ** are available.
1377c8e9a2dfSdanielk1977 **
1378c8e9a2dfSdanielk1977 ** Calling this routine registers up to three versions of the user function
1379c8e9a2dfSdanielk1977 ** "test_function" with database handle <db>.  If the second argument is
1380c8e9a2dfSdanielk1977 ** true, then a version of test_function is registered for UTF-8, if the
1381c8e9a2dfSdanielk1977 ** third is true, a version is registered for UTF-16le, if the fourth is
1382c8e9a2dfSdanielk1977 ** true, a UTF-16be version is available.  Previous versions of
1383c8e9a2dfSdanielk1977 ** test_function are deleted.
1384c8e9a2dfSdanielk1977 **
1385c8e9a2dfSdanielk1977 ** The user function is implemented by calling the following TCL script:
1386c8e9a2dfSdanielk1977 **
1387c8e9a2dfSdanielk1977 **   "test_function <enc> <arg>"
1388c8e9a2dfSdanielk1977 **
1389c8e9a2dfSdanielk1977 ** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
1390c8e9a2dfSdanielk1977 ** single argument passed to the SQL function. The value returned by
1391c8e9a2dfSdanielk1977 ** the TCL script is used as the return value of the SQL function. It
1392c8e9a2dfSdanielk1977 ** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
1393c8e9a2dfSdanielk1977 ** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
1394c8e9a2dfSdanielk1977 ** prefers UTF-16BE.
1395c8e9a2dfSdanielk1977 */
13965436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
1397c8e9a2dfSdanielk1977 static void test_function_utf8(
1398c8e9a2dfSdanielk1977   sqlite3_context *pCtx,
1399c8e9a2dfSdanielk1977   int nArg,
1400c8e9a2dfSdanielk1977   sqlite3_value **argv
1401c8e9a2dfSdanielk1977 ){
1402c8e9a2dfSdanielk1977   Tcl_Interp *interp;
1403c8e9a2dfSdanielk1977   Tcl_Obj *pX;
1404c8e9a2dfSdanielk1977   sqlite3_value *pVal;
1405c8e9a2dfSdanielk1977   interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1406c8e9a2dfSdanielk1977   pX = Tcl_NewStringObj("test_function", -1);
1407c8e9a2dfSdanielk1977   Tcl_IncrRefCount(pX);
1408c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
1409c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX,
141003d847eaSdrh       Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
1411c8e9a2dfSdanielk1977   Tcl_EvalObjEx(interp, pX, 0);
1412c8e9a2dfSdanielk1977   Tcl_DecrRefCount(pX);
1413c8e9a2dfSdanielk1977   sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
1414c8e9a2dfSdanielk1977   pVal = sqlite3ValueNew();
1415c8e9a2dfSdanielk1977   sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1416c8e9a2dfSdanielk1977       SQLITE_UTF8, SQLITE_STATIC);
1417c8e9a2dfSdanielk1977   sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
1418c8e9a2dfSdanielk1977       -1, SQLITE_TRANSIENT);
1419c8e9a2dfSdanielk1977   sqlite3ValueFree(pVal);
1420c8e9a2dfSdanielk1977 }
1421c8e9a2dfSdanielk1977 static void test_function_utf16le(
1422c8e9a2dfSdanielk1977   sqlite3_context *pCtx,
1423c8e9a2dfSdanielk1977   int nArg,
1424c8e9a2dfSdanielk1977   sqlite3_value **argv
1425c8e9a2dfSdanielk1977 ){
1426c8e9a2dfSdanielk1977   Tcl_Interp *interp;
1427c8e9a2dfSdanielk1977   Tcl_Obj *pX;
1428c8e9a2dfSdanielk1977   sqlite3_value *pVal;
1429c8e9a2dfSdanielk1977   interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1430c8e9a2dfSdanielk1977   pX = Tcl_NewStringObj("test_function", -1);
1431c8e9a2dfSdanielk1977   Tcl_IncrRefCount(pX);
1432c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
1433c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX,
143403d847eaSdrh       Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
1435c8e9a2dfSdanielk1977   Tcl_EvalObjEx(interp, pX, 0);
1436c8e9a2dfSdanielk1977   Tcl_DecrRefCount(pX);
1437c8e9a2dfSdanielk1977   pVal = sqlite3ValueNew();
1438c8e9a2dfSdanielk1977   sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1439c8e9a2dfSdanielk1977       SQLITE_UTF8, SQLITE_STATIC);
144003d847eaSdrh   sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
1441c8e9a2dfSdanielk1977   sqlite3ValueFree(pVal);
1442c8e9a2dfSdanielk1977 }
1443c8e9a2dfSdanielk1977 static void test_function_utf16be(
1444c8e9a2dfSdanielk1977   sqlite3_context *pCtx,
1445c8e9a2dfSdanielk1977   int nArg,
1446c8e9a2dfSdanielk1977   sqlite3_value **argv
1447c8e9a2dfSdanielk1977 ){
1448c8e9a2dfSdanielk1977   Tcl_Interp *interp;
1449c8e9a2dfSdanielk1977   Tcl_Obj *pX;
1450c8e9a2dfSdanielk1977   sqlite3_value *pVal;
1451c8e9a2dfSdanielk1977   interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1452c8e9a2dfSdanielk1977   pX = Tcl_NewStringObj("test_function", -1);
1453c8e9a2dfSdanielk1977   Tcl_IncrRefCount(pX);
1454c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
1455c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX,
145603d847eaSdrh       Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
1457c8e9a2dfSdanielk1977   Tcl_EvalObjEx(interp, pX, 0);
1458c8e9a2dfSdanielk1977   Tcl_DecrRefCount(pX);
1459c8e9a2dfSdanielk1977   pVal = sqlite3ValueNew();
1460c8e9a2dfSdanielk1977   sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1461c8e9a2dfSdanielk1977       SQLITE_UTF8, SQLITE_STATIC);
1462c8e9a2dfSdanielk1977   sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
1463c8e9a2dfSdanielk1977       -1, SQLITE_TRANSIENT);
1464c8e9a2dfSdanielk1977   sqlite3ValueFree(pVal);
1465c8e9a2dfSdanielk1977 }
14665436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
1467c8e9a2dfSdanielk1977 static int test_function(
1468c8e9a2dfSdanielk1977   void * clientData,
1469c8e9a2dfSdanielk1977   Tcl_Interp *interp,
1470c8e9a2dfSdanielk1977   int objc,
1471c8e9a2dfSdanielk1977   Tcl_Obj *CONST objv[]
1472c8e9a2dfSdanielk1977 ){
14735436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
1474c8e9a2dfSdanielk1977   sqlite3 *db;
1475c8e9a2dfSdanielk1977   int val;
1476c8e9a2dfSdanielk1977 
1477c8e9a2dfSdanielk1977   if( objc!=5 ) goto bad_args;
1478c8e9a2dfSdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1479c8e9a2dfSdanielk1977 
1480c8e9a2dfSdanielk1977   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
1481c8e9a2dfSdanielk1977   if( val ){
1482c8e9a2dfSdanielk1977     sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
1483c8e9a2dfSdanielk1977         interp, test_function_utf8, 0, 0);
1484c8e9a2dfSdanielk1977   }
1485c8e9a2dfSdanielk1977   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1486c8e9a2dfSdanielk1977   if( val ){
1487c8e9a2dfSdanielk1977     sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
1488c8e9a2dfSdanielk1977         interp, test_function_utf16le, 0, 0);
1489c8e9a2dfSdanielk1977   }
1490c8e9a2dfSdanielk1977   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
1491c8e9a2dfSdanielk1977   if( val ){
1492c8e9a2dfSdanielk1977     sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
1493c8e9a2dfSdanielk1977         interp, test_function_utf16be, 0, 0);
1494c8e9a2dfSdanielk1977   }
1495c8e9a2dfSdanielk1977 
1496c8e9a2dfSdanielk1977   return TCL_OK;
1497c8e9a2dfSdanielk1977 bad_args:
1498c8e9a2dfSdanielk1977   Tcl_AppendResult(interp, "wrong # args: should be \"",
1499c8e9a2dfSdanielk1977       Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
15005436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
1501c8e9a2dfSdanielk1977   return TCL_ERROR;
1502c8e9a2dfSdanielk1977 }
1503c8e9a2dfSdanielk1977 
1504312d6b36Sdanielk1977 /*
1505312d6b36Sdanielk1977 ** Usage:         test_errstr <err code>
1506312d6b36Sdanielk1977 **
1507312d6b36Sdanielk1977 ** Test that the english language string equivalents for sqlite error codes
1508312d6b36Sdanielk1977 ** are sane. The parameter is an integer representing an sqlite error code.
1509312d6b36Sdanielk1977 ** The result is a list of two elements, the string representation of the
1510312d6b36Sdanielk1977 ** error code and the english language explanation.
1511312d6b36Sdanielk1977 */
1512312d6b36Sdanielk1977 static int test_errstr(
1513312d6b36Sdanielk1977   void * clientData,
1514312d6b36Sdanielk1977   Tcl_Interp *interp,
1515312d6b36Sdanielk1977   int objc,
1516312d6b36Sdanielk1977   Tcl_Obj *CONST objv[]
1517312d6b36Sdanielk1977 ){
1518312d6b36Sdanielk1977   char *zCode;
1519312d6b36Sdanielk1977   int i;
1520312d6b36Sdanielk1977   if( objc!=1 ){
1521312d6b36Sdanielk1977     Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
1522312d6b36Sdanielk1977   }
1523312d6b36Sdanielk1977 
1524312d6b36Sdanielk1977   zCode = Tcl_GetString(objv[1]);
1525312d6b36Sdanielk1977   for(i=0; i<200; i++){
1526312d6b36Sdanielk1977     if( 0==strcmp(errorName(i), zCode) ) break;
1527312d6b36Sdanielk1977   }
1528312d6b36Sdanielk1977   Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
1529312d6b36Sdanielk1977   return TCL_OK;
1530312d6b36Sdanielk1977 }
1531312d6b36Sdanielk1977 
153250457896Sdrh /*
153399ee3600Sdrh ** Usage:    breakpoint
153499ee3600Sdrh **
153599ee3600Sdrh ** This routine exists for one purpose - to provide a place to put a
153699ee3600Sdrh ** breakpoint with GDB that can be triggered using TCL code.  The use
153799ee3600Sdrh ** for this is when a particular test fails on (say) the 1485th iteration.
153899ee3600Sdrh ** In the TCL test script, we can add code like this:
153999ee3600Sdrh **
154099ee3600Sdrh **     if {$i==1485} breakpoint
154199ee3600Sdrh **
154299ee3600Sdrh ** Then run testfixture in the debugger and wait for the breakpoint to
154399ee3600Sdrh ** fire.  Then additional breakpoints can be set to trace down the bug.
154499ee3600Sdrh */
154599ee3600Sdrh static int test_breakpoint(
154699ee3600Sdrh   void *NotUsed,
154799ee3600Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
154899ee3600Sdrh   int argc,              /* Number of arguments */
154999ee3600Sdrh   char **argv            /* Text of each argument */
155099ee3600Sdrh ){
155199ee3600Sdrh   return TCL_OK;         /* Do nothing */
155299ee3600Sdrh }
155399ee3600Sdrh 
1554241db313Sdrh /*
1555241db313Sdrh ** Usage:   sqlite3_bind_int  STMT N VALUE
1556241db313Sdrh **
1557241db313Sdrh ** Test the sqlite3_bind_int interface.  STMT is a prepared statement.
1558241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1559241db313Sdrh ** binds a 32-bit integer VALUE to that wildcard.
1560241db313Sdrh */
1561241db313Sdrh static int test_bind_int(
156251e3d8e2Sdanielk1977   void * clientData,
156351e3d8e2Sdanielk1977   Tcl_Interp *interp,
156451e3d8e2Sdanielk1977   int objc,
156551e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
156651e3d8e2Sdanielk1977 ){
156751e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
156851e3d8e2Sdanielk1977   int idx;
156951e3d8e2Sdanielk1977   int value;
157051e3d8e2Sdanielk1977   int rc;
157151e3d8e2Sdanielk1977 
157251e3d8e2Sdanielk1977   if( objc!=4 ){
157351e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1574241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
157551e3d8e2Sdanielk1977     return TCL_ERROR;
157651e3d8e2Sdanielk1977   }
157751e3d8e2Sdanielk1977 
157851e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
157951e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
158051e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
158151e3d8e2Sdanielk1977 
1582c572ef7fSdanielk1977   rc = sqlite3_bind_int(pStmt, idx, value);
1583c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
158451e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
158551e3d8e2Sdanielk1977     return TCL_ERROR;
158651e3d8e2Sdanielk1977   }
158751e3d8e2Sdanielk1977 
158851e3d8e2Sdanielk1977   return TCL_OK;
158951e3d8e2Sdanielk1977 }
159051e3d8e2Sdanielk1977 
1591241db313Sdrh 
1592241db313Sdrh /*
1593241db313Sdrh ** Usage:   sqlite3_bind_int64  STMT N VALUE
1594241db313Sdrh **
1595241db313Sdrh ** Test the sqlite3_bind_int64 interface.  STMT is a prepared statement.
1596241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1597241db313Sdrh ** binds a 64-bit integer VALUE to that wildcard.
1598241db313Sdrh */
159951e3d8e2Sdanielk1977 static int test_bind_int64(
160051e3d8e2Sdanielk1977   void * clientData,
160151e3d8e2Sdanielk1977   Tcl_Interp *interp,
160251e3d8e2Sdanielk1977   int objc,
160351e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
160451e3d8e2Sdanielk1977 ){
160551e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
160651e3d8e2Sdanielk1977   int idx;
160751e3d8e2Sdanielk1977   i64 value;
160851e3d8e2Sdanielk1977   int rc;
160951e3d8e2Sdanielk1977 
161051e3d8e2Sdanielk1977   if( objc!=4 ){
161151e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1612241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
161351e3d8e2Sdanielk1977     return TCL_ERROR;
161451e3d8e2Sdanielk1977   }
161551e3d8e2Sdanielk1977 
161651e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
161751e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
161851e3d8e2Sdanielk1977   if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
161951e3d8e2Sdanielk1977 
162051e3d8e2Sdanielk1977   rc = sqlite3_bind_int64(pStmt, idx, value);
1621c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
162251e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
162351e3d8e2Sdanielk1977     return TCL_ERROR;
162451e3d8e2Sdanielk1977   }
162551e3d8e2Sdanielk1977 
162651e3d8e2Sdanielk1977   return TCL_OK;
162751e3d8e2Sdanielk1977 }
162851e3d8e2Sdanielk1977 
1629241db313Sdrh 
1630241db313Sdrh /*
1631241db313Sdrh ** Usage:   sqlite3_bind_double  STMT N VALUE
1632241db313Sdrh **
1633241db313Sdrh ** Test the sqlite3_bind_double interface.  STMT is a prepared statement.
1634241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1635241db313Sdrh ** binds a 64-bit integer VALUE to that wildcard.
1636241db313Sdrh */
163751e3d8e2Sdanielk1977 static int test_bind_double(
163851e3d8e2Sdanielk1977   void * clientData,
163951e3d8e2Sdanielk1977   Tcl_Interp *interp,
164051e3d8e2Sdanielk1977   int objc,
164151e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
164251e3d8e2Sdanielk1977 ){
164351e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
164451e3d8e2Sdanielk1977   int idx;
164551e3d8e2Sdanielk1977   double value;
164651e3d8e2Sdanielk1977   int rc;
164751e3d8e2Sdanielk1977 
164851e3d8e2Sdanielk1977   if( objc!=4 ){
164951e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1650241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
165151e3d8e2Sdanielk1977     return TCL_ERROR;
165251e3d8e2Sdanielk1977   }
165351e3d8e2Sdanielk1977 
165451e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
165551e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
165651e3d8e2Sdanielk1977   if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR;
165751e3d8e2Sdanielk1977 
165851e3d8e2Sdanielk1977   rc = sqlite3_bind_double(pStmt, idx, value);
1659c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
166051e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
166151e3d8e2Sdanielk1977     return TCL_ERROR;
166251e3d8e2Sdanielk1977   }
166351e3d8e2Sdanielk1977 
166451e3d8e2Sdanielk1977   return TCL_OK;
166551e3d8e2Sdanielk1977 }
166651e3d8e2Sdanielk1977 
1667241db313Sdrh /*
1668241db313Sdrh ** Usage:   sqlite3_bind_null  STMT N
1669241db313Sdrh **
1670241db313Sdrh ** Test the sqlite3_bind_null interface.  STMT is a prepared statement.
1671241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1672241db313Sdrh ** binds a NULL to the wildcard.
1673241db313Sdrh */
167451e3d8e2Sdanielk1977 static int test_bind_null(
167551e3d8e2Sdanielk1977   void * clientData,
167651e3d8e2Sdanielk1977   Tcl_Interp *interp,
167751e3d8e2Sdanielk1977   int objc,
167851e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
167951e3d8e2Sdanielk1977 ){
168051e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
168151e3d8e2Sdanielk1977   int idx;
168251e3d8e2Sdanielk1977   int rc;
168351e3d8e2Sdanielk1977 
168451e3d8e2Sdanielk1977   if( objc!=3 ){
168551e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1686241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
168751e3d8e2Sdanielk1977     return TCL_ERROR;
168851e3d8e2Sdanielk1977   }
168951e3d8e2Sdanielk1977 
169051e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
169151e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
169251e3d8e2Sdanielk1977 
169351e3d8e2Sdanielk1977   rc = sqlite3_bind_null(pStmt, idx);
1694c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
169551e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
169651e3d8e2Sdanielk1977     return TCL_ERROR;
169751e3d8e2Sdanielk1977   }
169851e3d8e2Sdanielk1977 
169951e3d8e2Sdanielk1977   return TCL_OK;
170051e3d8e2Sdanielk1977 }
170151e3d8e2Sdanielk1977 
1702241db313Sdrh /*
1703241db313Sdrh ** Usage:   sqlite3_bind_text  STMT N STRING BYTES
1704241db313Sdrh **
1705241db313Sdrh ** Test the sqlite3_bind_text interface.  STMT is a prepared statement.
1706241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1707241db313Sdrh ** binds a UTF-8 string STRING to the wildcard.  The string is BYTES bytes
1708241db313Sdrh ** long.
1709241db313Sdrh */
171051e3d8e2Sdanielk1977 static int test_bind_text(
171151e3d8e2Sdanielk1977   void * clientData,
171251e3d8e2Sdanielk1977   Tcl_Interp *interp,
171351e3d8e2Sdanielk1977   int objc,
171451e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
171551e3d8e2Sdanielk1977 ){
171651e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
171751e3d8e2Sdanielk1977   int idx;
171851e3d8e2Sdanielk1977   int bytes;
171951e3d8e2Sdanielk1977   char *value;
172051e3d8e2Sdanielk1977   int rc;
172151e3d8e2Sdanielk1977 
172251e3d8e2Sdanielk1977   if( objc!=5 ){
172351e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1724241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
172551e3d8e2Sdanielk1977     return TCL_ERROR;
172651e3d8e2Sdanielk1977   }
172751e3d8e2Sdanielk1977 
172851e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
172951e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
173051e3d8e2Sdanielk1977   value = Tcl_GetString(objv[3]);
173151e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
173251e3d8e2Sdanielk1977 
1733d8123366Sdanielk1977   rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
1734c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
173551e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
1736473d179dSdrh     Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
173751e3d8e2Sdanielk1977     return TCL_ERROR;
173851e3d8e2Sdanielk1977   }
173951e3d8e2Sdanielk1977 
174051e3d8e2Sdanielk1977   return TCL_OK;
174151e3d8e2Sdanielk1977 }
174251e3d8e2Sdanielk1977 
1743241db313Sdrh /*
1744241db313Sdrh ** Usage:   sqlite3_bind_text16  STMT N STRING BYTES
1745241db313Sdrh **
1746241db313Sdrh ** Test the sqlite3_bind_text16 interface.  STMT is a prepared statement.
1747241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1748241db313Sdrh ** binds a UTF-16 string STRING to the wildcard.  The string is BYTES bytes
1749241db313Sdrh ** long.
1750241db313Sdrh */
175151e3d8e2Sdanielk1977 static int test_bind_text16(
175251e3d8e2Sdanielk1977   void * clientData,
175351e3d8e2Sdanielk1977   Tcl_Interp *interp,
175451e3d8e2Sdanielk1977   int objc,
175551e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
175651e3d8e2Sdanielk1977 ){
17575436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
175851e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
175951e3d8e2Sdanielk1977   int idx;
176051e3d8e2Sdanielk1977   int bytes;
176151e3d8e2Sdanielk1977   char *value;
176251e3d8e2Sdanielk1977   int rc;
176351e3d8e2Sdanielk1977 
176451e3d8e2Sdanielk1977   if( objc!=5 ){
176551e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1766241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
176751e3d8e2Sdanielk1977     return TCL_ERROR;
176851e3d8e2Sdanielk1977   }
176951e3d8e2Sdanielk1977 
177051e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
177151e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
177203d847eaSdrh   value = (char*)Tcl_GetByteArrayFromObj(objv[3], 0);
177351e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
177451e3d8e2Sdanielk1977 
1775d8123366Sdanielk1977   rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, SQLITE_TRANSIENT);
1776c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
177751e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
177851e3d8e2Sdanielk1977     return TCL_ERROR;
177951e3d8e2Sdanielk1977   }
178051e3d8e2Sdanielk1977 
17815436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
178251e3d8e2Sdanielk1977   return TCL_OK;
178351e3d8e2Sdanielk1977 }
178451e3d8e2Sdanielk1977 
1785241db313Sdrh /*
1786241db313Sdrh ** Usage:   sqlite3_bind_blob  STMT N DATA BYTES
1787241db313Sdrh **
1788241db313Sdrh ** Test the sqlite3_bind_blob interface.  STMT is a prepared statement.
1789241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1790241db313Sdrh ** binds a BLOB to the wildcard.  The BLOB is BYTES bytes in size.
1791241db313Sdrh */
179251e3d8e2Sdanielk1977 static int test_bind_blob(
179351e3d8e2Sdanielk1977   void * clientData,
179451e3d8e2Sdanielk1977   Tcl_Interp *interp,
179551e3d8e2Sdanielk1977   int objc,
179651e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
179751e3d8e2Sdanielk1977 ){
179851e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
179951e3d8e2Sdanielk1977   int idx;
180051e3d8e2Sdanielk1977   int bytes;
180151e3d8e2Sdanielk1977   char *value;
180251e3d8e2Sdanielk1977   int rc;
180351e3d8e2Sdanielk1977 
180451e3d8e2Sdanielk1977   if( objc!=5 ){
180551e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1806241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
180751e3d8e2Sdanielk1977     return TCL_ERROR;
180851e3d8e2Sdanielk1977   }
180951e3d8e2Sdanielk1977 
181051e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
181151e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
181251e3d8e2Sdanielk1977   value = Tcl_GetString(objv[3]);
181349e4643eSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
181451e3d8e2Sdanielk1977 
1815d8123366Sdanielk1977   rc = sqlite3_bind_blob(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
1816c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
181751e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
181851e3d8e2Sdanielk1977     return TCL_ERROR;
181951e3d8e2Sdanielk1977   }
182051e3d8e2Sdanielk1977 
182151e3d8e2Sdanielk1977   return TCL_OK;
182251e3d8e2Sdanielk1977 }
182351e3d8e2Sdanielk1977 
182499ee3600Sdrh /*
182575f6a032Sdrh ** Usage:   sqlite3_bind_parameter_count  STMT
182675f6a032Sdrh **
182775f6a032Sdrh ** Return the number of wildcards in the given statement.
182875f6a032Sdrh */
182975f6a032Sdrh static int test_bind_parameter_count(
183075f6a032Sdrh   void * clientData,
183175f6a032Sdrh   Tcl_Interp *interp,
183275f6a032Sdrh   int objc,
183375f6a032Sdrh   Tcl_Obj *CONST objv[]
183475f6a032Sdrh ){
183575f6a032Sdrh   sqlite3_stmt *pStmt;
183675f6a032Sdrh 
183775f6a032Sdrh   if( objc!=2 ){
183875f6a032Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "STMT");
183975f6a032Sdrh     return TCL_ERROR;
184075f6a032Sdrh   }
184175f6a032Sdrh   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
184275f6a032Sdrh   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
184375f6a032Sdrh   return TCL_OK;
184475f6a032Sdrh }
184575f6a032Sdrh 
184675f6a032Sdrh /*
1847895d7472Sdrh ** Usage:   sqlite3_bind_parameter_name  STMT  N
1848895d7472Sdrh **
1849895d7472Sdrh ** Return the name of the Nth wildcard.  The first wildcard is 1.
1850895d7472Sdrh ** An empty string is returned if N is out of range or if the wildcard
1851895d7472Sdrh ** is nameless.
1852895d7472Sdrh */
1853895d7472Sdrh static int test_bind_parameter_name(
1854895d7472Sdrh   void * clientData,
1855895d7472Sdrh   Tcl_Interp *interp,
1856895d7472Sdrh   int objc,
1857895d7472Sdrh   Tcl_Obj *CONST objv[]
1858895d7472Sdrh ){
1859895d7472Sdrh   sqlite3_stmt *pStmt;
1860895d7472Sdrh   int i;
1861895d7472Sdrh 
1862895d7472Sdrh   if( objc!=3 ){
1863895d7472Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
1864895d7472Sdrh     return TCL_ERROR;
1865895d7472Sdrh   }
1866895d7472Sdrh   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1867895d7472Sdrh   if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
1868895d7472Sdrh   Tcl_SetObjResult(interp,
1869895d7472Sdrh      Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
1870895d7472Sdrh   );
1871895d7472Sdrh   return TCL_OK;
1872895d7472Sdrh }
1873895d7472Sdrh 
1874895d7472Sdrh /*
1875fa6bc000Sdrh ** Usage:   sqlite3_bind_parameter_index  STMT  NAME
1876fa6bc000Sdrh **
1877fa6bc000Sdrh ** Return the index of the wildcard called NAME.  Return 0 if there is
1878fa6bc000Sdrh ** no such wildcard.
1879fa6bc000Sdrh */
1880fa6bc000Sdrh static int test_bind_parameter_index(
1881fa6bc000Sdrh   void * clientData,
1882fa6bc000Sdrh   Tcl_Interp *interp,
1883fa6bc000Sdrh   int objc,
1884fa6bc000Sdrh   Tcl_Obj *CONST objv[]
1885fa6bc000Sdrh ){
1886fa6bc000Sdrh   sqlite3_stmt *pStmt;
1887fa6bc000Sdrh 
1888fa6bc000Sdrh   if( objc!=3 ){
1889fa6bc000Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
1890fa6bc000Sdrh     return TCL_ERROR;
1891fa6bc000Sdrh   }
1892fa6bc000Sdrh   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1893fa6bc000Sdrh   Tcl_SetObjResult(interp,
1894fa6bc000Sdrh      Tcl_NewIntObj(
1895fa6bc000Sdrh        sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
1896fa6bc000Sdrh      )
1897fa6bc000Sdrh   );
1898fa6bc000Sdrh   return TCL_OK;
1899fa6bc000Sdrh }
1900fa6bc000Sdrh 
1901fa6bc000Sdrh /*
1902600dd0baSdanielk1977 ** Usage:   sqlite3_clear_bindings STMT
1903600dd0baSdanielk1977 **
1904600dd0baSdanielk1977 */
1905600dd0baSdanielk1977 #if 0
1906600dd0baSdanielk1977 static int test_clear_bindings(
1907600dd0baSdanielk1977   void * clientData,
1908600dd0baSdanielk1977   Tcl_Interp *interp,
1909600dd0baSdanielk1977   int objc,
1910600dd0baSdanielk1977   Tcl_Obj *CONST objv[]
1911600dd0baSdanielk1977 ){
1912600dd0baSdanielk1977   sqlite3_stmt *pStmt;
1913600dd0baSdanielk1977 
1914600dd0baSdanielk1977   if( objc!=2 ){
1915600dd0baSdanielk1977     Tcl_WrongNumArgs(interp, 1, objv, "STMT");
1916600dd0baSdanielk1977     return TCL_ERROR;
1917600dd0baSdanielk1977   }
1918600dd0baSdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1919600dd0baSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
1920600dd0baSdanielk1977   return TCL_OK;
1921600dd0baSdanielk1977 }
1922600dd0baSdanielk1977 #endif
1923600dd0baSdanielk1977 
1924600dd0baSdanielk1977 /*
19256622cce3Sdanielk1977 ** Usage: sqlite3_errcode DB
19266622cce3Sdanielk1977 **
19276622cce3Sdanielk1977 ** Return the string representation of the most recent sqlite3_* API
19286622cce3Sdanielk1977 ** error code. e.g. "SQLITE_ERROR".
19296622cce3Sdanielk1977 */
19306622cce3Sdanielk1977 static int test_errcode(
19316622cce3Sdanielk1977   void * clientData,
19326622cce3Sdanielk1977   Tcl_Interp *interp,
19336622cce3Sdanielk1977   int objc,
19346622cce3Sdanielk1977   Tcl_Obj *CONST objv[]
19356622cce3Sdanielk1977 ){
19366622cce3Sdanielk1977   sqlite3 *db;
19376622cce3Sdanielk1977 
19386622cce3Sdanielk1977   if( objc!=2 ){
19396622cce3Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
19406622cce3Sdanielk1977        Tcl_GetString(objv[0]), " DB", 0);
19416622cce3Sdanielk1977     return TCL_ERROR;
19426622cce3Sdanielk1977   }
19436622cce3Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
19446622cce3Sdanielk1977   Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0);
19456622cce3Sdanielk1977   return TCL_OK;
19466622cce3Sdanielk1977 }
19476622cce3Sdanielk1977 
19486622cce3Sdanielk1977 /*
19496622cce3Sdanielk1977 ** Usage:   test_errmsg DB
19506622cce3Sdanielk1977 **
19516622cce3Sdanielk1977 ** Returns the UTF-8 representation of the error message string for the
19526622cce3Sdanielk1977 ** most recent sqlite3_* API call.
19536622cce3Sdanielk1977 */
19546622cce3Sdanielk1977 static int test_errmsg(
19556622cce3Sdanielk1977   void * clientData,
19566622cce3Sdanielk1977   Tcl_Interp *interp,
19576622cce3Sdanielk1977   int objc,
19586622cce3Sdanielk1977   Tcl_Obj *CONST objv[]
19596622cce3Sdanielk1977 ){
19609bb575fdSdrh   sqlite3 *db;
19616622cce3Sdanielk1977   const char *zErr;
19626622cce3Sdanielk1977 
19636622cce3Sdanielk1977   if( objc!=2 ){
19646622cce3Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
19656622cce3Sdanielk1977        Tcl_GetString(objv[0]), " DB", 0);
19666622cce3Sdanielk1977     return TCL_ERROR;
19676622cce3Sdanielk1977   }
19686622cce3Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
19696622cce3Sdanielk1977 
19706622cce3Sdanielk1977   zErr = sqlite3_errmsg(db);
19716622cce3Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
19726622cce3Sdanielk1977   return TCL_OK;
19736622cce3Sdanielk1977 }
19746622cce3Sdanielk1977 
19756622cce3Sdanielk1977 /*
19766622cce3Sdanielk1977 ** Usage:   test_errmsg16 DB
19776622cce3Sdanielk1977 **
19786622cce3Sdanielk1977 ** Returns the UTF-16 representation of the error message string for the
19796622cce3Sdanielk1977 ** most recent sqlite3_* API call. This is a byte array object at the TCL
19806622cce3Sdanielk1977 ** level, and it includes the 0x00 0x00 terminator bytes at the end of the
19816622cce3Sdanielk1977 ** UTF-16 string.
19826622cce3Sdanielk1977 */
19836622cce3Sdanielk1977 static int test_errmsg16(
19846622cce3Sdanielk1977   void * clientData,
19856622cce3Sdanielk1977   Tcl_Interp *interp,
19866622cce3Sdanielk1977   int objc,
19876622cce3Sdanielk1977   Tcl_Obj *CONST objv[]
19886622cce3Sdanielk1977 ){
19895436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
19909bb575fdSdrh   sqlite3 *db;
19916622cce3Sdanielk1977   const void *zErr;
19926622cce3Sdanielk1977   int bytes;
19936622cce3Sdanielk1977 
19946622cce3Sdanielk1977   if( objc!=2 ){
19956622cce3Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
19966622cce3Sdanielk1977        Tcl_GetString(objv[0]), " DB", 0);
19976622cce3Sdanielk1977     return TCL_ERROR;
19986622cce3Sdanielk1977   }
19996622cce3Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
20006622cce3Sdanielk1977 
20016622cce3Sdanielk1977   zErr = sqlite3_errmsg16(db);
20026622cce3Sdanielk1977   bytes = sqlite3utf16ByteLen(zErr, -1);
20036622cce3Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
20045436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
20056622cce3Sdanielk1977   return TCL_OK;
20066622cce3Sdanielk1977 }
20076622cce3Sdanielk1977 
20086622cce3Sdanielk1977 /*
20096622cce3Sdanielk1977 ** Usage: sqlite3_prepare DB sql bytes tailvar
20106622cce3Sdanielk1977 **
20116622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
20126622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global
20136622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A
20146622cce3Sdanielk1977 ** STMT handle is returned.
20156622cce3Sdanielk1977 */
20166622cce3Sdanielk1977 static int test_prepare(
20176622cce3Sdanielk1977   void * clientData,
20186622cce3Sdanielk1977   Tcl_Interp *interp,
20196622cce3Sdanielk1977   int objc,
20206622cce3Sdanielk1977   Tcl_Obj *CONST objv[]
20216622cce3Sdanielk1977 ){
20226622cce3Sdanielk1977   sqlite3 *db;
20236622cce3Sdanielk1977   const char *zSql;
20246622cce3Sdanielk1977   int bytes;
20256622cce3Sdanielk1977   const char *zTail = 0;
20266622cce3Sdanielk1977   sqlite3_stmt *pStmt = 0;
20276622cce3Sdanielk1977   char zBuf[50];
20284ad1713cSdanielk1977   int rc;
20296622cce3Sdanielk1977 
20306622cce3Sdanielk1977   if( objc!=5 ){
20316622cce3Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
20326622cce3Sdanielk1977        Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
20336622cce3Sdanielk1977     return TCL_ERROR;
20346622cce3Sdanielk1977   }
20356622cce3Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
20366622cce3Sdanielk1977   zSql = Tcl_GetString(objv[2]);
20376622cce3Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
20386622cce3Sdanielk1977 
20394ad1713cSdanielk1977   rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail);
2040c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
20416622cce3Sdanielk1977   if( zTail ){
20426622cce3Sdanielk1977     if( bytes>=0 ){
20436622cce3Sdanielk1977       bytes = bytes - (zTail-zSql);
20446622cce3Sdanielk1977     }
20456622cce3Sdanielk1977     Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
20466622cce3Sdanielk1977   }
20474ad1713cSdanielk1977   if( rc!=SQLITE_OK ){
20484ad1713cSdanielk1977     assert( pStmt==0 );
20494ad1713cSdanielk1977     sprintf(zBuf, "(%d) ", rc);
20504ad1713cSdanielk1977     Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
20514ad1713cSdanielk1977     return TCL_ERROR;
20524ad1713cSdanielk1977   }
20536622cce3Sdanielk1977 
20544ad1713cSdanielk1977   if( pStmt ){
20556622cce3Sdanielk1977     if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
20566622cce3Sdanielk1977     Tcl_AppendResult(interp, zBuf, 0);
20574ad1713cSdanielk1977   }
20586622cce3Sdanielk1977   return TCL_OK;
20596622cce3Sdanielk1977 }
20606622cce3Sdanielk1977 
20616622cce3Sdanielk1977 /*
20626622cce3Sdanielk1977 ** Usage: sqlite3_prepare DB sql bytes tailvar
20636622cce3Sdanielk1977 **
20646622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
20656622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global
20666622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A
20676622cce3Sdanielk1977 ** STMT handle is returned.
20686622cce3Sdanielk1977 */
20696622cce3Sdanielk1977 static int test_prepare16(
20706622cce3Sdanielk1977   void * clientData,
20716622cce3Sdanielk1977   Tcl_Interp *interp,
20726622cce3Sdanielk1977   int objc,
20736622cce3Sdanielk1977   Tcl_Obj *CONST objv[]
20746622cce3Sdanielk1977 ){
20755436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
20766622cce3Sdanielk1977   sqlite3 *db;
20776622cce3Sdanielk1977   const void *zSql;
20786622cce3Sdanielk1977   const void *zTail = 0;
20796622cce3Sdanielk1977   Tcl_Obj *pTail = 0;
20806622cce3Sdanielk1977   sqlite3_stmt *pStmt = 0;
20816622cce3Sdanielk1977   char zBuf[50];
2082c60d0446Sdrh   int rc;
20836622cce3Sdanielk1977   int bytes;                /* The integer specified as arg 3 */
20846622cce3Sdanielk1977   int objlen;               /* The byte-array length of arg 2 */
20856622cce3Sdanielk1977 
20866622cce3Sdanielk1977   if( objc!=5 ){
20876622cce3Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
20886622cce3Sdanielk1977        Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
20896622cce3Sdanielk1977     return TCL_ERROR;
20906622cce3Sdanielk1977   }
20916622cce3Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
20926622cce3Sdanielk1977   zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
20936622cce3Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
20946622cce3Sdanielk1977 
2095c60d0446Sdrh   rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail);
2096c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
2097c60d0446Sdrh   if( rc ){
20986622cce3Sdanielk1977     return TCL_ERROR;
20996622cce3Sdanielk1977   }
21006622cce3Sdanielk1977 
21016622cce3Sdanielk1977   if( zTail ){
21026622cce3Sdanielk1977     objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
21036622cce3Sdanielk1977   }else{
21046622cce3Sdanielk1977     objlen = 0;
21056622cce3Sdanielk1977   }
21066622cce3Sdanielk1977   pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
21076622cce3Sdanielk1977   Tcl_IncrRefCount(pTail);
21086622cce3Sdanielk1977   Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
21094ad1713cSdanielk1977   Tcl_DecrRefCount(pTail);
21106622cce3Sdanielk1977 
21114ad1713cSdanielk1977   if( pStmt ){
21126622cce3Sdanielk1977     if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
21134ad1713cSdanielk1977   }
21146622cce3Sdanielk1977   Tcl_AppendResult(interp, zBuf, 0);
21155436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
21166622cce3Sdanielk1977   return TCL_OK;
21176622cce3Sdanielk1977 }
21186622cce3Sdanielk1977 
21194ad1713cSdanielk1977 /*
21204ad1713cSdanielk1977 ** Usage: sqlite3_open filename ?options-list?
21214ad1713cSdanielk1977 */
21224ad1713cSdanielk1977 static int test_open(
21234ad1713cSdanielk1977   void * clientData,
21244ad1713cSdanielk1977   Tcl_Interp *interp,
21254ad1713cSdanielk1977   int objc,
21264ad1713cSdanielk1977   Tcl_Obj *CONST objv[]
21274ad1713cSdanielk1977 ){
21284ad1713cSdanielk1977   const char *zFilename;
21294ad1713cSdanielk1977   sqlite3 *db;
21304ad1713cSdanielk1977   int rc;
21314ad1713cSdanielk1977   char zBuf[100];
21324ad1713cSdanielk1977 
21334ad1713cSdanielk1977   if( objc!=3 && objc!=2 ){
21344ad1713cSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
21354ad1713cSdanielk1977        Tcl_GetString(objv[0]), " filename options-list", 0);
21364ad1713cSdanielk1977     return TCL_ERROR;
21374ad1713cSdanielk1977   }
21384ad1713cSdanielk1977 
21394ad1713cSdanielk1977   zFilename = Tcl_GetString(objv[1]);
21404f057f90Sdanielk1977   rc = sqlite3_open(zFilename, &db);
21414ad1713cSdanielk1977 
21424ad1713cSdanielk1977   if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
21434ad1713cSdanielk1977   Tcl_AppendResult(interp, zBuf, 0);
21444ad1713cSdanielk1977   return TCL_OK;
21454ad1713cSdanielk1977 }
21464ad1713cSdanielk1977 
21474ad1713cSdanielk1977 /*
21484ad1713cSdanielk1977 ** Usage: sqlite3_open16 filename options
21494ad1713cSdanielk1977 */
21504ad1713cSdanielk1977 static int test_open16(
21514ad1713cSdanielk1977   void * clientData,
21524ad1713cSdanielk1977   Tcl_Interp *interp,
21534ad1713cSdanielk1977   int objc,
21544ad1713cSdanielk1977   Tcl_Obj *CONST objv[]
21554ad1713cSdanielk1977 ){
21565436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
21574ad1713cSdanielk1977   const void *zFilename;
21584ad1713cSdanielk1977   sqlite3 *db;
21594ad1713cSdanielk1977   int rc;
21604ad1713cSdanielk1977   char zBuf[100];
21614ad1713cSdanielk1977 
21624ad1713cSdanielk1977   if( objc!=3 ){
21634ad1713cSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
21644ad1713cSdanielk1977        Tcl_GetString(objv[0]), " filename options-list", 0);
21654ad1713cSdanielk1977     return TCL_ERROR;
21664ad1713cSdanielk1977   }
21674ad1713cSdanielk1977 
21684ad1713cSdanielk1977   zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
21694f057f90Sdanielk1977   rc = sqlite3_open16(zFilename, &db);
21704ad1713cSdanielk1977 
21714ad1713cSdanielk1977   if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
21724ad1713cSdanielk1977   Tcl_AppendResult(interp, zBuf, 0);
21735436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
21744ad1713cSdanielk1977   return TCL_OK;
21754ad1713cSdanielk1977 }
2176d3d39e93Sdrh 
2177d3d39e93Sdrh /*
2178bc6ada41Sdanielk1977 ** Usage: sqlite3_complete16 <UTF-16 string>
2179bc6ada41Sdanielk1977 **
2180bc6ada41Sdanielk1977 ** Return 1 if the supplied argument is a complete SQL statement, or zero
2181bc6ada41Sdanielk1977 ** otherwise.
2182bc6ada41Sdanielk1977 */
2183bc6ada41Sdanielk1977 static int test_complete16(
2184bc6ada41Sdanielk1977   void * clientData,
2185bc6ada41Sdanielk1977   Tcl_Interp *interp,
2186bc6ada41Sdanielk1977   int objc,
2187bc6ada41Sdanielk1977   Tcl_Obj *CONST objv[]
2188bc6ada41Sdanielk1977 ){
2189ccae6026Sdrh #if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16)
2190bc6ada41Sdanielk1977   char *zBuf;
2191bc6ada41Sdanielk1977 
2192bc6ada41Sdanielk1977   if( objc!=2 ){
2193bc6ada41Sdanielk1977     Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
2194bc6ada41Sdanielk1977     return TCL_ERROR;
2195bc6ada41Sdanielk1977   }
2196bc6ada41Sdanielk1977 
219703d847eaSdrh   zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0);
2198bc6ada41Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
2199ccae6026Sdrh #endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */
2200bc6ada41Sdanielk1977   return TCL_OK;
2201bc6ada41Sdanielk1977 }
2202bc6ada41Sdanielk1977 
2203bc6ada41Sdanielk1977 /*
2204106bb236Sdanielk1977 ** Usage: sqlite3_step STMT
2205106bb236Sdanielk1977 **
2206106bb236Sdanielk1977 ** Advance the statement to the next row.
2207106bb236Sdanielk1977 */
220817240fd9Sdanielk1977 static int test_step(
2209106bb236Sdanielk1977   void * clientData,
2210106bb236Sdanielk1977   Tcl_Interp *interp,
2211106bb236Sdanielk1977   int objc,
2212106bb236Sdanielk1977   Tcl_Obj *CONST objv[]
2213106bb236Sdanielk1977 ){
2214106bb236Sdanielk1977   sqlite3_stmt *pStmt;
2215106bb236Sdanielk1977   int rc;
2216106bb236Sdanielk1977 
2217e1cd9874Sdanielk1977   if( objc!=2 ){
2218106bb236Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
2219106bb236Sdanielk1977        Tcl_GetString(objv[0]), " STMT", 0);
2220106bb236Sdanielk1977     return TCL_ERROR;
2221106bb236Sdanielk1977   }
2222106bb236Sdanielk1977 
2223106bb236Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
222417240fd9Sdanielk1977   rc = sqlite3_step(pStmt);
2225106bb236Sdanielk1977 
2226fbcd585fSdanielk1977   /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
22276590493dSdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), 0);
2228e1cd9874Sdanielk1977   return TCL_OK;
2229e1cd9874Sdanielk1977 }
2230e1cd9874Sdanielk1977 
2231e1cd9874Sdanielk1977 /*
223217240fd9Sdanielk1977 ** Usage: sqlite3_column_count STMT
223317240fd9Sdanielk1977 **
223417240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT.
223517240fd9Sdanielk1977 */
223617240fd9Sdanielk1977 static int test_column_count(
223717240fd9Sdanielk1977   void * clientData,
223817240fd9Sdanielk1977   Tcl_Interp *interp,
223917240fd9Sdanielk1977   int objc,
224017240fd9Sdanielk1977   Tcl_Obj *CONST objv[]
224117240fd9Sdanielk1977 ){
224217240fd9Sdanielk1977   sqlite3_stmt *pStmt;
224317240fd9Sdanielk1977 
224417240fd9Sdanielk1977   if( objc!=2 ){
224517240fd9Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
224617240fd9Sdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
224717240fd9Sdanielk1977     return TCL_ERROR;
224817240fd9Sdanielk1977   }
224917240fd9Sdanielk1977 
225017240fd9Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
225117240fd9Sdanielk1977 
225217240fd9Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
225317240fd9Sdanielk1977   return TCL_OK;
225417240fd9Sdanielk1977 }
225517240fd9Sdanielk1977 
225617240fd9Sdanielk1977 /*
22573cf86063Sdanielk1977 ** Usage: sqlite3_column_type STMT column
22583cf86063Sdanielk1977 **
22593cf86063Sdanielk1977 ** Return the type of the data in column 'column' of the current row.
22603cf86063Sdanielk1977 */
22613cf86063Sdanielk1977 static int test_column_type(
22623cf86063Sdanielk1977   void * clientData,
22633cf86063Sdanielk1977   Tcl_Interp *interp,
22643cf86063Sdanielk1977   int objc,
22653cf86063Sdanielk1977   Tcl_Obj *CONST objv[]
22663cf86063Sdanielk1977 ){
22673cf86063Sdanielk1977   sqlite3_stmt *pStmt;
22683cf86063Sdanielk1977   int col;
22693cf86063Sdanielk1977   int tp;
22703cf86063Sdanielk1977 
22713cf86063Sdanielk1977   if( objc!=3 ){
22723cf86063Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
22733cf86063Sdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
22743cf86063Sdanielk1977     return TCL_ERROR;
22753cf86063Sdanielk1977   }
22763cf86063Sdanielk1977 
22773cf86063Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
22783cf86063Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
22793cf86063Sdanielk1977 
22803cf86063Sdanielk1977   tp = sqlite3_column_type(pStmt, col);
22813cf86063Sdanielk1977   switch( tp ){
22829c054830Sdrh     case SQLITE_INTEGER:
22833cf86063Sdanielk1977       Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
22843cf86063Sdanielk1977       break;
22859c054830Sdrh     case SQLITE_NULL:
22863cf86063Sdanielk1977       Tcl_SetResult(interp, "NULL", TCL_STATIC);
22873cf86063Sdanielk1977       break;
22889c054830Sdrh     case SQLITE_FLOAT:
22893cf86063Sdanielk1977       Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
22903cf86063Sdanielk1977       break;
22919c054830Sdrh     case SQLITE_TEXT:
22923cf86063Sdanielk1977       Tcl_SetResult(interp, "TEXT", TCL_STATIC);
22933cf86063Sdanielk1977       break;
22949c054830Sdrh     case SQLITE_BLOB:
22953cf86063Sdanielk1977       Tcl_SetResult(interp, "BLOB", TCL_STATIC);
22963cf86063Sdanielk1977       break;
22973cf86063Sdanielk1977     default:
22983cf86063Sdanielk1977       assert(0);
22993cf86063Sdanielk1977   }
23003cf86063Sdanielk1977 
23013cf86063Sdanielk1977   return TCL_OK;
23023cf86063Sdanielk1977 }
23033cf86063Sdanielk1977 
23043cf86063Sdanielk1977 /*
230504f2e68dSdanielk1977 ** Usage: sqlite3_column_int64 STMT column
23063cf86063Sdanielk1977 **
23073cf86063Sdanielk1977 ** Return the data in column 'column' of the current row cast as an
230804f2e68dSdanielk1977 ** wide (64-bit) integer.
23093cf86063Sdanielk1977 */
231004f2e68dSdanielk1977 static int test_column_int64(
23113cf86063Sdanielk1977   void * clientData,
23123cf86063Sdanielk1977   Tcl_Interp *interp,
23133cf86063Sdanielk1977   int objc,
23143cf86063Sdanielk1977   Tcl_Obj *CONST objv[]
23153cf86063Sdanielk1977 ){
23163cf86063Sdanielk1977   sqlite3_stmt *pStmt;
23173cf86063Sdanielk1977   int col;
231804f2e68dSdanielk1977   i64 iVal;
23193cf86063Sdanielk1977 
23203cf86063Sdanielk1977   if( objc!=3 ){
23213cf86063Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
23223cf86063Sdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
23233cf86063Sdanielk1977     return TCL_ERROR;
23243cf86063Sdanielk1977   }
23253cf86063Sdanielk1977 
23263cf86063Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
23273cf86063Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
23283cf86063Sdanielk1977 
232904f2e68dSdanielk1977   iVal = sqlite3_column_int64(pStmt, col);
233004f2e68dSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
233104f2e68dSdanielk1977   return TCL_OK;
233204f2e68dSdanielk1977 }
233304f2e68dSdanielk1977 
233404f2e68dSdanielk1977 /*
2335ea61b2c4Sdanielk1977 ** Usage: sqlite3_column_blob STMT column
2336ea61b2c4Sdanielk1977 */
2337ea61b2c4Sdanielk1977 static int test_column_blob(
2338ea61b2c4Sdanielk1977   void * clientData,
2339ea61b2c4Sdanielk1977   Tcl_Interp *interp,
2340ea61b2c4Sdanielk1977   int objc,
2341ea61b2c4Sdanielk1977   Tcl_Obj *CONST objv[]
2342ea61b2c4Sdanielk1977 ){
2343ea61b2c4Sdanielk1977   sqlite3_stmt *pStmt;
2344ea61b2c4Sdanielk1977   int col;
2345ea61b2c4Sdanielk1977 
2346ea61b2c4Sdanielk1977   int len;
2347c572ef7fSdanielk1977   const void *pBlob;
2348ea61b2c4Sdanielk1977 
2349ea61b2c4Sdanielk1977   if( objc!=3 ){
2350ea61b2c4Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
2351ea61b2c4Sdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
2352ea61b2c4Sdanielk1977     return TCL_ERROR;
2353ea61b2c4Sdanielk1977   }
2354ea61b2c4Sdanielk1977 
2355ea61b2c4Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2356ea61b2c4Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2357ea61b2c4Sdanielk1977 
2358ea61b2c4Sdanielk1977   pBlob = sqlite3_column_blob(pStmt, col);
2359ea61b2c4Sdanielk1977   len = sqlite3_column_bytes(pStmt, col);
2360ea61b2c4Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
2361ea61b2c4Sdanielk1977   return TCL_OK;
2362ea61b2c4Sdanielk1977 }
2363ea61b2c4Sdanielk1977 
2364ea61b2c4Sdanielk1977 /*
236504f2e68dSdanielk1977 ** Usage: sqlite3_column_double STMT column
236604f2e68dSdanielk1977 **
236704f2e68dSdanielk1977 ** Return the data in column 'column' of the current row cast as a double.
236804f2e68dSdanielk1977 */
236904f2e68dSdanielk1977 static int test_column_double(
237004f2e68dSdanielk1977   void * clientData,
237104f2e68dSdanielk1977   Tcl_Interp *interp,
237204f2e68dSdanielk1977   int objc,
237304f2e68dSdanielk1977   Tcl_Obj *CONST objv[]
237404f2e68dSdanielk1977 ){
237504f2e68dSdanielk1977   sqlite3_stmt *pStmt;
237604f2e68dSdanielk1977   int col;
237704f2e68dSdanielk1977   double rVal;
237804f2e68dSdanielk1977 
237904f2e68dSdanielk1977   if( objc!=3 ){
238004f2e68dSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
238104f2e68dSdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
238204f2e68dSdanielk1977     return TCL_ERROR;
238304f2e68dSdanielk1977   }
238404f2e68dSdanielk1977 
238504f2e68dSdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
238604f2e68dSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
238704f2e68dSdanielk1977 
238804f2e68dSdanielk1977   rVal = sqlite3_column_double(pStmt, col);
2389c572ef7fSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
23903cf86063Sdanielk1977   return TCL_OK;
23913cf86063Sdanielk1977 }
23923cf86063Sdanielk1977 
23933cf86063Sdanielk1977 /*
239417240fd9Sdanielk1977 ** Usage: sqlite3_data_count STMT
239517240fd9Sdanielk1977 **
239617240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT.
239717240fd9Sdanielk1977 */
239817240fd9Sdanielk1977 static int test_data_count(
239917240fd9Sdanielk1977   void * clientData,
240017240fd9Sdanielk1977   Tcl_Interp *interp,
240117240fd9Sdanielk1977   int objc,
240217240fd9Sdanielk1977   Tcl_Obj *CONST objv[]
240317240fd9Sdanielk1977 ){
240417240fd9Sdanielk1977   sqlite3_stmt *pStmt;
240517240fd9Sdanielk1977 
240617240fd9Sdanielk1977   if( objc!=2 ){
240717240fd9Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
240817240fd9Sdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
240917240fd9Sdanielk1977     return TCL_ERROR;
241017240fd9Sdanielk1977   }
241117240fd9Sdanielk1977 
241217240fd9Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
241317240fd9Sdanielk1977 
241417240fd9Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
241517240fd9Sdanielk1977   return TCL_OK;
241617240fd9Sdanielk1977 }
241717240fd9Sdanielk1977 
241817240fd9Sdanielk1977 /*
241904f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column
242004f2e68dSdanielk1977 **
242104f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column
242204f2e68dSdanielk1977 **
242304f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column
242404f2e68dSdanielk1977 */
242504f2e68dSdanielk1977 static int test_stmt_utf8(
2426241db313Sdrh   void * clientData,        /* Pointer to SQLite API function to be invoke */
242704f2e68dSdanielk1977   Tcl_Interp *interp,
242804f2e68dSdanielk1977   int objc,
242904f2e68dSdanielk1977   Tcl_Obj *CONST objv[]
243004f2e68dSdanielk1977 ){
243104f2e68dSdanielk1977   sqlite3_stmt *pStmt;
243204f2e68dSdanielk1977   int col;
2433c572ef7fSdanielk1977   const char *(*xFunc)(sqlite3_stmt*, int) = clientData;
2434f93bbbeaSdanielk1977   const char *zRet;
243504f2e68dSdanielk1977 
243604f2e68dSdanielk1977   if( objc!=3 ){
243704f2e68dSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
243804f2e68dSdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
243904f2e68dSdanielk1977     return TCL_ERROR;
244004f2e68dSdanielk1977   }
244104f2e68dSdanielk1977 
244204f2e68dSdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
244304f2e68dSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2444f93bbbeaSdanielk1977   zRet = xFunc(pStmt, col);
2445f93bbbeaSdanielk1977   if( zRet ){
2446f93bbbeaSdanielk1977     Tcl_SetResult(interp, (char *)zRet, 0);
2447f93bbbeaSdanielk1977   }
244804f2e68dSdanielk1977   return TCL_OK;
244904f2e68dSdanielk1977 }
245004f2e68dSdanielk1977 
24516b456a2bSdanielk1977 static int test_global_recover(
24526b456a2bSdanielk1977   void * clientData,
24536b456a2bSdanielk1977   Tcl_Interp *interp,
24546b456a2bSdanielk1977   int objc,
24556b456a2bSdanielk1977   Tcl_Obj *CONST objv[]
24566b456a2bSdanielk1977 ){
24576b456a2bSdanielk1977 #ifndef SQLITE_OMIT_GLOBALRECOVER
24586b456a2bSdanielk1977   int rc;
24596b456a2bSdanielk1977   if( objc!=1 ){
24606b456a2bSdanielk1977     Tcl_WrongNumArgs(interp, 1, objv, "");
24616b456a2bSdanielk1977     return TCL_ERROR;
24626b456a2bSdanielk1977   }
24636b456a2bSdanielk1977   rc = sqlite3_global_recover();
24646b456a2bSdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
24656b456a2bSdanielk1977 #endif
24666b456a2bSdanielk1977   return TCL_OK;
24676b456a2bSdanielk1977 }
24686b456a2bSdanielk1977 
246904f2e68dSdanielk1977 /*
247004f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column
247104f2e68dSdanielk1977 **
247204f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column
247304f2e68dSdanielk1977 **
247404f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column
247504f2e68dSdanielk1977 */
247604f2e68dSdanielk1977 static int test_stmt_utf16(
2477241db313Sdrh   void * clientData,     /* Pointer to SQLite API function to be invoked */
247804f2e68dSdanielk1977   Tcl_Interp *interp,
247904f2e68dSdanielk1977   int objc,
248004f2e68dSdanielk1977   Tcl_Obj *CONST objv[]
248104f2e68dSdanielk1977 ){
24825436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
248304f2e68dSdanielk1977   sqlite3_stmt *pStmt;
248404f2e68dSdanielk1977   int col;
248504f2e68dSdanielk1977   Tcl_Obj *pRet;
248604f2e68dSdanielk1977   const void *zName16;
2487c572ef7fSdanielk1977   const void *(*xFunc)(sqlite3_stmt*, int) = clientData;
248804f2e68dSdanielk1977 
248904f2e68dSdanielk1977   if( objc!=3 ){
249004f2e68dSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
249104f2e68dSdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
249204f2e68dSdanielk1977     return TCL_ERROR;
249304f2e68dSdanielk1977   }
249404f2e68dSdanielk1977 
249504f2e68dSdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
249604f2e68dSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
249704f2e68dSdanielk1977 
249804f2e68dSdanielk1977   zName16 = xFunc(pStmt, col);
2499f93bbbeaSdanielk1977   if( zName16 ){
250004f2e68dSdanielk1977     pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2);
250104f2e68dSdanielk1977     Tcl_SetObjResult(interp, pRet);
2502f93bbbeaSdanielk1977   }
25035436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
250404f2e68dSdanielk1977 
250504f2e68dSdanielk1977   return TCL_OK;
250604f2e68dSdanielk1977 }
250704f2e68dSdanielk1977 
250804f2e68dSdanielk1977 /*
250904f2e68dSdanielk1977 ** Usage: sqlite3_column_int STMT column
251004f2e68dSdanielk1977 **
251104f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes STMT column
251204f2e68dSdanielk1977 **
251304f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes16 STMT column
251404f2e68dSdanielk1977 **
251504f2e68dSdanielk1977 */
251604f2e68dSdanielk1977 static int test_stmt_int(
2517241db313Sdrh   void * clientData,    /* Pointer to SQLite API function to be invoked */
251804f2e68dSdanielk1977   Tcl_Interp *interp,
251904f2e68dSdanielk1977   int objc,
252004f2e68dSdanielk1977   Tcl_Obj *CONST objv[]
252104f2e68dSdanielk1977 ){
252204f2e68dSdanielk1977   sqlite3_stmt *pStmt;
252304f2e68dSdanielk1977   int col;
2524c572ef7fSdanielk1977   int (*xFunc)(sqlite3_stmt*, int) = clientData;
252504f2e68dSdanielk1977 
252604f2e68dSdanielk1977   if( objc!=3 ){
252704f2e68dSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
252804f2e68dSdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
252904f2e68dSdanielk1977     return TCL_ERROR;
253004f2e68dSdanielk1977   }
253104f2e68dSdanielk1977 
253204f2e68dSdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
253304f2e68dSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
253404f2e68dSdanielk1977 
253504f2e68dSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
253604f2e68dSdanielk1977   return TCL_OK;
253704f2e68dSdanielk1977 }
253804f2e68dSdanielk1977 
253944ee5bf7Sdanielk1977 #ifndef SQLITE_OMIT_DISKIO
25409a1d0abeSdanielk1977 /*
25419a1d0abeSdanielk1977 ** Usage:  sqlite3OsOpenReadWrite <filename>
25429a1d0abeSdanielk1977 */
25439a1d0abeSdanielk1977 static int test_sqlite3OsOpenReadWrite(
25449a1d0abeSdanielk1977   void * clientData,
25459a1d0abeSdanielk1977   Tcl_Interp *interp,
25469a1d0abeSdanielk1977   int objc,
25479a1d0abeSdanielk1977   Tcl_Obj *CONST objv[]
25489a1d0abeSdanielk1977 ){
25499a1d0abeSdanielk1977   OsFile *pFile;
25509a1d0abeSdanielk1977   int rc;
25519a1d0abeSdanielk1977   int dummy;
25529a1d0abeSdanielk1977   char zBuf[100];
255304f2e68dSdanielk1977 
25549a1d0abeSdanielk1977   if( objc!=2 ){
25559a1d0abeSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
25569a1d0abeSdanielk1977        Tcl_GetString(objv[0]), " filename", 0);
25579a1d0abeSdanielk1977     return TCL_ERROR;
25589a1d0abeSdanielk1977   }
25599a1d0abeSdanielk1977 
2560054889ecSdrh   rc = sqlite3Os.xOpenReadWrite(Tcl_GetString(objv[1]), &pFile, &dummy);
25619a1d0abeSdanielk1977   if( rc!=SQLITE_OK ){
25629a1d0abeSdanielk1977     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
25639a1d0abeSdanielk1977     return TCL_ERROR;
25649a1d0abeSdanielk1977   }
25659a1d0abeSdanielk1977   makePointerStr(interp, zBuf, pFile);
25669a1d0abeSdanielk1977   Tcl_SetResult(interp, zBuf, 0);
25679a1d0abeSdanielk1977   return TCL_ERROR;
25689a1d0abeSdanielk1977 }
25699a1d0abeSdanielk1977 
25709a1d0abeSdanielk1977 /*
25719a1d0abeSdanielk1977 ** Usage:  sqlite3OsClose <file handle>
25729a1d0abeSdanielk1977 */
25739a1d0abeSdanielk1977 static int test_sqlite3OsClose(
25749a1d0abeSdanielk1977   void * clientData,
25759a1d0abeSdanielk1977   Tcl_Interp *interp,
25769a1d0abeSdanielk1977   int objc,
25779a1d0abeSdanielk1977   Tcl_Obj *CONST objv[]
25789a1d0abeSdanielk1977 ){
25799a1d0abeSdanielk1977   OsFile *pFile;
25809a1d0abeSdanielk1977   int rc;
25819a1d0abeSdanielk1977 
25829a1d0abeSdanielk1977   if( objc!=2 ){
25839a1d0abeSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
25849a1d0abeSdanielk1977        Tcl_GetString(objv[0]), " filehandle", 0);
25859a1d0abeSdanielk1977     return TCL_ERROR;
25869a1d0abeSdanielk1977   }
25879a1d0abeSdanielk1977 
25889a1d0abeSdanielk1977   if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
25899a1d0abeSdanielk1977     return TCL_ERROR;
25909a1d0abeSdanielk1977   }
2591054889ecSdrh   rc = sqlite3OsClose(&pFile);
25929a1d0abeSdanielk1977   if( rc!=SQLITE_OK ){
25939a1d0abeSdanielk1977     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
25949a1d0abeSdanielk1977     return TCL_ERROR;
25959a1d0abeSdanielk1977   }
25969a1d0abeSdanielk1977   return TCL_OK;
25979a1d0abeSdanielk1977 }
25989a1d0abeSdanielk1977 
25999a1d0abeSdanielk1977 /*
26009a1d0abeSdanielk1977 ** Usage:  sqlite3OsLock <file handle> <locktype>
26019a1d0abeSdanielk1977 */
26029a1d0abeSdanielk1977 static int test_sqlite3OsLock(
26039a1d0abeSdanielk1977   void * clientData,
26049a1d0abeSdanielk1977   Tcl_Interp *interp,
26059a1d0abeSdanielk1977   int objc,
26069a1d0abeSdanielk1977   Tcl_Obj *CONST objv[]
26079a1d0abeSdanielk1977 ){
26089a1d0abeSdanielk1977   OsFile * pFile;
26099a1d0abeSdanielk1977   int rc;
26109a1d0abeSdanielk1977 
26119a1d0abeSdanielk1977   if( objc!=3 ){
26129a1d0abeSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
26139a1d0abeSdanielk1977         Tcl_GetString(objv[0]),
26149a1d0abeSdanielk1977         " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
26159a1d0abeSdanielk1977     return TCL_ERROR;
26169a1d0abeSdanielk1977   }
26179a1d0abeSdanielk1977 
26189a1d0abeSdanielk1977   if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
26199a1d0abeSdanielk1977     return TCL_ERROR;
26209a1d0abeSdanielk1977   }
26219a1d0abeSdanielk1977 
26229a1d0abeSdanielk1977   if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){
2623054889ecSdrh     rc = sqlite3OsLock(pFile, SHARED_LOCK);
26249a1d0abeSdanielk1977   }
26259a1d0abeSdanielk1977   else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){
2626054889ecSdrh     rc = sqlite3OsLock(pFile, RESERVED_LOCK);
26279a1d0abeSdanielk1977   }
26289a1d0abeSdanielk1977   else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){
2629054889ecSdrh     rc = sqlite3OsLock(pFile, PENDING_LOCK);
26309a1d0abeSdanielk1977   }
26319a1d0abeSdanielk1977   else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){
2632054889ecSdrh     rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK);
26339a1d0abeSdanielk1977   }else{
26349a1d0abeSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
26359a1d0abeSdanielk1977         Tcl_GetString(objv[0]),
26369a1d0abeSdanielk1977         " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
26379a1d0abeSdanielk1977     return TCL_ERROR;
26389a1d0abeSdanielk1977   }
26399a1d0abeSdanielk1977 
26409a1d0abeSdanielk1977   if( rc!=SQLITE_OK ){
26419a1d0abeSdanielk1977     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
26429a1d0abeSdanielk1977     return TCL_ERROR;
26439a1d0abeSdanielk1977   }
26449a1d0abeSdanielk1977   return TCL_OK;
26459a1d0abeSdanielk1977 }
26469a1d0abeSdanielk1977 
26479a1d0abeSdanielk1977 /*
26489a1d0abeSdanielk1977 ** Usage:  sqlite3OsUnlock <file handle>
26499a1d0abeSdanielk1977 */
26509a1d0abeSdanielk1977 static int test_sqlite3OsUnlock(
26519a1d0abeSdanielk1977   void * clientData,
26529a1d0abeSdanielk1977   Tcl_Interp *interp,
26539a1d0abeSdanielk1977   int objc,
26549a1d0abeSdanielk1977   Tcl_Obj *CONST objv[]
26559a1d0abeSdanielk1977 ){
26569a1d0abeSdanielk1977   OsFile * pFile;
26579a1d0abeSdanielk1977   int rc;
26589a1d0abeSdanielk1977 
26599a1d0abeSdanielk1977   if( objc!=2 ){
26609a1d0abeSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
26619a1d0abeSdanielk1977        Tcl_GetString(objv[0]), " filehandle", 0);
26629a1d0abeSdanielk1977     return TCL_ERROR;
26639a1d0abeSdanielk1977   }
26649a1d0abeSdanielk1977 
26659a1d0abeSdanielk1977   if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
26669a1d0abeSdanielk1977     return TCL_ERROR;
26679a1d0abeSdanielk1977   }
2668054889ecSdrh   rc = sqlite3OsUnlock(pFile, NO_LOCK);
26699a1d0abeSdanielk1977   if( rc!=SQLITE_OK ){
26709a1d0abeSdanielk1977     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
26719a1d0abeSdanielk1977     return TCL_ERROR;
26729a1d0abeSdanielk1977   }
26739a1d0abeSdanielk1977   return TCL_OK;
26749a1d0abeSdanielk1977 }
2675d3d39e93Sdrh 
2676ab3f9feaSdrh /*
2677ab3f9feaSdrh ** Usage:  sqlite3OsTempFileName
2678ab3f9feaSdrh */
2679ab3f9feaSdrh static int test_sqlite3OsTempFileName(
2680ab3f9feaSdrh   void * clientData,
2681ab3f9feaSdrh   Tcl_Interp *interp,
2682ab3f9feaSdrh   int objc,
2683ab3f9feaSdrh   Tcl_Obj *CONST objv[]
2684ab3f9feaSdrh ){
2685ab3f9feaSdrh   char zFile[SQLITE_TEMPNAME_SIZE];
2686ab3f9feaSdrh   int rc;
2687ab3f9feaSdrh 
2688054889ecSdrh   rc = sqlite3Os.xTempFileName(zFile);
2689ab3f9feaSdrh   if( rc!=SQLITE_OK ){
2690ab3f9feaSdrh     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2691ab3f9feaSdrh     return TCL_ERROR;
2692ab3f9feaSdrh   }
2693ab3f9feaSdrh   Tcl_AppendResult(interp, zFile, 0);
2694ab3f9feaSdrh   return TCL_OK;
2695ab3f9feaSdrh }
269644ee5bf7Sdanielk1977 #endif
2697d8123366Sdanielk1977 
26986622cce3Sdanielk1977 /*
2699cacb208eSdrh ** Usage:  sqlite_set_magic  DB  MAGIC-NUMBER
2700cacb208eSdrh **
2701cacb208eSdrh ** Set the db->magic value.  This is used to test error recovery logic.
2702cacb208eSdrh */
2703cacb208eSdrh static int sqlite_set_magic(
2704cacb208eSdrh   void * clientData,
2705cacb208eSdrh   Tcl_Interp *interp,
2706cacb208eSdrh   int argc,
2707cacb208eSdrh   char **argv
2708cacb208eSdrh ){
2709cacb208eSdrh   sqlite3 *db;
2710cacb208eSdrh   if( argc!=3 ){
2711cacb208eSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2712cacb208eSdrh          " DB MAGIC", 0);
2713cacb208eSdrh     return TCL_ERROR;
2714cacb208eSdrh   }
2715cacb208eSdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2716cacb208eSdrh   if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
2717cacb208eSdrh     db->magic = SQLITE_MAGIC_OPEN;
2718cacb208eSdrh   }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
2719cacb208eSdrh     db->magic = SQLITE_MAGIC_CLOSED;
2720cacb208eSdrh   }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
2721cacb208eSdrh     db->magic = SQLITE_MAGIC_BUSY;
2722cacb208eSdrh   }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
2723cacb208eSdrh     db->magic = SQLITE_MAGIC_ERROR;
2724cacb208eSdrh   }else if( Tcl_GetInt(interp, argv[2], &db->magic) ){
2725cacb208eSdrh     return TCL_ERROR;
2726cacb208eSdrh   }
2727cacb208eSdrh   return TCL_OK;
2728cacb208eSdrh }
2729cacb208eSdrh 
2730cacb208eSdrh /*
2731c5cdca61Sdrh ** Usage:  sqlite3_interrupt  DB
2732c5cdca61Sdrh **
2733c5cdca61Sdrh ** Trigger an interrupt on DB
2734c5cdca61Sdrh */
2735c5cdca61Sdrh static int test_interrupt(
2736c5cdca61Sdrh   void * clientData,
2737c5cdca61Sdrh   Tcl_Interp *interp,
2738c5cdca61Sdrh   int argc,
2739c5cdca61Sdrh   char **argv
2740c5cdca61Sdrh ){
2741c5cdca61Sdrh   sqlite3 *db;
2742c5cdca61Sdrh   if( argc!=2 ){
2743c5cdca61Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
2744c5cdca61Sdrh     return TCL_ERROR;
2745c5cdca61Sdrh   }
2746c5cdca61Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2747c5cdca61Sdrh   sqlite3_interrupt(db);
2748c5cdca61Sdrh   return TCL_OK;
2749c5cdca61Sdrh }
2750c5cdca61Sdrh 
275179158e18Sdrh static u8 *sqlite3_stack_baseline = 0;
275279158e18Sdrh 
2753c5cdca61Sdrh /*
275479158e18Sdrh ** Fill the stack with a known bitpattern.
2755600dd0baSdanielk1977 */
275679158e18Sdrh static void prepStack(void){
275779158e18Sdrh   int i;
275879158e18Sdrh   u32 bigBuf[65536];
275979158e18Sdrh   for(i=0; i<sizeof(bigBuf); i++) bigBuf[i] = 0xdeadbeef;
276079158e18Sdrh   sqlite3_stack_baseline = (u8*)&bigBuf[65536];
276179158e18Sdrh }
276279158e18Sdrh 
276379158e18Sdrh /*
276479158e18Sdrh ** Get the current stack depth.  Used for debugging only.
276579158e18Sdrh */
276679158e18Sdrh u64 sqlite3StackDepth(void){
276779158e18Sdrh   u8 x;
276879158e18Sdrh   return (u64)(sqlite3_stack_baseline - &x);
276979158e18Sdrh }
277079158e18Sdrh 
277179158e18Sdrh /*
277279158e18Sdrh ** Usage:  sqlite3_stack_used DB SQL
277379158e18Sdrh **
277479158e18Sdrh ** Try to measure the amount of stack space used by a call to sqlite3_exec
277579158e18Sdrh */
277679158e18Sdrh static int test_stack_used(
2777600dd0baSdanielk1977   void * clientData,
2778600dd0baSdanielk1977   Tcl_Interp *interp,
2779600dd0baSdanielk1977   int argc,
2780600dd0baSdanielk1977   char **argv
2781600dd0baSdanielk1977 ){
2782600dd0baSdanielk1977   sqlite3 *db;
278379158e18Sdrh   int i;
278479158e18Sdrh   if( argc!=3 ){
278579158e18Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
278679158e18Sdrh         " DB SQL", 0);
2787600dd0baSdanielk1977     return TCL_ERROR;
2788600dd0baSdanielk1977   }
278979158e18Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
279079158e18Sdrh   prepStack();
279179158e18Sdrh   sqlite3_exec(db, argv[2], 0, 0, 0);
279279158e18Sdrh   for(i=65535; i>=0 && ((u32*)sqlite3_stack_baseline)[-i]==0xdeadbeef; i--){}
279379158e18Sdrh   Tcl_SetObjResult(interp, Tcl_NewIntObj(i*4));
2794600dd0baSdanielk1977   return TCL_OK;
2795600dd0baSdanielk1977 }
2796600dd0baSdanielk1977 
2797600dd0baSdanielk1977 /*
27989636c4e1Sdanielk1977 ** Usage: sqlite_delete_function DB function-name
27999636c4e1Sdanielk1977 **
28009636c4e1Sdanielk1977 ** Delete the user function 'function-name' from database handle DB. It
28019636c4e1Sdanielk1977 ** is assumed that the user function was created as UTF8, any number of
28029636c4e1Sdanielk1977 ** arguments (the way the TCL interface does it).
28039636c4e1Sdanielk1977 */
28049636c4e1Sdanielk1977 static int delete_function(
28059636c4e1Sdanielk1977   void * clientData,
28069636c4e1Sdanielk1977   Tcl_Interp *interp,
28079636c4e1Sdanielk1977   int argc,
28089636c4e1Sdanielk1977   char **argv
28099636c4e1Sdanielk1977 ){
28109636c4e1Sdanielk1977   int rc;
28119636c4e1Sdanielk1977   sqlite3 *db;
28129636c4e1Sdanielk1977   if( argc!=3 ){
28139636c4e1Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
28149636c4e1Sdanielk1977         " DB function-name", 0);
28159636c4e1Sdanielk1977     return TCL_ERROR;
28169636c4e1Sdanielk1977   }
28179636c4e1Sdanielk1977   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
28189636c4e1Sdanielk1977   rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
28199636c4e1Sdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
28209636c4e1Sdanielk1977   return TCL_OK;
28219636c4e1Sdanielk1977 }
28229636c4e1Sdanielk1977 
28239636c4e1Sdanielk1977 /*
28249636c4e1Sdanielk1977 ** Usage: sqlite_delete_collation DB collation-name
28259636c4e1Sdanielk1977 **
28269636c4e1Sdanielk1977 ** Delete the collation sequence 'collation-name' from database handle
28279636c4e1Sdanielk1977 ** DB. It is assumed that the collation sequence was created as UTF8 (the
28289636c4e1Sdanielk1977 ** way the TCL interface does it).
28299636c4e1Sdanielk1977 */
28309636c4e1Sdanielk1977 static int delete_collation(
28319636c4e1Sdanielk1977   void * clientData,
28329636c4e1Sdanielk1977   Tcl_Interp *interp,
28339636c4e1Sdanielk1977   int argc,
28349636c4e1Sdanielk1977   char **argv
28359636c4e1Sdanielk1977 ){
28369636c4e1Sdanielk1977   int rc;
28379636c4e1Sdanielk1977   sqlite3 *db;
28389636c4e1Sdanielk1977   if( argc!=3 ){
28399636c4e1Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
28409636c4e1Sdanielk1977         " DB function-name", 0);
28419636c4e1Sdanielk1977     return TCL_ERROR;
28429636c4e1Sdanielk1977   }
28439636c4e1Sdanielk1977   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
28449636c4e1Sdanielk1977   rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
28459636c4e1Sdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
28469636c4e1Sdanielk1977   return TCL_OK;
28479636c4e1Sdanielk1977 }
28489636c4e1Sdanielk1977 
28499636c4e1Sdanielk1977 /*
28503e1d8e63Sdrh ** Usage: sqlite3_get_autocommit DB
28513e1d8e63Sdrh **
28523e1d8e63Sdrh ** Return true if the database DB is currently in auto-commit mode.
28533e1d8e63Sdrh ** Return false if not.
28543e1d8e63Sdrh */
28553e1d8e63Sdrh static int get_autocommit(
28563e1d8e63Sdrh   void * clientData,
28573e1d8e63Sdrh   Tcl_Interp *interp,
28583e1d8e63Sdrh   int argc,
28593e1d8e63Sdrh   char **argv
28603e1d8e63Sdrh ){
28613e1d8e63Sdrh   char zBuf[30];
28623e1d8e63Sdrh   sqlite3 *db;
28633e1d8e63Sdrh   if( argc!=2 ){
28643e1d8e63Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
28653e1d8e63Sdrh         " DB", 0);
28663e1d8e63Sdrh     return TCL_ERROR;
28673e1d8e63Sdrh   }
28683e1d8e63Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
28693e1d8e63Sdrh   sprintf(zBuf, "%d", sqlite3_get_autocommit(db));
28703e1d8e63Sdrh   Tcl_AppendResult(interp, zBuf, 0);
28713e1d8e63Sdrh   return TCL_OK;
28723e1d8e63Sdrh }
28733e1d8e63Sdrh 
28743e1d8e63Sdrh /*
287592febd92Sdrh ** Usage:  tcl_variable_type VARIABLENAME
287692febd92Sdrh **
287792febd92Sdrh ** Return the name of the internal representation for the
287892febd92Sdrh ** value of the given variable.
287992febd92Sdrh */
288092febd92Sdrh static int tcl_variable_type(
288192febd92Sdrh   void * clientData,
288292febd92Sdrh   Tcl_Interp *interp,
288392febd92Sdrh   int objc,
288492febd92Sdrh   Tcl_Obj *CONST objv[]
288592febd92Sdrh ){
288692febd92Sdrh   Tcl_Obj *pVar;
288792febd92Sdrh   if( objc!=2 ){
288892febd92Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
288992febd92Sdrh     return TCL_ERROR;
289092febd92Sdrh   }
289192febd92Sdrh   pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
289292febd92Sdrh   if( pVar==0 ) return TCL_ERROR;
289392febd92Sdrh   if( pVar->typePtr ){
289492febd92Sdrh     Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
289592febd92Sdrh   }
289692febd92Sdrh   return TCL_OK;
289792febd92Sdrh }
289892febd92Sdrh 
289992febd92Sdrh /*
290027d258a3Sdrh ** This routine sets entries in the global ::sqlite_options() array variable
290127d258a3Sdrh ** according to the compile-time configuration of the database.  Test
290227d258a3Sdrh ** procedures use this to determine when tests should be omitted.
290327d258a3Sdrh */
290427d258a3Sdrh static void set_options(Tcl_Interp *interp){
290575f86a4bSdrh #ifdef SQLITE_32BIT_ROWID
290675f86a4bSdrh   Tcl_SetVar2(interp, "sqlite_options", "rowid32", "1", TCL_GLOBAL_ONLY);
290775f86a4bSdrh #else
290875f86a4bSdrh   Tcl_SetVar2(interp, "sqlite_options", "rowid32", "0", TCL_GLOBAL_ONLY);
290975f86a4bSdrh #endif
291075f86a4bSdrh 
29119f18e8a0Sdrh #ifdef SQLITE_CASE_SENSITIVE_LIKE
29129f18e8a0Sdrh   Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","1",TCL_GLOBAL_ONLY);
29139f18e8a0Sdrh #else
29149f18e8a0Sdrh   Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY);
29159f18e8a0Sdrh #endif
29169f18e8a0Sdrh 
2917d7c03f74Sdanielk1977 #ifdef SQLITE_DISABLE_DIRSYNC
2918d7c03f74Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "dirsync", "0", TCL_GLOBAL_ONLY);
2919d7c03f74Sdanielk1977 #else
2920d7c03f74Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "dirsync", "1", TCL_GLOBAL_ONLY);
2921d7c03f74Sdanielk1977 #endif
2922d7c03f74Sdanielk1977 
292326c5d79fSdanielk1977 #ifdef SQLITE_DISABLE_LFS
292426c5d79fSdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "lfs", "0", TCL_GLOBAL_ONLY);
292526c5d79fSdanielk1977 #else
292626c5d79fSdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "lfs", "1", TCL_GLOBAL_ONLY);
292726c5d79fSdanielk1977 #endif
292826c5d79fSdanielk1977 
29291c8c23ccSdanielk1977 #ifdef SQLITE_OMIT_ALTERTABLE
29301c8c23ccSdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "altertable", "0", TCL_GLOBAL_ONLY);
29311c8c23ccSdanielk1977 #else
29321c8c23ccSdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "altertable", "1", TCL_GLOBAL_ONLY);
29331c8c23ccSdanielk1977 #endif
293413d7042aSdrh 
29359f18e8a0Sdrh #ifdef SQLITE_OMIT_ANALYZE
29369f18e8a0Sdrh   Tcl_SetVar2(interp, "sqlite_options", "analyze", "0", TCL_GLOBAL_ONLY);
29379f18e8a0Sdrh #else
29389f18e8a0Sdrh   Tcl_SetVar2(interp, "sqlite_options", "analyze", "1", TCL_GLOBAL_ONLY);
29399f18e8a0Sdrh #endif
29409f18e8a0Sdrh 
294113d7042aSdrh #ifdef SQLITE_OMIT_AUTHORIZATION
294213d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "auth", "0", TCL_GLOBAL_ONLY);
294313d7042aSdrh #else
294413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "auth", "1", TCL_GLOBAL_ONLY);
294513d7042aSdrh #endif
294613d7042aSdrh 
2947f3388144Sdrh #ifdef SQLITE_OMIT_AUTOINCREMENT
2948f3388144Sdrh   Tcl_SetVar2(interp, "sqlite_options", "autoinc", "0", TCL_GLOBAL_ONLY);
2949f3388144Sdrh #else
2950f3388144Sdrh   Tcl_SetVar2(interp, "sqlite_options", "autoinc", "1", TCL_GLOBAL_ONLY);
2951f3388144Sdrh #endif
2952f3388144Sdrh 
295345901d62Sdanielk1977 #ifdef SQLITE_OMIT_AUTOVACUUM
295445901d62Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "0", TCL_GLOBAL_ONLY);
295545901d62Sdanielk1977 #else
295645901d62Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "1", TCL_GLOBAL_ONLY);
2957f3388144Sdrh #endif /* SQLITE_OMIT_AUTOVACUUM */
29584d36b81eSdanielk1977 #if !defined(SQLITE_DEFAULT_AUTOVACUUM) || SQLITE_DEFAULT_AUTOVACUUM==0
295945901d62Sdanielk1977   Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","0",TCL_GLOBAL_ONLY);
296045901d62Sdanielk1977 #else
296145901d62Sdanielk1977   Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","1",TCL_GLOBAL_ONLY);
296245901d62Sdanielk1977 #endif
296313d7042aSdrh 
296455ef4d97Sdrh #ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
296555ef4d97Sdrh   Tcl_SetVar2(interp, "sqlite_options", "between_opt", "0", TCL_GLOBAL_ONLY);
296655ef4d97Sdrh #else
296755ef4d97Sdrh   Tcl_SetVar2(interp, "sqlite_options", "between_opt", "1", TCL_GLOBAL_ONLY);
296855ef4d97Sdrh #endif
296955ef4d97Sdrh 
297013d7042aSdrh #ifdef SQLITE_OMIT_BLOB_LITERAL
297113d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "bloblit", "0", TCL_GLOBAL_ONLY);
297213d7042aSdrh #else
297313d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY);
297413d7042aSdrh #endif
297513d7042aSdrh 
2976487e262fSdrh #ifdef SQLITE_OMIT_CAST
2977487e262fSdrh   Tcl_SetVar2(interp, "sqlite_options", "cast", "0", TCL_GLOBAL_ONLY);
2978487e262fSdrh #else
2979487e262fSdrh   Tcl_SetVar2(interp, "sqlite_options", "cast", "1", TCL_GLOBAL_ONLY);
2980487e262fSdrh #endif
2981487e262fSdrh 
2982ffe07b2dSdrh #ifdef SQLITE_OMIT_CHECK
2983ffe07b2dSdrh   Tcl_SetVar2(interp, "sqlite_options", "check", "0", TCL_GLOBAL_ONLY);
2984ffe07b2dSdrh #else
2985ffe07b2dSdrh   Tcl_SetVar2(interp, "sqlite_options", "check", "1", TCL_GLOBAL_ONLY);
2986ffe07b2dSdrh #endif
2987ffe07b2dSdrh 
2988ccae6026Sdrh #ifdef SQLITE_OMIT_COMPLETE
2989ccae6026Sdrh   Tcl_SetVar2(interp, "sqlite_options", "complete", "0", TCL_GLOBAL_ONLY);
2990ccae6026Sdrh #else
2991ccae6026Sdrh   Tcl_SetVar2(interp, "sqlite_options", "complete", "1", TCL_GLOBAL_ONLY);
2992ccae6026Sdrh #endif
2993ccae6026Sdrh 
299413d7042aSdrh #ifdef SQLITE_OMIT_COMPOUND_SELECT
299513d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "compound", "0", TCL_GLOBAL_ONLY);
299613d7042aSdrh #else
299713d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "compound", "1", TCL_GLOBAL_ONLY);
299813d7042aSdrh #endif
299913d7042aSdrh 
300013d7042aSdrh #ifdef SQLITE_OMIT_CONFLICT_CLAUSE
300113d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "conflict", "0", TCL_GLOBAL_ONLY);
300213d7042aSdrh #else
300313d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY);
300413d7042aSdrh #endif
300513d7042aSdrh 
300613d7042aSdrh #ifdef SQLITE_OMIT_DATETIME_FUNCS
300713d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY);
300813d7042aSdrh #else
300913d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY);
301013d7042aSdrh #endif
301113d7042aSdrh 
30122e66f0b9Sdrh #ifdef SQLITE_OMIT_DISKIO
30132e66f0b9Sdrh   Tcl_SetVar2(interp, "sqlite_options", "diskio", "0", TCL_GLOBAL_ONLY);
30142e66f0b9Sdrh #else
30152e66f0b9Sdrh   Tcl_SetVar2(interp, "sqlite_options", "diskio", "1", TCL_GLOBAL_ONLY);
30162e66f0b9Sdrh #endif
30172e66f0b9Sdrh 
301813d7042aSdrh #ifdef SQLITE_OMIT_EXPLAIN
301913d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "explain", "0", TCL_GLOBAL_ONLY);
302013d7042aSdrh #else
302113d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "explain", "1", TCL_GLOBAL_ONLY);
302213d7042aSdrh #endif
302313d7042aSdrh 
302413d7042aSdrh #ifdef SQLITE_OMIT_FLOATING_POINT
302513d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "0", TCL_GLOBAL_ONLY);
302613d7042aSdrh #else
302713d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "1", TCL_GLOBAL_ONLY);
302813d7042aSdrh #endif
302913d7042aSdrh 
303013d7042aSdrh #ifdef SQLITE_OMIT_FOREIGN_KEY
303113d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "0", TCL_GLOBAL_ONLY);
303213d7042aSdrh #else
303313d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "1", TCL_GLOBAL_ONLY);
303413d7042aSdrh #endif
303513d7042aSdrh 
30366b456a2bSdanielk1977 #ifdef SQLITE_OMIT_GLOBALRECOVER
30376b456a2bSdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "globalrecover", "0", TCL_GLOBAL_ONLY);
30386b456a2bSdanielk1977 #else
30396b456a2bSdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "globalrecover", "1", TCL_GLOBAL_ONLY);
30406b456a2bSdanielk1977 #endif
30416b456a2bSdanielk1977 
304213d7042aSdrh #ifdef SQLITE_OMIT_INTEGRITY_CHECK
304313d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
304413d7042aSdrh #else
304513d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "integrityck", "1", TCL_GLOBAL_ONLY);
304613d7042aSdrh #endif
304713d7042aSdrh 
304855ef4d97Sdrh #ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
304955ef4d97Sdrh   Tcl_SetVar2(interp, "sqlite_options", "like_opt", "0", TCL_GLOBAL_ONLY);
305055ef4d97Sdrh #else
305155ef4d97Sdrh   Tcl_SetVar2(interp, "sqlite_options", "like_opt", "1", TCL_GLOBAL_ONLY);
305255ef4d97Sdrh #endif
305355ef4d97Sdrh 
305413d7042aSdrh #ifdef SQLITE_OMIT_MEMORYDB
305513d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY);
305613d7042aSdrh #else
305713d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "memorydb", "1", TCL_GLOBAL_ONLY);
305813d7042aSdrh #endif
305913d7042aSdrh 
306055ef4d97Sdrh #ifdef SQLITE_OMIT_OR_OPTIMIZATION
306155ef4d97Sdrh   Tcl_SetVar2(interp, "sqlite_options", "or_opt", "0", TCL_GLOBAL_ONLY);
306255ef4d97Sdrh #else
306355ef4d97Sdrh   Tcl_SetVar2(interp, "sqlite_options", "or_opt", "1", TCL_GLOBAL_ONLY);
306455ef4d97Sdrh #endif
306555ef4d97Sdrh 
306613d7042aSdrh #ifdef SQLITE_OMIT_PAGER_PRAGMAS
306713d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY);
306813d7042aSdrh #else
306913d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "1", TCL_GLOBAL_ONLY);
307013d7042aSdrh #endif
307113d7042aSdrh 
30722e66f0b9Sdrh #ifdef SQLITE_OMIT_PARSER
30732e66f0b9Sdrh   Tcl_SetVar2(interp, "sqlite_options", "parser", "0", TCL_GLOBAL_ONLY);
30742e66f0b9Sdrh #else
30752e66f0b9Sdrh   Tcl_SetVar2(interp, "sqlite_options", "parser", "1", TCL_GLOBAL_ONLY);
30762e66f0b9Sdrh #endif
30772e66f0b9Sdrh 
3078bf21627bSdrh #if defined(SQLITE_OMIT_PRAGMA) || defined(SQLITE_OMIT_FLAG_PRAGMAS)
307913d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "pragma", "0", TCL_GLOBAL_ONLY);
308013d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
308113d7042aSdrh #else
308213d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "pragma", "1", TCL_GLOBAL_ONLY);
308313d7042aSdrh #endif
308413d7042aSdrh 
308513d7042aSdrh #ifdef SQLITE_OMIT_PROGRESS_CALLBACK
308613d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "progress", "0", TCL_GLOBAL_ONLY);
308713d7042aSdrh #else
308813d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY);
308913d7042aSdrh #endif
309013d7042aSdrh 
309113d7042aSdrh #ifdef SQLITE_OMIT_REINDEX
309213d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "reindex", "0", TCL_GLOBAL_ONLY);
309313d7042aSdrh #else
309413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "reindex", "1", TCL_GLOBAL_ONLY);
309513d7042aSdrh #endif
309613d7042aSdrh 
309713d7042aSdrh #ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
309813d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "0", TCL_GLOBAL_ONLY);
309913d7042aSdrh #else
310013d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "1", TCL_GLOBAL_ONLY);
310113d7042aSdrh #endif
310213d7042aSdrh 
310313d7042aSdrh #ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
310413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "schema_version", "0", TCL_GLOBAL_ONLY);
310513d7042aSdrh #else
310613d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY);
310713d7042aSdrh #endif
310813d7042aSdrh 
3109*aef0bf64Sdanielk1977 #ifdef SQLITE_OMIT_SHARED_CACHE
3110*aef0bf64Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "0", TCL_GLOBAL_ONLY);
3111*aef0bf64Sdanielk1977 #else
3112*aef0bf64Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "1", TCL_GLOBAL_ONLY);
3113*aef0bf64Sdanielk1977 #endif
3114*aef0bf64Sdanielk1977 
31153e8c37e7Sdanielk1977 #ifdef SQLITE_OMIT_SUBQUERY
31163e8c37e7Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "subquery", "0", TCL_GLOBAL_ONLY);
31173e8c37e7Sdanielk1977 #else
31183e8c37e7Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "subquery", "1", TCL_GLOBAL_ONLY);
31193e8c37e7Sdanielk1977 #endif
31203e8c37e7Sdanielk1977 
312113d7042aSdrh #ifdef SQLITE_OMIT_TCL_VARIABLE
312213d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY);
312313d7042aSdrh #else
312413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY);
312513d7042aSdrh #endif
312613d7042aSdrh 
312713d7042aSdrh #if defined(THREADSAFE) && THREADSAFE
312813d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY);
312913d7042aSdrh #else
313013d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "0", TCL_GLOBAL_ONLY);
313113d7042aSdrh #endif
313213d7042aSdrh 
313319e2d37fSdrh #ifdef SQLITE_OMIT_TRACE
313419e2d37fSdrh   Tcl_SetVar2(interp, "sqlite_options", "trace", "0", TCL_GLOBAL_ONLY);
313519e2d37fSdrh #else
313619e2d37fSdrh   Tcl_SetVar2(interp, "sqlite_options", "trace", "1", TCL_GLOBAL_ONLY);
313719e2d37fSdrh #endif
313819e2d37fSdrh 
313913d7042aSdrh #ifdef SQLITE_OMIT_TRIGGER
314013d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "trigger", "0", TCL_GLOBAL_ONLY);
314113d7042aSdrh #else
314213d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "trigger", "1", TCL_GLOBAL_ONLY);
314313d7042aSdrh #endif
314413d7042aSdrh 
314553c0f748Sdanielk1977 #ifdef SQLITE_OMIT_TEMPDB
314653c0f748Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "tempdb", "0", TCL_GLOBAL_ONLY);
314753c0f748Sdanielk1977 #else
314853c0f748Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "tempdb", "1", TCL_GLOBAL_ONLY);
314953c0f748Sdanielk1977 #endif
315053c0f748Sdanielk1977 
315113d7042aSdrh #ifdef SQLITE_OMIT_UTF16
315213d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY);
315313d7042aSdrh #else
315413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "utf16", "1", TCL_GLOBAL_ONLY);
315513d7042aSdrh #endif
315613d7042aSdrh 
315713d7042aSdrh #ifdef SQLITE_OMIT_VACUUM
315813d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "vacuum", "0", TCL_GLOBAL_ONLY);
315913d7042aSdrh #else
316013d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "vacuum", "1", TCL_GLOBAL_ONLY);
316113d7042aSdrh #endif
316213d7042aSdrh 
316313d7042aSdrh #ifdef SQLITE_OMIT_VIEW
316413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "view", "0", TCL_GLOBAL_ONLY);
316513d7042aSdrh #else
316613d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "view", "1", TCL_GLOBAL_ONLY);
316713d7042aSdrh #endif
316827d258a3Sdrh }
316927d258a3Sdrh 
317027d258a3Sdrh /*
3171d1bf3512Sdrh ** Register commands with the TCL interpreter.
3172d1bf3512Sdrh */
3173d1bf3512Sdrh int Sqlitetest1_Init(Tcl_Interp *interp){
31746f8a503dSdanielk1977   extern int sqlite3_search_count;
31756f8a503dSdanielk1977   extern int sqlite3_interrupt_count;
31766f8a503dSdanielk1977   extern int sqlite3_open_file_count;
31776bf89570Sdrh   extern int sqlite3_sort_count;
31786f8a503dSdanielk1977   extern int sqlite3_current_time;
3179c2eef3b3Sdrh   static struct {
3180c2eef3b3Sdrh      char *zName;
3181c2eef3b3Sdrh      Tcl_CmdProc *xProc;
3182c2eef3b3Sdrh   } aCmd[] = {
31836f8a503dSdanielk1977      { "sqlite3_mprintf_int",           (Tcl_CmdProc*)sqlite3_mprintf_int    },
3184e9707671Sdrh      { "sqlite3_mprintf_int64",         (Tcl_CmdProc*)sqlite3_mprintf_int64  },
31856f8a503dSdanielk1977      { "sqlite3_mprintf_str",           (Tcl_CmdProc*)sqlite3_mprintf_str    },
3186e29b1a05Sdrh      { "sqlite3_mprintf_stronly",       (Tcl_CmdProc*)sqlite3_mprintf_stronly},
31876f8a503dSdanielk1977      { "sqlite3_mprintf_double",        (Tcl_CmdProc*)sqlite3_mprintf_double },
31886f8a503dSdanielk1977      { "sqlite3_mprintf_scaled",        (Tcl_CmdProc*)sqlite3_mprintf_scaled },
318963782855Sdrh      { "sqlite3_mprintf_hexdouble",   (Tcl_CmdProc*)sqlite3_mprintf_hexdouble},
31906f8a503dSdanielk1977      { "sqlite3_mprintf_z_test",        (Tcl_CmdProc*)test_mprintf_z        },
31916f8a503dSdanielk1977      { "sqlite3_last_insert_rowid",     (Tcl_CmdProc*)test_last_rowid       },
31926f8a503dSdanielk1977      { "sqlite3_exec_printf",           (Tcl_CmdProc*)test_exec_printf      },
31936f8a503dSdanielk1977      { "sqlite3_get_table_printf",      (Tcl_CmdProc*)test_get_table_printf },
31946f8a503dSdanielk1977      { "sqlite3_close",                 (Tcl_CmdProc*)sqlite_test_close     },
31956f8a503dSdanielk1977      { "sqlite3_create_function",       (Tcl_CmdProc*)test_create_function  },
31966f8a503dSdanielk1977      { "sqlite3_create_aggregate",      (Tcl_CmdProc*)test_create_aggregate },
3197c2eef3b3Sdrh      { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func    },
3198c2eef3b3Sdrh      { "sqlite_abort",                  (Tcl_CmdProc*)sqlite_abort          },
31992c336549Sdanielk1977 #ifdef SQLITE_MEMDEBUG
3200c2eef3b3Sdrh      { "sqlite_malloc_fail",            (Tcl_CmdProc*)sqlite_malloc_fail    },
3201c2eef3b3Sdrh      { "sqlite_malloc_stat",            (Tcl_CmdProc*)sqlite_malloc_stat    },
3202c2eef3b3Sdrh #endif
320396fc5fe6Sdanielk1977      { "sqlite_bind",                   (Tcl_CmdProc*)test_bind             },
320499ee3600Sdrh      { "breakpoint",                    (Tcl_CmdProc*)test_breakpoint       },
320525d6543dSdrh      { "sqlite3_key",                   (Tcl_CmdProc*)test_key              },
320625d6543dSdrh      { "sqlite3_rekey",                 (Tcl_CmdProc*)test_rekey            },
3207cacb208eSdrh      { "sqlite_set_magic",              (Tcl_CmdProc*)sqlite_set_magic      },
3208c5cdca61Sdrh      { "sqlite3_interrupt",             (Tcl_CmdProc*)test_interrupt        },
3209600dd0baSdanielk1977 #if 0
3210600dd0baSdanielk1977      { "sqlite3_sleep",                 (Tcl_CmdProc*)test_sleep            },
3211600dd0baSdanielk1977 #endif
32129636c4e1Sdanielk1977      { "sqlite_delete_function",        (Tcl_CmdProc*)delete_function       },
32133e1d8e63Sdrh      { "sqlite_delete_collation",       (Tcl_CmdProc*)delete_collation      },
32143e1d8e63Sdrh      { "sqlite3_get_autocommit",        (Tcl_CmdProc*)get_autocommit        },
321579158e18Sdrh      { "sqlite3_stack_used",            (Tcl_CmdProc*)test_stack_used       },
3216c2eef3b3Sdrh   };
321751e3d8e2Sdanielk1977   static struct {
321851e3d8e2Sdanielk1977      char *zName;
321951e3d8e2Sdanielk1977      Tcl_ObjCmdProc *xProc;
322004f2e68dSdanielk1977      void *clientData;
322151e3d8e2Sdanielk1977   } aObjCmd[] = {
3222241db313Sdrh      { "sqlite3_bind_int",              test_bind_int,      0 },
322304f2e68dSdanielk1977      { "sqlite3_bind_int64",            test_bind_int64,    0 },
322404f2e68dSdanielk1977      { "sqlite3_bind_double",           test_bind_double,   0 },
322504f2e68dSdanielk1977      { "sqlite3_bind_null",             test_bind_null     ,0 },
322604f2e68dSdanielk1977      { "sqlite3_bind_text",             test_bind_text     ,0 },
322704f2e68dSdanielk1977      { "sqlite3_bind_text16",           test_bind_text16   ,0 },
322804f2e68dSdanielk1977      { "sqlite3_bind_blob",             test_bind_blob     ,0 },
322975f6a032Sdrh      { "sqlite3_bind_parameter_count",  test_bind_parameter_count, 0},
3230895d7472Sdrh      { "sqlite3_bind_parameter_name",   test_bind_parameter_name,  0},
3231fa6bc000Sdrh      { "sqlite3_bind_parameter_index",  test_bind_parameter_index, 0},
3232600dd0baSdanielk1977 #if 0
3233600dd0baSdanielk1977      { "sqlite3_clear_bindings",        test_clear_bindings, 0},
3234600dd0baSdanielk1977 #endif
323504f2e68dSdanielk1977      { "sqlite3_errcode",               test_errcode       ,0 },
323604f2e68dSdanielk1977      { "sqlite3_errmsg",                test_errmsg        ,0 },
323704f2e68dSdanielk1977      { "sqlite3_errmsg16",              test_errmsg16      ,0 },
323804f2e68dSdanielk1977      { "sqlite3_open",                  test_open          ,0 },
323904f2e68dSdanielk1977      { "sqlite3_open16",                test_open16        ,0 },
3240bc6ada41Sdanielk1977      { "sqlite3_complete16",            test_complete16    ,0 },
324104f2e68dSdanielk1977 
324204f2e68dSdanielk1977      { "sqlite3_prepare",               test_prepare       ,0 },
324304f2e68dSdanielk1977      { "sqlite3_prepare16",             test_prepare16     ,0 },
324404f2e68dSdanielk1977      { "sqlite3_finalize",              test_finalize      ,0 },
324504f2e68dSdanielk1977      { "sqlite3_reset",                 test_reset         ,0 },
3246d89bd007Sdrh      { "sqlite3_expired",               test_expired       ,0 },
3247f8db1bc0Sdrh      { "sqlite3_transfer_bindings",     test_transfer_bind ,0 },
3248fbcd585fSdanielk1977      { "sqlite3_changes",               test_changes       ,0 },
324904f2e68dSdanielk1977      { "sqlite3_step",                  test_step          ,0 },
325004f2e68dSdanielk1977 
325104f2e68dSdanielk1977      /* sqlite3_column_*() API */
325204f2e68dSdanielk1977      { "sqlite3_column_count",          test_column_count  ,0 },
325304f2e68dSdanielk1977      { "sqlite3_data_count",            test_data_count    ,0 },
325404f2e68dSdanielk1977      { "sqlite3_column_type",           test_column_type   ,0 },
3255ea61b2c4Sdanielk1977      { "sqlite3_column_blob",           test_column_blob   ,0 },
325604f2e68dSdanielk1977      { "sqlite3_column_double",         test_column_double ,0 },
325704f2e68dSdanielk1977      { "sqlite3_column_int64",          test_column_int64  ,0 },
325804f2e68dSdanielk1977      { "sqlite3_column_text",       test_stmt_utf8,  sqlite3_column_text      },
325904f2e68dSdanielk1977      { "sqlite3_column_decltype",   test_stmt_utf8,  sqlite3_column_decltype  },
326004f2e68dSdanielk1977      { "sqlite3_column_name",       test_stmt_utf8,  sqlite3_column_name      },
32616c62608fSdrh      { "sqlite3_column_int",        test_stmt_int,   sqlite3_column_int       },
32626c62608fSdrh      { "sqlite3_column_bytes",      test_stmt_int,   sqlite3_column_bytes     },
32636c62608fSdrh #ifndef SQLITE_OMIT_UTF16
32646c62608fSdrh      { "sqlite3_column_bytes16",    test_stmt_int,   sqlite3_column_bytes16   },
326504f2e68dSdanielk1977      { "sqlite3_column_text16",     test_stmt_utf16, sqlite3_column_text16    },
326604f2e68dSdanielk1977      { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16},
326704f2e68dSdanielk1977      { "sqlite3_column_name16",     test_stmt_utf16, sqlite3_column_name16    },
32686c62608fSdrh #endif
32696b456a2bSdanielk1977      { "sqlite3_global_recover",    test_global_recover, 0   },
327004f2e68dSdanielk1977 
32719a1d0abeSdanielk1977      /* Functions from os.h */
327244ee5bf7Sdanielk1977 #ifndef SQLITE_OMIT_DISKIO
32739a1d0abeSdanielk1977      { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
32749a1d0abeSdanielk1977      { "sqlite3OsClose",        test_sqlite3OsClose, 0 },
32759a1d0abeSdanielk1977      { "sqlite3OsLock",         test_sqlite3OsLock, 0 },
3276ab3f9feaSdrh      { "sqlite3OsTempFileName", test_sqlite3OsTempFileName, 0 },
3277312d6b36Sdanielk1977 
3278312d6b36Sdanielk1977      /* Custom test interfaces */
32799a1d0abeSdanielk1977      { "sqlite3OsUnlock",         test_sqlite3OsUnlock, 0    },
328044ee5bf7Sdanielk1977 #endif
32815436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
32824e6af134Sdanielk1977      { "add_test_collate",        test_collate, 0            },
3283312d6b36Sdanielk1977      { "add_test_collate_needed", test_collate_needed, 0     },
3284c8e9a2dfSdanielk1977      { "add_test_function",       test_function, 0           },
32855436dc2dSdrh #endif
32865591df55Sdanielk1977 #ifdef SQLITE_MEMDEBUG
32875591df55Sdanielk1977      { "sqlite_malloc_outstanding", sqlite_malloc_outstanding, 0},
32885591df55Sdanielk1977 #endif
3289312d6b36Sdanielk1977      { "sqlite3_test_errstr",     test_errstr, 0             },
329092febd92Sdrh      { "tcl_variable_type",       tcl_variable_type, 0       },
3291*aef0bf64Sdanielk1977 #ifndef SQLITE_OMIT_SHARED_CACHE
3292*aef0bf64Sdanielk1977      { "sqlite3_enable_shared_cache", test_enable_shared_cache, 0},
3293*aef0bf64Sdanielk1977 #endif
329451e3d8e2Sdanielk1977   };
32951398ad36Sdrh   static int bitmask_size = sizeof(Bitmask)*8;
3296c2eef3b3Sdrh   int i;
32972ac3ee97Sdrh   extern int sqlite3_os_trace;
329851147baaSdrh   extern int sqlite3_where_trace;
3299b851b2c9Sdrh   extern int sqlite3_sync_count, sqlite3_fullsync_count;
3300af6df11fSdrh   extern int sqlite3_opentemp_count;
330101397205Sdrh   extern int sqlite3_memUsed;
33022e588c75Sdanielk1977   extern int sqlite3_malloc_id;
330301397205Sdrh   extern int sqlite3_memMax;
330455ef4d97Sdrh   extern int sqlite3_like_count;
3305c0929987Sdrh #if OS_WIN
3306c0929987Sdrh   extern int sqlite3_os_type;
3307c0929987Sdrh #endif
33088b3d990bSdrh #ifdef SQLITE_DEBUG
33098b3d990bSdrh   extern int sqlite3_vdbe_addop_trace;
3310549c8b68Sdrh #endif
3311549c8b68Sdrh #ifdef SQLITE_TEST
3312549c8b68Sdrh   extern char sqlite3_query_plan[];
33139042f395Sdrh   static char *query_plan = sqlite3_query_plan;
331448083ceeSdrh #endif
3315c2eef3b3Sdrh 
3316c2eef3b3Sdrh   for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
3317c2eef3b3Sdrh     Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
3318c2eef3b3Sdrh   }
331951e3d8e2Sdanielk1977   for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
3320c572ef7fSdanielk1977     Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
3321c572ef7fSdanielk1977         aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
332251e3d8e2Sdanielk1977   }
33236490bebdSdanielk1977   Tcl_LinkVar(interp, "sqlite_search_count",
33246f8a503dSdanielk1977       (char*)&sqlite3_search_count, TCL_LINK_INT);
33256bf89570Sdrh   Tcl_LinkVar(interp, "sqlite_sort_count",
33266bf89570Sdrh       (char*)&sqlite3_sort_count, TCL_LINK_INT);
332755ef4d97Sdrh   Tcl_LinkVar(interp, "sqlite_like_count",
332855ef4d97Sdrh       (char*)&sqlite3_like_count, TCL_LINK_INT);
33296490bebdSdanielk1977   Tcl_LinkVar(interp, "sqlite_interrupt_count",
33306f8a503dSdanielk1977       (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
33316490bebdSdanielk1977   Tcl_LinkVar(interp, "sqlite_open_file_count",
33326f8a503dSdanielk1977       (char*)&sqlite3_open_file_count, TCL_LINK_INT);
33336490bebdSdanielk1977   Tcl_LinkVar(interp, "sqlite_current_time",
33346f8a503dSdanielk1977       (char*)&sqlite3_current_time, TCL_LINK_INT);
33352ac3ee97Sdrh   Tcl_LinkVar(interp, "sqlite_os_trace",
33362ac3ee97Sdrh       (char*)&sqlite3_os_trace, TCL_LINK_INT);
3337268803a9Sdrh #ifndef SQLITE_OMIT_UTF16
3338268803a9Sdrh   Tcl_LinkVar(interp, "sqlite_last_needed_collation",
3339268803a9Sdrh       (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
3340268803a9Sdrh #endif
334197cb2e96Sdanielk1977 #ifdef SQLITE_MEMDEBUG
33422e588c75Sdanielk1977   Tcl_LinkVar(interp, "sqlite_malloc_id",
33432e588c75Sdanielk1977       (char*)&sqlite3_malloc_id, TCL_LINK_STRING);
334497cb2e96Sdanielk1977 #endif
3345c0929987Sdrh #if OS_WIN
3346c0929987Sdrh   Tcl_LinkVar(interp, "sqlite_os_type",
3347c0929987Sdrh       (char*)&sqlite3_os_type, TCL_LINK_INT);
3348c0929987Sdrh #endif
3349549c8b68Sdrh #ifdef SQLITE_TEST
3350549c8b68Sdrh   Tcl_LinkVar(interp, "sqlite_query_plan",
3351549c8b68Sdrh       (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
3352549c8b68Sdrh #endif
33538b3d990bSdrh #ifdef SQLITE_DEBUG
33548b3d990bSdrh   Tcl_LinkVar(interp, "sqlite_addop_trace",
33558b3d990bSdrh       (char*)&sqlite3_vdbe_addop_trace, TCL_LINK_INT);
335648083ceeSdrh   Tcl_LinkVar(interp, "sqlite_where_trace",
335748083ceeSdrh       (char*)&sqlite3_where_trace, TCL_LINK_INT);
33588b3d990bSdrh #endif
33597018030dSdrh #ifdef SQLITE_MEMDEBUG
336001397205Sdrh   Tcl_LinkVar(interp, "sqlite_memused",
336101397205Sdrh       (char*)&sqlite3_memUsed, TCL_LINK_INT | TCL_LINK_READ_ONLY);
336201397205Sdrh   Tcl_LinkVar(interp, "sqlite_memmax",
336301397205Sdrh       (char*)&sqlite3_memMax, TCL_LINK_INT | TCL_LINK_READ_ONLY);
33647018030dSdrh #endif
3365cbe21be3Sdanielk1977 #ifndef SQLITE_OMIT_DISKIO
3366af6df11fSdrh   Tcl_LinkVar(interp, "sqlite_opentemp_count",
3367af6df11fSdrh       (char*)&sqlite3_opentemp_count, TCL_LINK_INT);
3368cbe21be3Sdanielk1977 #endif
33697c972decSdrh   Tcl_LinkVar(interp, "sqlite_static_bind_value",
33707c972decSdrh       (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
3371ab3f9feaSdrh   Tcl_LinkVar(interp, "sqlite_temp_directory",
3372effd02bcSdrh       (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
33731398ad36Sdrh   Tcl_LinkVar(interp, "bitmask_size",
33741398ad36Sdrh       (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
3375748f763fSdrh #if OS_UNIX
3376b851b2c9Sdrh   Tcl_LinkVar(interp, "sqlite_sync_count",
3377b851b2c9Sdrh       (char*)&sqlite3_sync_count, TCL_LINK_INT);
3378b851b2c9Sdrh   Tcl_LinkVar(interp, "sqlite_fullsync_count",
3379b851b2c9Sdrh       (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
3380748f763fSdrh #endif /* OS_UNIX */
338127d258a3Sdrh   set_options(interp);
3382d1bf3512Sdrh   return TCL_OK;
3383d1bf3512Sdrh }
3384