xref: /sqlite-3.40.0/src/test1.c (revision 3e8c37e7)
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*3e8c37e7Sdanielk1977 ** $Id: test1.c,v 1.125 2005/01/21 03:12:16 danielk1977 Exp $
17d1bf3512Sdrh */
18d1bf3512Sdrh #include "sqliteInt.h"
19d1bf3512Sdrh #include "tcl.h"
2094e92032Sdrh #include "os.h"
21d1bf3512Sdrh #include <stdlib.h>
22d1bf3512Sdrh #include <string.h>
23d1bf3512Sdrh 
246622cce3Sdanielk1977 static const char * errorName(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_INTERNAL:   zName = "SQLITE_INTERNAL";    break;
306622cce3Sdanielk1977     case SQLITE_PERM:       zName = "SQLITE_PERM";        break;
316622cce3Sdanielk1977     case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break;
326622cce3Sdanielk1977     case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break;
336622cce3Sdanielk1977     case SQLITE_LOCKED:     zName = "SQLITE_LOCKED";      break;
346622cce3Sdanielk1977     case SQLITE_NOMEM:      zName = "SQLITE_NOMEM";       break;
356622cce3Sdanielk1977     case SQLITE_READONLY:   zName = "SQLITE_READONLY";    break;
366622cce3Sdanielk1977     case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break;
376622cce3Sdanielk1977     case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break;
386622cce3Sdanielk1977     case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break;
396622cce3Sdanielk1977     case SQLITE_NOTFOUND:   zName = "SQLITE_NOTFOUND";    break;
406622cce3Sdanielk1977     case SQLITE_FULL:       zName = "SQLITE_FULL";        break;
416622cce3Sdanielk1977     case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break;
426622cce3Sdanielk1977     case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break;
436622cce3Sdanielk1977     case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break;
446622cce3Sdanielk1977     case SQLITE_SCHEMA:     zName = "SQLITE_SCHEMA";      break;
456622cce3Sdanielk1977     case SQLITE_TOOBIG:     zName = "SQLITE_TOOBIG";      break;
466622cce3Sdanielk1977     case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT";  break;
476622cce3Sdanielk1977     case SQLITE_MISMATCH:   zName = "SQLITE_MISMATCH";    break;
486622cce3Sdanielk1977     case SQLITE_MISUSE:     zName = "SQLITE_MISUSE";      break;
496622cce3Sdanielk1977     case SQLITE_NOLFS:      zName = "SQLITE_NOLFS";       break;
506622cce3Sdanielk1977     case SQLITE_AUTH:       zName = "SQLITE_AUTH";        break;
516622cce3Sdanielk1977     case SQLITE_FORMAT:     zName = "SQLITE_FORMAT";      break;
526622cce3Sdanielk1977     case SQLITE_RANGE:      zName = "SQLITE_RANGE";       break;
536622cce3Sdanielk1977     case SQLITE_ROW:        zName = "SQLITE_ROW";         break;
546622cce3Sdanielk1977     case SQLITE_DONE:       zName = "SQLITE_DONE";        break;
55312d6b36Sdanielk1977     case SQLITE_NOTADB:     zName = "SQLITE_NOTADB";      break;
566622cce3Sdanielk1977     default:                zName = "SQLITE_Unknown";     break;
576622cce3Sdanielk1977   }
586622cce3Sdanielk1977   return zName;
596622cce3Sdanielk1977 }
606622cce3Sdanielk1977 
61d1bf3512Sdrh /*
62c60d0446Sdrh ** Convert an sqlite3_stmt* into an sqlite3*.  This depends on the
63c60d0446Sdrh ** fact that the sqlite3* is the first field in the Vdbe structure.
64c60d0446Sdrh */
65c60d0446Sdrh #define StmtToDb(X)   (*(sqlite3**)(X))
66c60d0446Sdrh 
67c60d0446Sdrh /*
68c60d0446Sdrh ** Check a return value to make sure it agrees with the results
69c60d0446Sdrh ** from sqlite3_errcode.
70c60d0446Sdrh */
71c60d0446Sdrh int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
72c60d0446Sdrh   if( rc!=SQLITE_MISUSE && rc!=SQLITE_OK && sqlite3_errcode(db)!=rc ){
73c60d0446Sdrh     char zBuf[200];
74c60d0446Sdrh     int r2 = sqlite3_errcode(db);
75c60d0446Sdrh     sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)",
76c60d0446Sdrh        errorName(rc), rc, errorName(r2), r2);
77c60d0446Sdrh     Tcl_ResetResult(interp);
78c60d0446Sdrh     Tcl_AppendResult(interp, zBuf, 0);
79c60d0446Sdrh     return 1;
80c60d0446Sdrh   }
81c60d0446Sdrh   return 0;
82c60d0446Sdrh }
83c60d0446Sdrh 
84c60d0446Sdrh /*
859bb575fdSdrh ** Decode a pointer to an sqlite3 object.
86b86ccfb2Sdrh */
879bb575fdSdrh static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
88fe63d1c9Sdrh   *ppDb = (sqlite3*)sqlite3TextToPtr(zA);
89b86ccfb2Sdrh   return TCL_OK;
90b86ccfb2Sdrh }
91b86ccfb2Sdrh 
92b86ccfb2Sdrh /*
9351e3d8e2Sdanielk1977 ** Decode a pointer to an sqlite3_stmt object.
9451e3d8e2Sdanielk1977 */
9551e3d8e2Sdanielk1977 static int getStmtPointer(
9651e3d8e2Sdanielk1977   Tcl_Interp *interp,
9751e3d8e2Sdanielk1977   const char *zArg,
9851e3d8e2Sdanielk1977   sqlite3_stmt **ppStmt
9951e3d8e2Sdanielk1977 ){
100fe63d1c9Sdrh   *ppStmt = (sqlite3_stmt*)sqlite3TextToPtr(zArg);
10151e3d8e2Sdanielk1977   return TCL_OK;
10251e3d8e2Sdanielk1977 }
10351e3d8e2Sdanielk1977 
10451e3d8e2Sdanielk1977 /*
1059a1d0abeSdanielk1977 ** Decode a pointer to an sqlite3_stmt object.
1069a1d0abeSdanielk1977 */
1079a1d0abeSdanielk1977 static int getFilePointer(
1089a1d0abeSdanielk1977   Tcl_Interp *interp,
1099a1d0abeSdanielk1977   const char *zArg,
1109a1d0abeSdanielk1977   OsFile **ppFile
1119a1d0abeSdanielk1977 ){
112fe63d1c9Sdrh   *ppFile = (OsFile*)sqlite3TextToPtr(zArg);
1139a1d0abeSdanielk1977   return TCL_OK;
1149a1d0abeSdanielk1977 }
1159a1d0abeSdanielk1977 
1169a1d0abeSdanielk1977 /*
1177d8085a8Sdrh ** Generate a text representation of a pointer that can be understood
1187d8085a8Sdrh ** by the getDbPointer and getVmPointer routines above.
1197d8085a8Sdrh **
1207d8085a8Sdrh ** The problem is, on some machines (Solaris) if you do a printf with
1217d8085a8Sdrh ** "%p" you cannot turn around and do a scanf with the same "%p" and
1227d8085a8Sdrh ** get your pointer back.  You have to prepend a "0x" before it will
1237d8085a8Sdrh ** work.  Or at least that is what is reported to me (drh).  But this
1247d8085a8Sdrh ** behavior varies from machine to machine.  The solution used her is
1257d8085a8Sdrh ** to test the string right after it is generated to see if it can be
1267d8085a8Sdrh ** understood by scanf, and if not, try prepending an "0x" to see if
1277d8085a8Sdrh ** that helps.  If nothing works, a fatal error is generated.
1287d8085a8Sdrh */
1297d8085a8Sdrh static int makePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
130fe63d1c9Sdrh   sqlite3_snprintf(100, zPtr, "%p", p);
1317d8085a8Sdrh   return TCL_OK;
1327d8085a8Sdrh }
1337d8085a8Sdrh 
1347d8085a8Sdrh /*
1356f8a503dSdanielk1977 ** The callback routine for sqlite3_exec_printf().
136d1bf3512Sdrh */
137d1bf3512Sdrh static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
138d1bf3512Sdrh   Tcl_DString *str = (Tcl_DString*)pArg;
139d1bf3512Sdrh   int i;
140d1bf3512Sdrh 
141d1bf3512Sdrh   if( Tcl_DStringLength(str)==0 ){
142d1bf3512Sdrh     for(i=0; i<argc; i++){
143d1bf3512Sdrh       Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
144d1bf3512Sdrh     }
145d1bf3512Sdrh   }
146d1bf3512Sdrh   for(i=0; i<argc; i++){
147d1bf3512Sdrh     Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
148d1bf3512Sdrh   }
149d1bf3512Sdrh   return 0;
150d1bf3512Sdrh }
151d1bf3512Sdrh 
152d1bf3512Sdrh /*
1536f8a503dSdanielk1977 ** Usage:  sqlite3_exec_printf  DB  FORMAT  STRING
154d1bf3512Sdrh **
1556f8a503dSdanielk1977 ** Invoke the sqlite3_exec_printf() interface using the open database
156d1bf3512Sdrh ** DB.  The SQL is the string FORMAT.  The format string should contain
157d1bf3512Sdrh ** one %s or %q.  STRING is the value inserted into %s or %q.
158d1bf3512Sdrh */
159d1bf3512Sdrh static int test_exec_printf(
160d1bf3512Sdrh   void *NotUsed,
161d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
162d1bf3512Sdrh   int argc,              /* Number of arguments */
163d1bf3512Sdrh   char **argv            /* Text of each argument */
164d1bf3512Sdrh ){
1659bb575fdSdrh   sqlite3 *db;
166d1bf3512Sdrh   Tcl_DString str;
167d1bf3512Sdrh   int rc;
168d1bf3512Sdrh   char *zErr = 0;
1691211de37Sdrh   char *zSql;
170d1bf3512Sdrh   char zBuf[30];
171d1bf3512Sdrh   if( argc!=4 ){
172d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
173d1bf3512Sdrh        " DB FORMAT STRING", 0);
174d1bf3512Sdrh     return TCL_ERROR;
175d1bf3512Sdrh   }
176b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
177d1bf3512Sdrh   Tcl_DStringInit(&str);
1781211de37Sdrh   zSql = sqlite3_mprintf(argv[2], argv[3]);
1791211de37Sdrh   rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
1801211de37Sdrh   sqlite3_free(zSql);
181d1bf3512Sdrh   sprintf(zBuf, "%d", rc);
182d1bf3512Sdrh   Tcl_AppendElement(interp, zBuf);
183d1bf3512Sdrh   Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
184d1bf3512Sdrh   Tcl_DStringFree(&str);
185d1bf3512Sdrh   if( zErr ) free(zErr);
186c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
187d1bf3512Sdrh   return TCL_OK;
188d1bf3512Sdrh }
189d1bf3512Sdrh 
190d1bf3512Sdrh /*
1916f8a503dSdanielk1977 ** Usage:  sqlite3_mprintf_z_test  SEPARATOR  ARG0  ARG1 ...
192d93d8a81Sdrh **
193d93d8a81Sdrh ** Test the %z format of mprintf().  Use multiple mprintf() calls to
194d93d8a81Sdrh ** concatenate arg0 through argn using separator as the separator.
195d93d8a81Sdrh ** Return the result.
196d93d8a81Sdrh */
197d93d8a81Sdrh static int test_mprintf_z(
198d93d8a81Sdrh   void *NotUsed,
199d93d8a81Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
200d93d8a81Sdrh   int argc,              /* Number of arguments */
201d93d8a81Sdrh   char **argv            /* Text of each argument */
202d93d8a81Sdrh ){
203d93d8a81Sdrh   char *zResult = 0;
204d93d8a81Sdrh   int i;
205d93d8a81Sdrh 
206d93d8a81Sdrh   for(i=2; i<argc; i++){
2074adee20fSdanielk1977     zResult = sqlite3MPrintf("%z%s%s", zResult, argv[1], argv[i]);
208d93d8a81Sdrh   }
209d93d8a81Sdrh   Tcl_AppendResult(interp, zResult, 0);
2105f968436Sdrh   sqliteFree(zResult);
211d93d8a81Sdrh   return TCL_OK;
212d93d8a81Sdrh }
213d93d8a81Sdrh 
214d93d8a81Sdrh /*
2156f8a503dSdanielk1977 ** Usage:  sqlite3_get_table_printf  DB  FORMAT  STRING
216d1bf3512Sdrh **
2176f8a503dSdanielk1977 ** Invoke the sqlite3_get_table_printf() interface using the open database
218d1bf3512Sdrh ** DB.  The SQL is the string FORMAT.  The format string should contain
219d1bf3512Sdrh ** one %s or %q.  STRING is the value inserted into %s or %q.
220d1bf3512Sdrh */
221d1bf3512Sdrh static int test_get_table_printf(
222d1bf3512Sdrh   void *NotUsed,
223d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
224d1bf3512Sdrh   int argc,              /* Number of arguments */
225d1bf3512Sdrh   char **argv            /* Text of each argument */
226d1bf3512Sdrh ){
2279bb575fdSdrh   sqlite3 *db;
228d1bf3512Sdrh   Tcl_DString str;
229d1bf3512Sdrh   int rc;
230d1bf3512Sdrh   char *zErr = 0;
231d1bf3512Sdrh   int nRow, nCol;
232d1bf3512Sdrh   char **aResult;
233d1bf3512Sdrh   int i;
234d1bf3512Sdrh   char zBuf[30];
2351211de37Sdrh   char *zSql;
236d1bf3512Sdrh   if( argc!=4 ){
237d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
238d1bf3512Sdrh        " DB FORMAT STRING", 0);
239d1bf3512Sdrh     return TCL_ERROR;
240d1bf3512Sdrh   }
241b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
242d1bf3512Sdrh   Tcl_DStringInit(&str);
2431211de37Sdrh   zSql = sqlite3_mprintf(argv[2],argv[3]);
2441211de37Sdrh   rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
2451211de37Sdrh   sqlite3_free(zSql);
246d1bf3512Sdrh   sprintf(zBuf, "%d", rc);
247d1bf3512Sdrh   Tcl_AppendElement(interp, zBuf);
248d1bf3512Sdrh   if( rc==SQLITE_OK ){
249d1bf3512Sdrh     sprintf(zBuf, "%d", nRow);
250d1bf3512Sdrh     Tcl_AppendElement(interp, zBuf);
251d1bf3512Sdrh     sprintf(zBuf, "%d", nCol);
252d1bf3512Sdrh     Tcl_AppendElement(interp, zBuf);
253d1bf3512Sdrh     for(i=0; i<(nRow+1)*nCol; i++){
254d1bf3512Sdrh       Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
255d1bf3512Sdrh     }
256d1bf3512Sdrh   }else{
257d1bf3512Sdrh     Tcl_AppendElement(interp, zErr);
258d1bf3512Sdrh   }
2596f8a503dSdanielk1977   sqlite3_free_table(aResult);
260d1bf3512Sdrh   if( zErr ) free(zErr);
261c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
262d1bf3512Sdrh   return TCL_OK;
263d1bf3512Sdrh }
264d1bf3512Sdrh 
265af9ff33aSdrh 
266af9ff33aSdrh /*
2676f8a503dSdanielk1977 ** Usage:  sqlite3_last_insert_rowid DB
268af9ff33aSdrh **
269af9ff33aSdrh ** Returns the integer ROWID of the most recent insert.
270af9ff33aSdrh */
271af9ff33aSdrh static int test_last_rowid(
272af9ff33aSdrh   void *NotUsed,
273af9ff33aSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
274af9ff33aSdrh   int argc,              /* Number of arguments */
275af9ff33aSdrh   char **argv            /* Text of each argument */
276af9ff33aSdrh ){
2779bb575fdSdrh   sqlite3 *db;
278af9ff33aSdrh   char zBuf[30];
279af9ff33aSdrh 
280af9ff33aSdrh   if( argc!=2 ){
281af9ff33aSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
282af9ff33aSdrh     return TCL_ERROR;
283af9ff33aSdrh   }
284b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
285c572ef7fSdanielk1977   sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db));
286af9ff33aSdrh   Tcl_AppendResult(interp, zBuf, 0);
287af9ff33aSdrh   return SQLITE_OK;
288af9ff33aSdrh }
289af9ff33aSdrh 
290d1bf3512Sdrh /*
29125d6543dSdrh ** Usage:  sqlite3_key DB KEY
29225d6543dSdrh **
29325d6543dSdrh ** Set the codec key.
29425d6543dSdrh */
29525d6543dSdrh static int test_key(
29625d6543dSdrh   void *NotUsed,
29725d6543dSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
29825d6543dSdrh   int argc,              /* Number of arguments */
29925d6543dSdrh   char **argv            /* Text of each argument */
30025d6543dSdrh ){
3019bb575fdSdrh   sqlite3 *db;
30225d6543dSdrh   const char *zKey;
30325d6543dSdrh   int nKey;
30425d6543dSdrh   if( argc!=3 ){
30525d6543dSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
30625d6543dSdrh        " FILENAME\"", 0);
30725d6543dSdrh     return TCL_ERROR;
30825d6543dSdrh   }
30925d6543dSdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
31025d6543dSdrh   zKey = argv[2];
31125d6543dSdrh   nKey = strlen(zKey);
31225d6543dSdrh #ifdef SQLITE_HAS_CODEC
31325d6543dSdrh   sqlite3_key(db, zKey, nKey);
31425d6543dSdrh #endif
31525d6543dSdrh   return TCL_OK;
31625d6543dSdrh }
31725d6543dSdrh 
31825d6543dSdrh /*
31925d6543dSdrh ** Usage:  sqlite3_rekey DB KEY
32025d6543dSdrh **
32125d6543dSdrh ** Change the codec key.
32225d6543dSdrh */
32325d6543dSdrh static int test_rekey(
32425d6543dSdrh   void *NotUsed,
32525d6543dSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
32625d6543dSdrh   int argc,              /* Number of arguments */
32725d6543dSdrh   char **argv            /* Text of each argument */
32825d6543dSdrh ){
3299bb575fdSdrh   sqlite3 *db;
33025d6543dSdrh   const char *zKey;
33125d6543dSdrh   int nKey;
33225d6543dSdrh   if( argc!=3 ){
33325d6543dSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
33425d6543dSdrh        " FILENAME\"", 0);
33525d6543dSdrh     return TCL_ERROR;
33625d6543dSdrh   }
33725d6543dSdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
33825d6543dSdrh   zKey = argv[2];
33925d6543dSdrh   nKey = strlen(zKey);
34025d6543dSdrh #ifdef SQLITE_HAS_CODEC
34125d6543dSdrh   sqlite3_rekey(db, zKey, nKey);
34225d6543dSdrh #endif
34325d6543dSdrh   return TCL_OK;
34425d6543dSdrh }
34525d6543dSdrh 
34625d6543dSdrh /*
3476f8a503dSdanielk1977 ** Usage:  sqlite3_close DB
348d1bf3512Sdrh **
3496f8a503dSdanielk1977 ** Closes the database opened by sqlite3_open.
350d1bf3512Sdrh */
351d1bf3512Sdrh static int sqlite_test_close(
352d1bf3512Sdrh   void *NotUsed,
353d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
354d1bf3512Sdrh   int argc,              /* Number of arguments */
355d1bf3512Sdrh   char **argv            /* Text of each argument */
356d1bf3512Sdrh ){
3579bb575fdSdrh   sqlite3 *db;
35896d81f99Sdanielk1977   int rc;
359d1bf3512Sdrh   if( argc!=2 ){
360d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
361d1bf3512Sdrh        " FILENAME\"", 0);
362d1bf3512Sdrh     return TCL_ERROR;
363d1bf3512Sdrh   }
364b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
36596d81f99Sdanielk1977   rc = sqlite3_close(db);
366f9d64d2cSdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
367d1bf3512Sdrh   return TCL_OK;
368d1bf3512Sdrh }
369d1bf3512Sdrh 
370d1bf3512Sdrh /*
371c22bd47dSdrh ** Implementation of the x_coalesce() function.
372c22bd47dSdrh ** Return the first argument non-NULL argument.
373c22bd47dSdrh */
3740ae8b831Sdanielk1977 static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
375c22bd47dSdrh   int i;
376c22bd47dSdrh   for(i=0; i<argc; i++){
3779c054830Sdrh     if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
378d8123366Sdanielk1977       sqlite3_result_text(context, sqlite3_value_text(argv[i]), -1,
379d8123366Sdanielk1977           SQLITE_TRANSIENT);
380c22bd47dSdrh       break;
381c22bd47dSdrh     }
382c22bd47dSdrh   }
383c22bd47dSdrh }
384c22bd47dSdrh 
385c22bd47dSdrh /*
386d1d9fc33Sdrh ** A structure into which to accumulate text.
387d1d9fc33Sdrh */
388d1d9fc33Sdrh struct dstr {
389d1d9fc33Sdrh   int nAlloc;  /* Space allocated */
390d1d9fc33Sdrh   int nUsed;   /* Space used */
391d1d9fc33Sdrh   char *z;     /* The space */
392d1d9fc33Sdrh };
393d1d9fc33Sdrh 
394d1d9fc33Sdrh /*
395d1d9fc33Sdrh ** Append text to a dstr
396d1d9fc33Sdrh */
397d1d9fc33Sdrh static void dstrAppend(struct dstr *p, const char *z, int divider){
398d1d9fc33Sdrh   int n = strlen(z);
399d1d9fc33Sdrh   if( p->nUsed + n + 2 > p->nAlloc ){
400d1d9fc33Sdrh     char *zNew;
401d1d9fc33Sdrh     p->nAlloc = p->nAlloc*2 + n + 200;
402d1d9fc33Sdrh     zNew = sqliteRealloc(p->z, p->nAlloc);
403d1d9fc33Sdrh     if( zNew==0 ){
404d1d9fc33Sdrh       sqliteFree(p->z);
405d1d9fc33Sdrh       memset(p, 0, sizeof(*p));
406d1d9fc33Sdrh       return;
407d1d9fc33Sdrh     }
408d1d9fc33Sdrh     p->z = zNew;
409d1d9fc33Sdrh   }
410d1d9fc33Sdrh   if( divider && p->nUsed>0 ){
411d1d9fc33Sdrh     p->z[p->nUsed++] = divider;
412d1d9fc33Sdrh   }
413d1d9fc33Sdrh   memcpy(&p->z[p->nUsed], z, n+1);
414d1d9fc33Sdrh   p->nUsed += n;
415d1d9fc33Sdrh }
416d1d9fc33Sdrh 
417d1d9fc33Sdrh /*
4184adee20fSdanielk1977 ** Invoked for each callback from sqlite3ExecFunc
419d1d9fc33Sdrh */
420d1d9fc33Sdrh static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
421d1d9fc33Sdrh   struct dstr *p = (struct dstr*)pData;
422d1d9fc33Sdrh   int i;
423d1d9fc33Sdrh   for(i=0; i<argc; i++){
424d1d9fc33Sdrh     if( argv[i]==0 ){
425d1d9fc33Sdrh       dstrAppend(p, "NULL", ' ');
426d1d9fc33Sdrh     }else{
427d1d9fc33Sdrh       dstrAppend(p, argv[i], ' ');
428d1d9fc33Sdrh     }
429d1d9fc33Sdrh   }
430d1d9fc33Sdrh   return 0;
431d1d9fc33Sdrh }
432d1d9fc33Sdrh 
433d1d9fc33Sdrh /*
434e35ee196Sdanielk1977 ** Implementation of the x_sqlite_exec() function.  This function takes
435c22bd47dSdrh ** a single argument and attempts to execute that argument as SQL code.
4366cbe1f1bSdrh ** This is illegal and should set the SQLITE_MISUSE flag on the database.
437c22bd47dSdrh **
4386f8a503dSdanielk1977 ** 2004-Jan-07:  We have changed this to make it legal to call sqlite3_exec()
439d1d9fc33Sdrh ** from within a function call.
440d1d9fc33Sdrh **
441c22bd47dSdrh ** This routine simulates the effect of having two threads attempt to
442c22bd47dSdrh ** use the same database at the same time.
443c22bd47dSdrh */
44451ad0ecdSdanielk1977 static void sqlite3ExecFunc(
4450ae8b831Sdanielk1977   sqlite3_context *context,
44651ad0ecdSdanielk1977   int argc,
44751ad0ecdSdanielk1977   sqlite3_value **argv
44851ad0ecdSdanielk1977 ){
449d1d9fc33Sdrh   struct dstr x;
450d1d9fc33Sdrh   memset(&x, 0, sizeof(x));
4519bb575fdSdrh   sqlite3_exec((sqlite3*)sqlite3_user_data(context),
4524f26d6c4Sdrh       sqlite3_value_text(argv[0]),
453d1d9fc33Sdrh       execFuncCallback, &x, 0);
454d8123366Sdanielk1977   sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
455d1d9fc33Sdrh   sqliteFree(x.z);
456c22bd47dSdrh }
457c22bd47dSdrh 
458c22bd47dSdrh /*
459c22bd47dSdrh ** Usage:  sqlite_test_create_function DB
460c22bd47dSdrh **
4616f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order
462c22bd47dSdrh ** to create a function named "x_coalesce".  This function does the same thing
463c22bd47dSdrh ** as the "coalesce" function.  This function also registers an SQL function
464e35ee196Sdanielk1977 ** named "x_sqlite_exec" that invokes sqlite3_exec().  Invoking sqlite3_exec()
465c22bd47dSdrh ** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
466c22bd47dSdrh ** The effect is similar to trying to use the same database connection from
467c22bd47dSdrh ** two threads at the same time.
468c22bd47dSdrh **
469c22bd47dSdrh ** The original motivation for this routine was to be able to call the
4706f8a503dSdanielk1977 ** sqlite3_create_function function while a query is in progress in order
471c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic.
472c22bd47dSdrh */
473c2eef3b3Sdrh static int test_create_function(
474c22bd47dSdrh   void *NotUsed,
475c22bd47dSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
476c22bd47dSdrh   int argc,              /* Number of arguments */
477c22bd47dSdrh   char **argv            /* Text of each argument */
478c22bd47dSdrh ){
479c60d0446Sdrh   int rc;
4809bb575fdSdrh   sqlite3 *db;
481312d6b36Sdanielk1977   sqlite3_value *pVal;
4829bb575fdSdrh   extern void Md5_Register(sqlite3*);
483312d6b36Sdanielk1977 
484c22bd47dSdrh   if( argc!=2 ){
485c22bd47dSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4864397de57Sdanielk1977        " DB\"", 0);
487c22bd47dSdrh     return TCL_ERROR;
488c22bd47dSdrh   }
489b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
490c60d0446Sdrh   rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,
491d8123366Sdanielk1977         ifnullFunc, 0, 0);
492312d6b36Sdanielk1977 
4935436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
494312d6b36Sdanielk1977   /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
495312d6b36Sdanielk1977   ** because it is not tested anywhere else. */
496c60d0446Sdrh   if( rc==SQLITE_OK ){
497312d6b36Sdanielk1977     pVal = sqlite3ValueNew();
498312d6b36Sdanielk1977     sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
499c60d0446Sdrh     rc = sqlite3_create_function16(db,
500c60d0446Sdrh               sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),
501312d6b36Sdanielk1977               1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
502312d6b36Sdanielk1977     sqlite3ValueFree(pVal);
503c60d0446Sdrh   }
5045436dc2dSdrh #endif
5055436dc2dSdrh 
506c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
5074397de57Sdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), 0);
508c22bd47dSdrh   return TCL_OK;
509c22bd47dSdrh }
510c22bd47dSdrh 
511c22bd47dSdrh /*
512c22bd47dSdrh ** Routines to implement the x_count() aggregate function.
513c22bd47dSdrh */
514c22bd47dSdrh typedef struct CountCtx CountCtx;
515c22bd47dSdrh struct CountCtx {
516c22bd47dSdrh   int n;
517c22bd47dSdrh };
5180ae8b831Sdanielk1977 static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
519c22bd47dSdrh   CountCtx *p;
5204f26d6c4Sdrh   p = sqlite3_aggregate_context(context, sizeof(*p));
5219c054830Sdrh   if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
522c22bd47dSdrh     p->n++;
523c22bd47dSdrh   }
524c22bd47dSdrh }
5250ae8b831Sdanielk1977 static void countFinalize(sqlite3_context *context){
526c22bd47dSdrh   CountCtx *p;
5274f26d6c4Sdrh   p = sqlite3_aggregate_context(context, sizeof(*p));
528c572ef7fSdanielk1977   sqlite3_result_int(context, p ? p->n : 0);
529c22bd47dSdrh }
530c22bd47dSdrh 
531c22bd47dSdrh /*
532c22bd47dSdrh ** Usage:  sqlite_test_create_aggregate DB
533c22bd47dSdrh **
5346f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order
535c22bd47dSdrh ** to create a function named "x_count".  This function does the same thing
536c22bd47dSdrh ** as the "md5sum" function.
537c22bd47dSdrh **
538c22bd47dSdrh ** The original motivation for this routine was to be able to call the
5396f8a503dSdanielk1977 ** sqlite3_create_aggregate function while a query is in progress in order
540c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic.
541c22bd47dSdrh */
542c2eef3b3Sdrh static int test_create_aggregate(
543c22bd47dSdrh   void *NotUsed,
544c22bd47dSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
545c22bd47dSdrh   int argc,              /* Number of arguments */
546c22bd47dSdrh   char **argv            /* Text of each argument */
547c22bd47dSdrh ){
5489bb575fdSdrh   sqlite3 *db;
549c60d0446Sdrh   int rc;
550c22bd47dSdrh   if( argc!=2 ){
551c22bd47dSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
552c22bd47dSdrh        " FILENAME\"", 0);
553c22bd47dSdrh     return TCL_ERROR;
554c22bd47dSdrh   }
555b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
556c60d0446Sdrh   rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
557d8123366Sdanielk1977       countStep,countFinalize);
558c60d0446Sdrh   if( rc==SQLITE_OK ){
559f9d64d2cSdanielk1977     sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
560d8123366Sdanielk1977         countStep,countFinalize);
561c60d0446Sdrh   }
562c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
563c22bd47dSdrh   return TCL_OK;
564c22bd47dSdrh }
565c22bd47dSdrh 
566c22bd47dSdrh 
567c22bd47dSdrh 
568c22bd47dSdrh /*
5696f8a503dSdanielk1977 ** Usage:  sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
570d1bf3512Sdrh **
571d1bf3512Sdrh ** Call mprintf with three integer arguments
572d1bf3512Sdrh */
5736f8a503dSdanielk1977 static int sqlite3_mprintf_int(
574d1bf3512Sdrh   void *NotUsed,
575d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
576d1bf3512Sdrh   int argc,              /* Number of arguments */
577d1bf3512Sdrh   char **argv            /* Text of each argument */
578d1bf3512Sdrh ){
579d1bf3512Sdrh   int a[3], i;
580d1bf3512Sdrh   char *z;
581d1bf3512Sdrh   if( argc!=5 ){
582d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
583d1bf3512Sdrh        " FORMAT INT INT INT\"", 0);
584d1bf3512Sdrh     return TCL_ERROR;
585d1bf3512Sdrh   }
586d1bf3512Sdrh   for(i=2; i<5; i++){
587d1bf3512Sdrh     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
588d1bf3512Sdrh   }
5896f8a503dSdanielk1977   z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
590d1bf3512Sdrh   Tcl_AppendResult(interp, z, 0);
5913f4fedb2Sdrh   sqlite3_free(z);
592d1bf3512Sdrh   return TCL_OK;
593d1bf3512Sdrh }
594d1bf3512Sdrh 
595d1bf3512Sdrh /*
5969d213ef0Sdrh ** If zNum represents an integer that will fit in 64-bits, then set
5979d213ef0Sdrh ** *pValue to that integer and return true.  Otherwise return false.
5989d213ef0Sdrh */
5999d213ef0Sdrh static int sqlite3GetInt64(const char *zNum, i64 *pValue){
6009d213ef0Sdrh   if( sqlite3FitsIn64Bits(zNum) ){
6019d213ef0Sdrh     sqlite3atoi64(zNum, pValue);
6029d213ef0Sdrh     return 1;
6039d213ef0Sdrh   }
6049d213ef0Sdrh   return 0;
6059d213ef0Sdrh }
6069d213ef0Sdrh 
6079d213ef0Sdrh /*
608e9707671Sdrh ** Usage:  sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
609e9707671Sdrh **
610e9707671Sdrh ** Call mprintf with three 64-bit integer arguments
611e9707671Sdrh */
612e9707671Sdrh static int sqlite3_mprintf_int64(
613e9707671Sdrh   void *NotUsed,
614e9707671Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
615e9707671Sdrh   int argc,              /* Number of arguments */
616e9707671Sdrh   char **argv            /* Text of each argument */
617e9707671Sdrh ){
618e9707671Sdrh   int i;
619e9707671Sdrh   sqlite_int64 a[3];
620e9707671Sdrh   char *z;
621e9707671Sdrh   if( argc!=5 ){
622e9707671Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
623e9707671Sdrh        " FORMAT INT INT INT\"", 0);
624e9707671Sdrh     return TCL_ERROR;
625e9707671Sdrh   }
626e9707671Sdrh   for(i=2; i<5; i++){
627e9707671Sdrh     if( !sqlite3GetInt64(argv[i], &a[i-2]) ){
628e9707671Sdrh       Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
629e9707671Sdrh       return TCL_ERROR;
630e9707671Sdrh     }
631e9707671Sdrh   }
632e9707671Sdrh   z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
633e9707671Sdrh   Tcl_AppendResult(interp, z, 0);
634e9707671Sdrh   sqlite3_free(z);
635e9707671Sdrh   return TCL_OK;
636e9707671Sdrh }
637e9707671Sdrh 
638e9707671Sdrh /*
6396f8a503dSdanielk1977 ** Usage:  sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
640d1bf3512Sdrh **
641d1bf3512Sdrh ** Call mprintf with two integer arguments and one string argument
642d1bf3512Sdrh */
6436f8a503dSdanielk1977 static int sqlite3_mprintf_str(
644d1bf3512Sdrh   void *NotUsed,
645d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
646d1bf3512Sdrh   int argc,              /* Number of arguments */
647d1bf3512Sdrh   char **argv            /* Text of each argument */
648d1bf3512Sdrh ){
649d1bf3512Sdrh   int a[3], i;
650d1bf3512Sdrh   char *z;
651f220b24fSchw   if( argc<4 || argc>5 ){
652d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
653f220b24fSchw        " FORMAT INT INT ?STRING?\"", 0);
654d1bf3512Sdrh     return TCL_ERROR;
655d1bf3512Sdrh   }
656d1bf3512Sdrh   for(i=2; i<4; i++){
657d1bf3512Sdrh     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
658d1bf3512Sdrh   }
6596f8a503dSdanielk1977   z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
660d1bf3512Sdrh   Tcl_AppendResult(interp, z, 0);
6613f4fedb2Sdrh   sqlite3_free(z);
662d1bf3512Sdrh   return TCL_OK;
663d1bf3512Sdrh }
664d1bf3512Sdrh 
665d1bf3512Sdrh /*
6666f8a503dSdanielk1977 ** Usage:  sqlite3_mprintf_str FORMAT INTEGER INTEGER DOUBLE
667d1bf3512Sdrh **
668d1bf3512Sdrh ** Call mprintf with two integer arguments and one double argument
669d1bf3512Sdrh */
6706f8a503dSdanielk1977 static int sqlite3_mprintf_double(
671d1bf3512Sdrh   void *NotUsed,
672d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
673d1bf3512Sdrh   int argc,              /* Number of arguments */
674d1bf3512Sdrh   char **argv            /* Text of each argument */
675d1bf3512Sdrh ){
676d1bf3512Sdrh   int a[3], i;
677d1bf3512Sdrh   double r;
678d1bf3512Sdrh   char *z;
679d1bf3512Sdrh   if( argc!=5 ){
680d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
681d1bf3512Sdrh        " FORMAT INT INT STRING\"", 0);
682d1bf3512Sdrh     return TCL_ERROR;
683d1bf3512Sdrh   }
684d1bf3512Sdrh   for(i=2; i<4; i++){
685d1bf3512Sdrh     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
686d1bf3512Sdrh   }
687d1bf3512Sdrh   if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
6886f8a503dSdanielk1977   z = sqlite3_mprintf(argv[1], a[0], a[1], r);
689d1bf3512Sdrh   Tcl_AppendResult(interp, z, 0);
6903f4fedb2Sdrh   sqlite3_free(z);
691d1bf3512Sdrh   return TCL_OK;
692d1bf3512Sdrh }
693d1bf3512Sdrh 
694d1bf3512Sdrh /*
6956f8a503dSdanielk1977 ** Usage:  sqlite3_mprintf_str FORMAT DOUBLE DOUBLE
696b621c237Sdrh **
697b621c237Sdrh ** Call mprintf with a single double argument which is the product of the
698b621c237Sdrh ** two arguments given above.  This is used to generate overflow and underflow
699b621c237Sdrh ** doubles to test that they are converted properly.
700b621c237Sdrh */
7016f8a503dSdanielk1977 static int sqlite3_mprintf_scaled(
702b621c237Sdrh   void *NotUsed,
703b621c237Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
704b621c237Sdrh   int argc,              /* Number of arguments */
705b621c237Sdrh   char **argv            /* Text of each argument */
706b621c237Sdrh ){
707b621c237Sdrh   int i;
708b621c237Sdrh   double r[2];
709b621c237Sdrh   char *z;
710b621c237Sdrh   if( argc!=4 ){
711b621c237Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
712b621c237Sdrh        " FORMAT DOUBLE DOUBLE\"", 0);
713b621c237Sdrh     return TCL_ERROR;
714b621c237Sdrh   }
715b621c237Sdrh   for(i=2; i<4; i++){
716b621c237Sdrh     if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
717b621c237Sdrh   }
7186f8a503dSdanielk1977   z = sqlite3_mprintf(argv[1], r[0]*r[1]);
719b621c237Sdrh   Tcl_AppendResult(interp, z, 0);
7203f4fedb2Sdrh   sqlite3_free(z);
721b621c237Sdrh   return TCL_OK;
722b621c237Sdrh }
723b621c237Sdrh 
724b621c237Sdrh /*
725e29b1a05Sdrh ** Usage:  sqlite3_mprintf_stronly FORMAT STRING
726e29b1a05Sdrh **
727e29b1a05Sdrh ** Call mprintf with a single double argument which is the product of the
728e29b1a05Sdrh ** two arguments given above.  This is used to generate overflow and underflow
729e29b1a05Sdrh ** doubles to test that they are converted properly.
730e29b1a05Sdrh */
731e29b1a05Sdrh static int sqlite3_mprintf_stronly(
732e29b1a05Sdrh   void *NotUsed,
733e29b1a05Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
734e29b1a05Sdrh   int argc,              /* Number of arguments */
735e29b1a05Sdrh   char **argv            /* Text of each argument */
736e29b1a05Sdrh ){
737e29b1a05Sdrh   char *z;
738e29b1a05Sdrh   if( argc!=3 ){
739e29b1a05Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
740e29b1a05Sdrh        " FORMAT STRING\"", 0);
741e29b1a05Sdrh     return TCL_ERROR;
742e29b1a05Sdrh   }
743e29b1a05Sdrh   z = sqlite3_mprintf(argv[1], argv[2]);
744e29b1a05Sdrh   Tcl_AppendResult(interp, z, 0);
745e29b1a05Sdrh   sqlite3_free(z);
746e29b1a05Sdrh   return TCL_OK;
747e29b1a05Sdrh }
748e29b1a05Sdrh 
749e29b1a05Sdrh /*
7504693423bSdrh ** Usage: sqlite_malloc_fail N  ?REPEAT-INTERVAL?
751daffd0e5Sdrh **
7524693423bSdrh ** Rig sqliteMalloc() to fail on the N-th call and every REPEAT-INTERVAL call
7534693423bSdrh ** after that.  If REPEAT-INTERVAL is 0 or is omitted, then only a single
7544693423bSdrh ** malloc will fail.  If REPEAT-INTERVAL is 1 then all mallocs after the
7554693423bSdrh ** first failure will continue to fail on every call.  If REPEAT-INTERVAL is
7564693423bSdrh ** 2 then every other malloc will fail.  And so forth.
7574693423bSdrh **
7584693423bSdrh ** Turn off this mechanism and reset the sqlite3_malloc_failed variable is N==0.
759daffd0e5Sdrh */
7602c336549Sdanielk1977 #ifdef SQLITE_MEMDEBUG
761daffd0e5Sdrh static int sqlite_malloc_fail(
762daffd0e5Sdrh   void *NotUsed,
763daffd0e5Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
764daffd0e5Sdrh   int argc,              /* Number of arguments */
765daffd0e5Sdrh   char **argv            /* Text of each argument */
766daffd0e5Sdrh ){
767daffd0e5Sdrh   int n;
7684693423bSdrh   int rep;
7694693423bSdrh   if( argc!=2 && argc!=3 ){
770daffd0e5Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0);
771daffd0e5Sdrh     return TCL_ERROR;
772daffd0e5Sdrh   }
773daffd0e5Sdrh   if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
7744693423bSdrh   if( argc==3 ){
7754693423bSdrh     if( Tcl_GetInt(interp, argv[2], &rep) ) return TCL_ERROR;
7764693423bSdrh   }else{
7774693423bSdrh     rep = 0;
7784693423bSdrh   }
7796f8a503dSdanielk1977   sqlite3_iMallocFail = n;
7804693423bSdrh   sqlite3_iMallocReset = rep;
7816f8a503dSdanielk1977   sqlite3_malloc_failed = 0;
782daffd0e5Sdrh   return TCL_OK;
783daffd0e5Sdrh }
784daffd0e5Sdrh #endif
785daffd0e5Sdrh 
786daffd0e5Sdrh /*
787daffd0e5Sdrh ** Usage: sqlite_malloc_stat
788daffd0e5Sdrh **
789daffd0e5Sdrh ** Return the number of prior calls to sqliteMalloc() and sqliteFree().
790daffd0e5Sdrh */
7912c336549Sdanielk1977 #ifdef SQLITE_MEMDEBUG
792daffd0e5Sdrh static int sqlite_malloc_stat(
793daffd0e5Sdrh   void *NotUsed,
794daffd0e5Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
795daffd0e5Sdrh   int argc,              /* Number of arguments */
796daffd0e5Sdrh   char **argv            /* Text of each argument */
797daffd0e5Sdrh ){
798daffd0e5Sdrh   char zBuf[200];
7996f8a503dSdanielk1977   sprintf(zBuf, "%d %d %d", sqlite3_nMalloc, sqlite3_nFree, sqlite3_iMallocFail);
800daffd0e5Sdrh   Tcl_AppendResult(interp, zBuf, 0);
801daffd0e5Sdrh   return TCL_OK;
802daffd0e5Sdrh }
803daffd0e5Sdrh #endif
804daffd0e5Sdrh 
805daffd0e5Sdrh /*
80628b4e489Sdrh ** Usage:  sqlite_abort
80728b4e489Sdrh **
80828b4e489Sdrh ** Shutdown the process immediately.  This is not a clean shutdown.
80928b4e489Sdrh ** This command is used to test the recoverability of a database in
81028b4e489Sdrh ** the event of a program crash.
81128b4e489Sdrh */
81228b4e489Sdrh static int sqlite_abort(
81328b4e489Sdrh   void *NotUsed,
81428b4e489Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
81528b4e489Sdrh   int argc,              /* Number of arguments */
81628b4e489Sdrh   char **argv            /* Text of each argument */
81728b4e489Sdrh ){
81828b4e489Sdrh   assert( interp==0 );   /* This will always fail */
81928b4e489Sdrh   return TCL_OK;
82028b4e489Sdrh }
82128b4e489Sdrh 
82228b4e489Sdrh /*
8236cbe1f1bSdrh ** The following routine is a user-defined SQL function whose purpose
8246cbe1f1bSdrh ** is to test the sqlite_set_result() API.
8256cbe1f1bSdrh */
8260ae8b831Sdanielk1977 static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
8276cbe1f1bSdrh   while( argc>=2 ){
8284f26d6c4Sdrh     const char *zArg0 = sqlite3_value_text(argv[0]);
8296d88bad4Sdanielk1977     if( zArg0 ){
8306d88bad4Sdanielk1977       if( 0==sqlite3StrICmp(zArg0, "int") ){
8316d88bad4Sdanielk1977         sqlite3_result_int(context, sqlite3_value_int(argv[1]));
8326d88bad4Sdanielk1977       }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
8336d88bad4Sdanielk1977         sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
83451ad0ecdSdanielk1977       }else if( sqlite3StrICmp(zArg0,"string")==0 ){
835d8123366Sdanielk1977         sqlite3_result_text(context, sqlite3_value_text(argv[1]), -1,
836d8123366Sdanielk1977             SQLITE_TRANSIENT);
83751ad0ecdSdanielk1977       }else if( sqlite3StrICmp(zArg0,"double")==0 ){
8386d88bad4Sdanielk1977         sqlite3_result_double(context, sqlite3_value_double(argv[1]));
8396d88bad4Sdanielk1977       }else if( sqlite3StrICmp(zArg0,"null")==0 ){
8406d88bad4Sdanielk1977         sqlite3_result_null(context);
8416d88bad4Sdanielk1977       }else if( sqlite3StrICmp(zArg0,"value")==0 ){
8426d88bad4Sdanielk1977         sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
8436cbe1f1bSdrh       }else{
8446d88bad4Sdanielk1977         goto error_out;
8456d88bad4Sdanielk1977       }
8466d88bad4Sdanielk1977     }else{
8476d88bad4Sdanielk1977       goto error_out;
8486cbe1f1bSdrh     }
8496cbe1f1bSdrh     argc -= 2;
8506cbe1f1bSdrh     argv += 2;
8516cbe1f1bSdrh   }
8526d88bad4Sdanielk1977   return;
8536d88bad4Sdanielk1977 
8546d88bad4Sdanielk1977 error_out:
8556d88bad4Sdanielk1977   sqlite3_result_error(context,"first argument should be one of: "
8566d88bad4Sdanielk1977       "int int64 string double null value", -1);
8576cbe1f1bSdrh }
8586cbe1f1bSdrh 
8596cbe1f1bSdrh /*
8606cbe1f1bSdrh ** Usage:   sqlite_register_test_function  DB  NAME
8616cbe1f1bSdrh **
8626cbe1f1bSdrh ** Register the test SQL function on the database DB under the name NAME.
8636cbe1f1bSdrh */
864c2eef3b3Sdrh static int test_register_func(
8656cbe1f1bSdrh   void *NotUsed,
8666cbe1f1bSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
8676cbe1f1bSdrh   int argc,              /* Number of arguments */
8686cbe1f1bSdrh   char **argv            /* Text of each argument */
8696cbe1f1bSdrh ){
8709bb575fdSdrh   sqlite3 *db;
8716cbe1f1bSdrh   int rc;
8726cbe1f1bSdrh   if( argc!=3 ){
8736cbe1f1bSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
8746cbe1f1bSdrh        " DB FUNCTION-NAME", 0);
8756cbe1f1bSdrh     return TCL_ERROR;
8766cbe1f1bSdrh   }
877b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
878f9d64d2cSdanielk1977   rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
879d8123366Sdanielk1977       testFunc, 0, 0);
8806cbe1f1bSdrh   if( rc!=0 ){
881f20b21c8Sdanielk1977     Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
8826cbe1f1bSdrh     return TCL_ERROR;
8836cbe1f1bSdrh   }
884c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
8856cbe1f1bSdrh   return TCL_OK;
8866cbe1f1bSdrh }
8876cbe1f1bSdrh 
8886cbe1f1bSdrh /*
889106bb236Sdanielk1977 ** Usage:  sqlite3_finalize  STMT
890b86ccfb2Sdrh **
891106bb236Sdanielk1977 ** Finalize a statement handle.
892b86ccfb2Sdrh */
893b86ccfb2Sdrh static int test_finalize(
894106bb236Sdanielk1977   void * clientData,
895106bb236Sdanielk1977   Tcl_Interp *interp,
896106bb236Sdanielk1977   int objc,
897106bb236Sdanielk1977   Tcl_Obj *CONST objv[]
898b86ccfb2Sdrh ){
899106bb236Sdanielk1977   sqlite3_stmt *pStmt;
900b86ccfb2Sdrh   int rc;
901c60d0446Sdrh   sqlite3 *db;
902106bb236Sdanielk1977 
903106bb236Sdanielk1977   if( objc!=2 ){
904106bb236Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
905106bb236Sdanielk1977         Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
906b86ccfb2Sdrh     return TCL_ERROR;
907b86ccfb2Sdrh   }
908106bb236Sdanielk1977 
909106bb236Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
910106bb236Sdanielk1977 
9114397de57Sdanielk1977   if( pStmt ){
912c60d0446Sdrh     db = StmtToDb(pStmt);
9134397de57Sdanielk1977   }
914fc57d7bfSdanielk1977   rc = sqlite3_finalize(pStmt);
915b77f5dadSdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
9164397de57Sdanielk1977   if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
917106bb236Sdanielk1977   return TCL_OK;
918106bb236Sdanielk1977 }
919106bb236Sdanielk1977 
920106bb236Sdanielk1977 /*
921106bb236Sdanielk1977 ** Usage:  sqlite3_reset  STMT
922106bb236Sdanielk1977 **
923106bb236Sdanielk1977 ** Finalize a statement handle.
924106bb236Sdanielk1977 */
925106bb236Sdanielk1977 static int test_reset(
926106bb236Sdanielk1977   void * clientData,
927106bb236Sdanielk1977   Tcl_Interp *interp,
928106bb236Sdanielk1977   int objc,
929106bb236Sdanielk1977   Tcl_Obj *CONST objv[]
930106bb236Sdanielk1977 ){
931106bb236Sdanielk1977   sqlite3_stmt *pStmt;
932106bb236Sdanielk1977   int rc;
933106bb236Sdanielk1977 
934106bb236Sdanielk1977   if( objc!=2 ){
935106bb236Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
936106bb236Sdanielk1977         Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
937106bb236Sdanielk1977     return TCL_ERROR;
938106bb236Sdanielk1977   }
939106bb236Sdanielk1977 
940106bb236Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
941106bb236Sdanielk1977 
942fc57d7bfSdanielk1977   rc = sqlite3_reset(pStmt);
9434397de57Sdanielk1977   if( pStmt &&
9444397de57Sdanielk1977       sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
9454397de57Sdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
946106bb236Sdanielk1977   if( rc ){
947b86ccfb2Sdrh     return TCL_ERROR;
948b86ccfb2Sdrh   }
949b86ccfb2Sdrh   return TCL_OK;
950b86ccfb2Sdrh }
951b86ccfb2Sdrh 
9525a38705eSdrh /*
953fbcd585fSdanielk1977 ** Usage:  sqlite3_changes DB
95450457896Sdrh **
955fbcd585fSdanielk1977 ** Return the number of changes made to the database by the last SQL
956fbcd585fSdanielk1977 ** execution.
95750457896Sdrh */
958fbcd585fSdanielk1977 static int test_changes(
959fbcd585fSdanielk1977   void * clientData,
960fbcd585fSdanielk1977   Tcl_Interp *interp,
961fbcd585fSdanielk1977   int objc,
962fbcd585fSdanielk1977   Tcl_Obj *CONST objv[]
963fbcd585fSdanielk1977 ){
964fbcd585fSdanielk1977   sqlite3 *db;
965fbcd585fSdanielk1977   if( objc!=2 ){
966fbcd585fSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
967fbcd585fSdanielk1977        Tcl_GetString(objv[0]), " DB", 0);
968fbcd585fSdanielk1977     return TCL_ERROR;
969fbcd585fSdanielk1977   }
970fbcd585fSdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
971fbcd585fSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
972fbcd585fSdanielk1977   return TCL_OK;
973fbcd585fSdanielk1977 }
97450457896Sdrh 
97550457896Sdrh /*
9767c972decSdrh ** This is the "static_bind_value" that variables are bound to when
9776f8a503dSdanielk1977 ** the FLAG option of sqlite3_bind is "static"
97850457896Sdrh */
9797c972decSdrh static char *sqlite_static_bind_value = 0;
9807c972decSdrh 
9817c972decSdrh /*
9826f8a503dSdanielk1977 ** Usage:  sqlite3_bind  VM  IDX  VALUE  FLAGS
9837c972decSdrh **
9847c972decSdrh ** Sets the value of the IDX-th occurance of "?" in the original SQL
9857c972decSdrh ** string.  VALUE is the new value.  If FLAGS=="null" then VALUE is
9867c972decSdrh ** ignored and the value is set to NULL.  If FLAGS=="static" then
9877c972decSdrh ** the value is set to the value of a static variable named
9887c972decSdrh ** "sqlite_static_bind_value".  If FLAGS=="normal" then a copy
9897c972decSdrh ** of the VALUE is made.
9907c972decSdrh */
9917c972decSdrh static int test_bind(
99250457896Sdrh   void *NotUsed,
99350457896Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
99450457896Sdrh   int argc,              /* Number of arguments */
99550457896Sdrh   char **argv            /* Text of each argument */
99650457896Sdrh ){
997fc57d7bfSdanielk1977   sqlite3_stmt *pStmt;
99850457896Sdrh   int rc;
9997c972decSdrh   int idx;
10007c972decSdrh   if( argc!=5 ){
100150457896Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
10027c972decSdrh        " VM IDX VALUE (null|static|normal)\"", 0);
100350457896Sdrh     return TCL_ERROR;
100450457896Sdrh   }
1005fc57d7bfSdanielk1977   if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
10067c972decSdrh   if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
10077c972decSdrh   if( strcmp(argv[4],"null")==0 ){
1008fc57d7bfSdanielk1977     rc = sqlite3_bind_null(pStmt, idx);
10097c972decSdrh   }else if( strcmp(argv[4],"static")==0 ){
1010fc57d7bfSdanielk1977     rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
10117c972decSdrh   }else if( strcmp(argv[4],"normal")==0 ){
1012d8123366Sdanielk1977     rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
10137c972decSdrh   }else{
10147c972decSdrh     Tcl_AppendResult(interp, "4th argument should be "
10157c972decSdrh         "\"null\" or \"static\" or \"normal\"", 0);
10167c972decSdrh     return TCL_ERROR;
10177c972decSdrh   }
1018c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
101950457896Sdrh   if( rc ){
102050457896Sdrh     char zBuf[50];
102150457896Sdrh     sprintf(zBuf, "(%d) ", rc);
1022f20b21c8Sdanielk1977     Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
102350457896Sdrh     return TCL_ERROR;
102450457896Sdrh   }
102550457896Sdrh   return TCL_OK;
102650457896Sdrh }
102750457896Sdrh 
10285436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
10294e6af134Sdanielk1977 /*
10304e6af134Sdanielk1977 ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
10314e6af134Sdanielk1977 **
10324e6af134Sdanielk1977 ** This function is used to test that SQLite selects the correct collation
10334e6af134Sdanielk1977 ** sequence callback when multiple versions (for different text encodings)
10344e6af134Sdanielk1977 ** are available.
10354e6af134Sdanielk1977 **
10364e6af134Sdanielk1977 ** Calling this routine registers the collation sequence "test_collate"
10374e6af134Sdanielk1977 ** with database handle <db>. The second argument must be a list of three
10384e6af134Sdanielk1977 ** boolean values. If the first is true, then a version of test_collate is
10394e6af134Sdanielk1977 ** registered for UTF-8, if the second is true, a version is registered for
10404e6af134Sdanielk1977 ** UTF-16le, if the third is true, a UTF-16be version is available.
10414e6af134Sdanielk1977 ** Previous versions of test_collate are deleted.
10424e6af134Sdanielk1977 **
10434e6af134Sdanielk1977 ** The collation sequence test_collate is implemented by calling the
10444e6af134Sdanielk1977 ** following TCL script:
10454e6af134Sdanielk1977 **
10464e6af134Sdanielk1977 **   "test_collate <enc> <lhs> <rhs>"
10474e6af134Sdanielk1977 **
10484e6af134Sdanielk1977 ** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
10494e6af134Sdanielk1977 ** The <enc> parameter is the encoding of the collation function that
10504e6af134Sdanielk1977 ** SQLite selected to call. The TCL test script implements the
10514e6af134Sdanielk1977 ** "test_collate" proc.
10524e6af134Sdanielk1977 **
10534e6af134Sdanielk1977 ** Note that this will only work with one intepreter at a time, as the
10544e6af134Sdanielk1977 ** interp pointer to use when evaluating the TCL script is stored in
10554e6af134Sdanielk1977 ** pTestCollateInterp.
10564e6af134Sdanielk1977 */
10574e6af134Sdanielk1977 static Tcl_Interp* pTestCollateInterp;
10584e6af134Sdanielk1977 static int test_collate_func(
10594e6af134Sdanielk1977   void *pCtx,
10604e6af134Sdanielk1977   int nA, const void *zA,
10614e6af134Sdanielk1977   int nB, const void *zB
10624e6af134Sdanielk1977 ){
10634e6af134Sdanielk1977   Tcl_Interp *i = pTestCollateInterp;
10644e6af134Sdanielk1977   int encin = (int)pCtx;
10654e6af134Sdanielk1977   int res;
10664e6af134Sdanielk1977 
10674e6af134Sdanielk1977   sqlite3_value *pVal;
10684e6af134Sdanielk1977   Tcl_Obj *pX;
10694e6af134Sdanielk1977 
10704e6af134Sdanielk1977   pX = Tcl_NewStringObj("test_collate", -1);
10714e6af134Sdanielk1977   Tcl_IncrRefCount(pX);
10724e6af134Sdanielk1977 
10734e6af134Sdanielk1977   switch( encin ){
10744e6af134Sdanielk1977     case SQLITE_UTF8:
10754e6af134Sdanielk1977       Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
10764e6af134Sdanielk1977       break;
10774e6af134Sdanielk1977     case SQLITE_UTF16LE:
10784e6af134Sdanielk1977       Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
10794e6af134Sdanielk1977       break;
10804e6af134Sdanielk1977     case SQLITE_UTF16BE:
10814e6af134Sdanielk1977       Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
10824e6af134Sdanielk1977       break;
10834e6af134Sdanielk1977     default:
10844e6af134Sdanielk1977       assert(0);
10854e6af134Sdanielk1977   }
10864e6af134Sdanielk1977 
10874e6af134Sdanielk1977   pVal = sqlite3ValueNew();
1088bfd6cce5Sdanielk1977   sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
10894e6af134Sdanielk1977   Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1));
1090bfd6cce5Sdanielk1977   sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
10914e6af134Sdanielk1977   Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1));
10924e6af134Sdanielk1977   sqlite3ValueFree(pVal);
10934e6af134Sdanielk1977 
10944e6af134Sdanielk1977   Tcl_EvalObjEx(i, pX, 0);
10954e6af134Sdanielk1977   Tcl_DecrRefCount(pX);
10964e6af134Sdanielk1977   Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
10974e6af134Sdanielk1977   return res;
10984e6af134Sdanielk1977 }
10994e6af134Sdanielk1977 static int test_collate(
11004e6af134Sdanielk1977   void * clientData,
11014e6af134Sdanielk1977   Tcl_Interp *interp,
11024e6af134Sdanielk1977   int objc,
11034e6af134Sdanielk1977   Tcl_Obj *CONST objv[]
11044e6af134Sdanielk1977 ){
11054e6af134Sdanielk1977   sqlite3 *db;
11064e6af134Sdanielk1977   int val;
1107312d6b36Sdanielk1977   sqlite3_value *pVal;
1108c60d0446Sdrh   int rc;
11094e6af134Sdanielk1977 
11104e6af134Sdanielk1977   if( objc!=5 ) goto bad_args;
11114e6af134Sdanielk1977   pTestCollateInterp = interp;
11124e6af134Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
11134e6af134Sdanielk1977 
11144e6af134Sdanielk1977   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
1115c60d0446Sdrh   rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
11164e6af134Sdanielk1977           (void *)SQLITE_UTF8, val?test_collate_func:0);
1117c60d0446Sdrh   if( rc==SQLITE_OK ){
11184e6af134Sdanielk1977     if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1119c60d0446Sdrh     rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
11204e6af134Sdanielk1977             (void *)SQLITE_UTF16LE, val?test_collate_func:0);
11214e6af134Sdanielk1977     if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
1122312d6b36Sdanielk1977 
1123312d6b36Sdanielk1977     pVal = sqlite3ValueNew();
1124312d6b36Sdanielk1977     sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
1125312d6b36Sdanielk1977     sqlite3_create_collation16(db, sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),
1126312d6b36Sdanielk1977           SQLITE_UTF16BE, (void *)SQLITE_UTF16BE, val?test_collate_func:0);
1127312d6b36Sdanielk1977     sqlite3ValueFree(pVal);
1128c60d0446Sdrh   }
1129c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
11304e6af134Sdanielk1977   return TCL_OK;
11314e6af134Sdanielk1977 
11324e6af134Sdanielk1977 bad_args:
11334e6af134Sdanielk1977   Tcl_AppendResult(interp, "wrong # args: should be \"",
11344e6af134Sdanielk1977       Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
11354e6af134Sdanielk1977   return TCL_ERROR;
11364e6af134Sdanielk1977 }
11374e6af134Sdanielk1977 
1138312d6b36Sdanielk1977 static void test_collate_needed_cb(
1139312d6b36Sdanielk1977   void *pCtx,
1140312d6b36Sdanielk1977   sqlite3 *db,
1141312d6b36Sdanielk1977   int eTextRep,
1142312d6b36Sdanielk1977   const void *notUsed
1143312d6b36Sdanielk1977 ){
1144312d6b36Sdanielk1977   int enc = db->enc;
1145312d6b36Sdanielk1977   sqlite3_create_collation(
1146312d6b36Sdanielk1977       db, "test_collate", db->enc, (void *)enc, test_collate_func);
1147312d6b36Sdanielk1977 }
1148312d6b36Sdanielk1977 
1149312d6b36Sdanielk1977 /*
1150312d6b36Sdanielk1977 ** Usage: add_test_collate_needed DB
1151312d6b36Sdanielk1977 */
1152312d6b36Sdanielk1977 static int test_collate_needed(
1153312d6b36Sdanielk1977   void * clientData,
1154312d6b36Sdanielk1977   Tcl_Interp *interp,
1155312d6b36Sdanielk1977   int objc,
1156312d6b36Sdanielk1977   Tcl_Obj *CONST objv[]
1157312d6b36Sdanielk1977 ){
1158312d6b36Sdanielk1977   sqlite3 *db;
1159c60d0446Sdrh   int rc;
1160312d6b36Sdanielk1977 
1161312d6b36Sdanielk1977   if( objc!=2 ) goto bad_args;
1162312d6b36Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1163c60d0446Sdrh   rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
1164c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
1165312d6b36Sdanielk1977   return TCL_OK;
1166312d6b36Sdanielk1977 
1167312d6b36Sdanielk1977 bad_args:
1168312d6b36Sdanielk1977   Tcl_WrongNumArgs(interp, 1, objv, "DB");
1169312d6b36Sdanielk1977   return TCL_ERROR;
1170312d6b36Sdanielk1977 }
11715436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
1172312d6b36Sdanielk1977 
1173c8e9a2dfSdanielk1977 /*
1174c8e9a2dfSdanielk1977 ** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
1175c8e9a2dfSdanielk1977 **
1176c8e9a2dfSdanielk1977 ** This function is used to test that SQLite selects the correct user
1177c8e9a2dfSdanielk1977 ** function callback when multiple versions (for different text encodings)
1178c8e9a2dfSdanielk1977 ** are available.
1179c8e9a2dfSdanielk1977 **
1180c8e9a2dfSdanielk1977 ** Calling this routine registers up to three versions of the user function
1181c8e9a2dfSdanielk1977 ** "test_function" with database handle <db>.  If the second argument is
1182c8e9a2dfSdanielk1977 ** true, then a version of test_function is registered for UTF-8, if the
1183c8e9a2dfSdanielk1977 ** third is true, a version is registered for UTF-16le, if the fourth is
1184c8e9a2dfSdanielk1977 ** true, a UTF-16be version is available.  Previous versions of
1185c8e9a2dfSdanielk1977 ** test_function are deleted.
1186c8e9a2dfSdanielk1977 **
1187c8e9a2dfSdanielk1977 ** The user function is implemented by calling the following TCL script:
1188c8e9a2dfSdanielk1977 **
1189c8e9a2dfSdanielk1977 **   "test_function <enc> <arg>"
1190c8e9a2dfSdanielk1977 **
1191c8e9a2dfSdanielk1977 ** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
1192c8e9a2dfSdanielk1977 ** single argument passed to the SQL function. The value returned by
1193c8e9a2dfSdanielk1977 ** the TCL script is used as the return value of the SQL function. It
1194c8e9a2dfSdanielk1977 ** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
1195c8e9a2dfSdanielk1977 ** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
1196c8e9a2dfSdanielk1977 ** prefers UTF-16BE.
1197c8e9a2dfSdanielk1977 */
11985436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
1199c8e9a2dfSdanielk1977 static void test_function_utf8(
1200c8e9a2dfSdanielk1977   sqlite3_context *pCtx,
1201c8e9a2dfSdanielk1977   int nArg,
1202c8e9a2dfSdanielk1977   sqlite3_value **argv
1203c8e9a2dfSdanielk1977 ){
1204c8e9a2dfSdanielk1977   Tcl_Interp *interp;
1205c8e9a2dfSdanielk1977   Tcl_Obj *pX;
1206c8e9a2dfSdanielk1977   sqlite3_value *pVal;
1207c8e9a2dfSdanielk1977   interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1208c8e9a2dfSdanielk1977   pX = Tcl_NewStringObj("test_function", -1);
1209c8e9a2dfSdanielk1977   Tcl_IncrRefCount(pX);
1210c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
1211c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX,
1212c8e9a2dfSdanielk1977       Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
1213c8e9a2dfSdanielk1977   Tcl_EvalObjEx(interp, pX, 0);
1214c8e9a2dfSdanielk1977   Tcl_DecrRefCount(pX);
1215c8e9a2dfSdanielk1977   sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
1216c8e9a2dfSdanielk1977   pVal = sqlite3ValueNew();
1217c8e9a2dfSdanielk1977   sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1218c8e9a2dfSdanielk1977       SQLITE_UTF8, SQLITE_STATIC);
1219c8e9a2dfSdanielk1977   sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
1220c8e9a2dfSdanielk1977       -1, SQLITE_TRANSIENT);
1221c8e9a2dfSdanielk1977   sqlite3ValueFree(pVal);
1222c8e9a2dfSdanielk1977 }
1223c8e9a2dfSdanielk1977 static void test_function_utf16le(
1224c8e9a2dfSdanielk1977   sqlite3_context *pCtx,
1225c8e9a2dfSdanielk1977   int nArg,
1226c8e9a2dfSdanielk1977   sqlite3_value **argv
1227c8e9a2dfSdanielk1977 ){
1228c8e9a2dfSdanielk1977   Tcl_Interp *interp;
1229c8e9a2dfSdanielk1977   Tcl_Obj *pX;
1230c8e9a2dfSdanielk1977   sqlite3_value *pVal;
1231c8e9a2dfSdanielk1977   interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1232c8e9a2dfSdanielk1977   pX = Tcl_NewStringObj("test_function", -1);
1233c8e9a2dfSdanielk1977   Tcl_IncrRefCount(pX);
1234c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
1235c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX,
1236c8e9a2dfSdanielk1977       Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
1237c8e9a2dfSdanielk1977   Tcl_EvalObjEx(interp, pX, 0);
1238c8e9a2dfSdanielk1977   Tcl_DecrRefCount(pX);
1239c8e9a2dfSdanielk1977   pVal = sqlite3ValueNew();
1240c8e9a2dfSdanielk1977   sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1241c8e9a2dfSdanielk1977       SQLITE_UTF8, SQLITE_STATIC);
1242c8e9a2dfSdanielk1977   sqlite3_result_text(pCtx,sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
1243c8e9a2dfSdanielk1977   sqlite3ValueFree(pVal);
1244c8e9a2dfSdanielk1977 }
1245c8e9a2dfSdanielk1977 static void test_function_utf16be(
1246c8e9a2dfSdanielk1977   sqlite3_context *pCtx,
1247c8e9a2dfSdanielk1977   int nArg,
1248c8e9a2dfSdanielk1977   sqlite3_value **argv
1249c8e9a2dfSdanielk1977 ){
1250c8e9a2dfSdanielk1977   Tcl_Interp *interp;
1251c8e9a2dfSdanielk1977   Tcl_Obj *pX;
1252c8e9a2dfSdanielk1977   sqlite3_value *pVal;
1253c8e9a2dfSdanielk1977   interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1254c8e9a2dfSdanielk1977   pX = Tcl_NewStringObj("test_function", -1);
1255c8e9a2dfSdanielk1977   Tcl_IncrRefCount(pX);
1256c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
1257c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX,
1258c8e9a2dfSdanielk1977       Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
1259c8e9a2dfSdanielk1977   Tcl_EvalObjEx(interp, pX, 0);
1260c8e9a2dfSdanielk1977   Tcl_DecrRefCount(pX);
1261c8e9a2dfSdanielk1977   pVal = sqlite3ValueNew();
1262c8e9a2dfSdanielk1977   sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1263c8e9a2dfSdanielk1977       SQLITE_UTF8, SQLITE_STATIC);
1264c8e9a2dfSdanielk1977   sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
1265c8e9a2dfSdanielk1977       -1, SQLITE_TRANSIENT);
1266c8e9a2dfSdanielk1977   sqlite3ValueFree(pVal);
1267c8e9a2dfSdanielk1977 }
12685436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
1269c8e9a2dfSdanielk1977 static int test_function(
1270c8e9a2dfSdanielk1977   void * clientData,
1271c8e9a2dfSdanielk1977   Tcl_Interp *interp,
1272c8e9a2dfSdanielk1977   int objc,
1273c8e9a2dfSdanielk1977   Tcl_Obj *CONST objv[]
1274c8e9a2dfSdanielk1977 ){
12755436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
1276c8e9a2dfSdanielk1977   sqlite3 *db;
1277c8e9a2dfSdanielk1977   int val;
1278c8e9a2dfSdanielk1977 
1279c8e9a2dfSdanielk1977   if( objc!=5 ) goto bad_args;
1280c8e9a2dfSdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1281c8e9a2dfSdanielk1977 
1282c8e9a2dfSdanielk1977   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
1283c8e9a2dfSdanielk1977   if( val ){
1284c8e9a2dfSdanielk1977     sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
1285c8e9a2dfSdanielk1977         interp, test_function_utf8, 0, 0);
1286c8e9a2dfSdanielk1977   }
1287c8e9a2dfSdanielk1977   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1288c8e9a2dfSdanielk1977   if( val ){
1289c8e9a2dfSdanielk1977     sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
1290c8e9a2dfSdanielk1977         interp, test_function_utf16le, 0, 0);
1291c8e9a2dfSdanielk1977   }
1292c8e9a2dfSdanielk1977   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
1293c8e9a2dfSdanielk1977   if( val ){
1294c8e9a2dfSdanielk1977     sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
1295c8e9a2dfSdanielk1977         interp, test_function_utf16be, 0, 0);
1296c8e9a2dfSdanielk1977   }
1297c8e9a2dfSdanielk1977 
1298c8e9a2dfSdanielk1977   return TCL_OK;
1299c8e9a2dfSdanielk1977 bad_args:
1300c8e9a2dfSdanielk1977   Tcl_AppendResult(interp, "wrong # args: should be \"",
1301c8e9a2dfSdanielk1977       Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
13025436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
1303c8e9a2dfSdanielk1977   return TCL_ERROR;
1304c8e9a2dfSdanielk1977 }
1305c8e9a2dfSdanielk1977 
1306312d6b36Sdanielk1977 /*
1307312d6b36Sdanielk1977 ** Usage:         test_errstr <err code>
1308312d6b36Sdanielk1977 **
1309312d6b36Sdanielk1977 ** Test that the english language string equivalents for sqlite error codes
1310312d6b36Sdanielk1977 ** are sane. The parameter is an integer representing an sqlite error code.
1311312d6b36Sdanielk1977 ** The result is a list of two elements, the string representation of the
1312312d6b36Sdanielk1977 ** error code and the english language explanation.
1313312d6b36Sdanielk1977 */
1314312d6b36Sdanielk1977 static int test_errstr(
1315312d6b36Sdanielk1977   void * clientData,
1316312d6b36Sdanielk1977   Tcl_Interp *interp,
1317312d6b36Sdanielk1977   int objc,
1318312d6b36Sdanielk1977   Tcl_Obj *CONST objv[]
1319312d6b36Sdanielk1977 ){
1320312d6b36Sdanielk1977   char *zCode;
1321312d6b36Sdanielk1977   int i;
1322312d6b36Sdanielk1977   if( objc!=1 ){
1323312d6b36Sdanielk1977     Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
1324312d6b36Sdanielk1977   }
1325312d6b36Sdanielk1977 
1326312d6b36Sdanielk1977   zCode = Tcl_GetString(objv[1]);
1327312d6b36Sdanielk1977   for(i=0; i<200; i++){
1328312d6b36Sdanielk1977     if( 0==strcmp(errorName(i), zCode) ) break;
1329312d6b36Sdanielk1977   }
1330312d6b36Sdanielk1977   Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
1331312d6b36Sdanielk1977   return TCL_OK;
1332312d6b36Sdanielk1977 }
1333312d6b36Sdanielk1977 
1334c8e9a2dfSdanielk1977 static int sqlite3_crashparams(
13358a6c550dSdanielk1977   void * clientData,
13368a6c550dSdanielk1977   Tcl_Interp *interp,
13378a6c550dSdanielk1977   int objc,
13388a6c550dSdanielk1977   Tcl_Obj *CONST objv[]
13398a6c550dSdanielk1977 ){
13408a6c550dSdanielk1977 #ifdef OS_TEST
1341c8e9a2dfSdanielk1977   int delay;
1342c8e9a2dfSdanielk1977   if( objc!=3 ) goto bad_args;
1343c8e9a2dfSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[1], &delay) ) return TCL_ERROR;
1344c8e9a2dfSdanielk1977   sqlite3SetCrashParams(delay, Tcl_GetString(objv[2]));
13458a6c550dSdanielk1977 #endif
13468a6c550dSdanielk1977   return TCL_OK;
13478a6c550dSdanielk1977 
1348241db313Sdrh #ifdef OS_TEST
13498a6c550dSdanielk1977 bad_args:
13508a6c550dSdanielk1977   Tcl_AppendResult(interp, "wrong # args: should be \"",
1351c8e9a2dfSdanielk1977       Tcl_GetStringFromObj(objv[0], 0), "<delay> <filename>", 0);
13528a6c550dSdanielk1977   return TCL_ERROR;
1353241db313Sdrh #endif
13548a6c550dSdanielk1977 }
13558a6c550dSdanielk1977 
13568a6c550dSdanielk1977 
135750457896Sdrh /*
135899ee3600Sdrh ** Usage:    breakpoint
135999ee3600Sdrh **
136099ee3600Sdrh ** This routine exists for one purpose - to provide a place to put a
136199ee3600Sdrh ** breakpoint with GDB that can be triggered using TCL code.  The use
136299ee3600Sdrh ** for this is when a particular test fails on (say) the 1485th iteration.
136399ee3600Sdrh ** In the TCL test script, we can add code like this:
136499ee3600Sdrh **
136599ee3600Sdrh **     if {$i==1485} breakpoint
136699ee3600Sdrh **
136799ee3600Sdrh ** Then run testfixture in the debugger and wait for the breakpoint to
136899ee3600Sdrh ** fire.  Then additional breakpoints can be set to trace down the bug.
136999ee3600Sdrh */
137099ee3600Sdrh static int test_breakpoint(
137199ee3600Sdrh   void *NotUsed,
137299ee3600Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
137399ee3600Sdrh   int argc,              /* Number of arguments */
137499ee3600Sdrh   char **argv            /* Text of each argument */
137599ee3600Sdrh ){
137699ee3600Sdrh   return TCL_OK;         /* Do nothing */
137799ee3600Sdrh }
137899ee3600Sdrh 
1379241db313Sdrh /*
1380241db313Sdrh ** Usage:   sqlite3_bind_int  STMT N VALUE
1381241db313Sdrh **
1382241db313Sdrh ** Test the sqlite3_bind_int interface.  STMT is a prepared statement.
1383241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1384241db313Sdrh ** binds a 32-bit integer VALUE to that wildcard.
1385241db313Sdrh */
1386241db313Sdrh static int test_bind_int(
138751e3d8e2Sdanielk1977   void * clientData,
138851e3d8e2Sdanielk1977   Tcl_Interp *interp,
138951e3d8e2Sdanielk1977   int objc,
139051e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
139151e3d8e2Sdanielk1977 ){
139251e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
139351e3d8e2Sdanielk1977   int idx;
139451e3d8e2Sdanielk1977   int value;
139551e3d8e2Sdanielk1977   int rc;
139651e3d8e2Sdanielk1977 
139751e3d8e2Sdanielk1977   if( objc!=4 ){
139851e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1399241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
140051e3d8e2Sdanielk1977     return TCL_ERROR;
140151e3d8e2Sdanielk1977   }
140251e3d8e2Sdanielk1977 
140351e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
140451e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
140551e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
140651e3d8e2Sdanielk1977 
1407c572ef7fSdanielk1977   rc = sqlite3_bind_int(pStmt, idx, value);
1408c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
140951e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
141051e3d8e2Sdanielk1977     return TCL_ERROR;
141151e3d8e2Sdanielk1977   }
141251e3d8e2Sdanielk1977 
141351e3d8e2Sdanielk1977   return TCL_OK;
141451e3d8e2Sdanielk1977 }
141551e3d8e2Sdanielk1977 
1416241db313Sdrh 
1417241db313Sdrh /*
1418241db313Sdrh ** Usage:   sqlite3_bind_int64  STMT N VALUE
1419241db313Sdrh **
1420241db313Sdrh ** Test the sqlite3_bind_int64 interface.  STMT is a prepared statement.
1421241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1422241db313Sdrh ** binds a 64-bit integer VALUE to that wildcard.
1423241db313Sdrh */
142451e3d8e2Sdanielk1977 static int test_bind_int64(
142551e3d8e2Sdanielk1977   void * clientData,
142651e3d8e2Sdanielk1977   Tcl_Interp *interp,
142751e3d8e2Sdanielk1977   int objc,
142851e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
142951e3d8e2Sdanielk1977 ){
143051e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
143151e3d8e2Sdanielk1977   int idx;
143251e3d8e2Sdanielk1977   i64 value;
143351e3d8e2Sdanielk1977   int rc;
143451e3d8e2Sdanielk1977 
143551e3d8e2Sdanielk1977   if( objc!=4 ){
143651e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1437241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
143851e3d8e2Sdanielk1977     return TCL_ERROR;
143951e3d8e2Sdanielk1977   }
144051e3d8e2Sdanielk1977 
144151e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
144251e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
144351e3d8e2Sdanielk1977   if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
144451e3d8e2Sdanielk1977 
144551e3d8e2Sdanielk1977   rc = sqlite3_bind_int64(pStmt, idx, value);
1446c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
144751e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
144851e3d8e2Sdanielk1977     return TCL_ERROR;
144951e3d8e2Sdanielk1977   }
145051e3d8e2Sdanielk1977 
145151e3d8e2Sdanielk1977   return TCL_OK;
145251e3d8e2Sdanielk1977 }
145351e3d8e2Sdanielk1977 
1454241db313Sdrh 
1455241db313Sdrh /*
1456241db313Sdrh ** Usage:   sqlite3_bind_double  STMT N VALUE
1457241db313Sdrh **
1458241db313Sdrh ** Test the sqlite3_bind_double interface.  STMT is a prepared statement.
1459241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1460241db313Sdrh ** binds a 64-bit integer VALUE to that wildcard.
1461241db313Sdrh */
146251e3d8e2Sdanielk1977 static int test_bind_double(
146351e3d8e2Sdanielk1977   void * clientData,
146451e3d8e2Sdanielk1977   Tcl_Interp *interp,
146551e3d8e2Sdanielk1977   int objc,
146651e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
146751e3d8e2Sdanielk1977 ){
146851e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
146951e3d8e2Sdanielk1977   int idx;
147051e3d8e2Sdanielk1977   double value;
147151e3d8e2Sdanielk1977   int rc;
147251e3d8e2Sdanielk1977 
147351e3d8e2Sdanielk1977   if( objc!=4 ){
147451e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1475241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
147651e3d8e2Sdanielk1977     return TCL_ERROR;
147751e3d8e2Sdanielk1977   }
147851e3d8e2Sdanielk1977 
147951e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
148051e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
148151e3d8e2Sdanielk1977   if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR;
148251e3d8e2Sdanielk1977 
148351e3d8e2Sdanielk1977   rc = sqlite3_bind_double(pStmt, idx, value);
1484c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
148551e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
148651e3d8e2Sdanielk1977     return TCL_ERROR;
148751e3d8e2Sdanielk1977   }
148851e3d8e2Sdanielk1977 
148951e3d8e2Sdanielk1977   return TCL_OK;
149051e3d8e2Sdanielk1977 }
149151e3d8e2Sdanielk1977 
1492241db313Sdrh /*
1493241db313Sdrh ** Usage:   sqlite3_bind_null  STMT N
1494241db313Sdrh **
1495241db313Sdrh ** Test the sqlite3_bind_null interface.  STMT is a prepared statement.
1496241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1497241db313Sdrh ** binds a NULL to the wildcard.
1498241db313Sdrh */
149951e3d8e2Sdanielk1977 static int test_bind_null(
150051e3d8e2Sdanielk1977   void * clientData,
150151e3d8e2Sdanielk1977   Tcl_Interp *interp,
150251e3d8e2Sdanielk1977   int objc,
150351e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
150451e3d8e2Sdanielk1977 ){
150551e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
150651e3d8e2Sdanielk1977   int idx;
150751e3d8e2Sdanielk1977   int rc;
150851e3d8e2Sdanielk1977 
150951e3d8e2Sdanielk1977   if( objc!=3 ){
151051e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1511241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
151251e3d8e2Sdanielk1977     return TCL_ERROR;
151351e3d8e2Sdanielk1977   }
151451e3d8e2Sdanielk1977 
151551e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
151651e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
151751e3d8e2Sdanielk1977 
151851e3d8e2Sdanielk1977   rc = sqlite3_bind_null(pStmt, idx);
1519c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
152051e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
152151e3d8e2Sdanielk1977     return TCL_ERROR;
152251e3d8e2Sdanielk1977   }
152351e3d8e2Sdanielk1977 
152451e3d8e2Sdanielk1977   return TCL_OK;
152551e3d8e2Sdanielk1977 }
152651e3d8e2Sdanielk1977 
1527241db313Sdrh /*
1528241db313Sdrh ** Usage:   sqlite3_bind_text  STMT N STRING BYTES
1529241db313Sdrh **
1530241db313Sdrh ** Test the sqlite3_bind_text interface.  STMT is a prepared statement.
1531241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1532241db313Sdrh ** binds a UTF-8 string STRING to the wildcard.  The string is BYTES bytes
1533241db313Sdrh ** long.
1534241db313Sdrh */
153551e3d8e2Sdanielk1977 static int test_bind_text(
153651e3d8e2Sdanielk1977   void * clientData,
153751e3d8e2Sdanielk1977   Tcl_Interp *interp,
153851e3d8e2Sdanielk1977   int objc,
153951e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
154051e3d8e2Sdanielk1977 ){
154151e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
154251e3d8e2Sdanielk1977   int idx;
154351e3d8e2Sdanielk1977   int bytes;
154451e3d8e2Sdanielk1977   char *value;
154551e3d8e2Sdanielk1977   int rc;
154651e3d8e2Sdanielk1977 
154751e3d8e2Sdanielk1977   if( objc!=5 ){
154851e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1549241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
155051e3d8e2Sdanielk1977     return TCL_ERROR;
155151e3d8e2Sdanielk1977   }
155251e3d8e2Sdanielk1977 
155351e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
155451e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
155551e3d8e2Sdanielk1977   value = Tcl_GetString(objv[3]);
155651e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
155751e3d8e2Sdanielk1977 
1558d8123366Sdanielk1977   rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
1559c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
156051e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
156151e3d8e2Sdanielk1977     return TCL_ERROR;
156251e3d8e2Sdanielk1977   }
156351e3d8e2Sdanielk1977 
156451e3d8e2Sdanielk1977   return TCL_OK;
156551e3d8e2Sdanielk1977 }
156651e3d8e2Sdanielk1977 
1567241db313Sdrh /*
1568241db313Sdrh ** Usage:   sqlite3_bind_text16  STMT N STRING BYTES
1569241db313Sdrh **
1570241db313Sdrh ** Test the sqlite3_bind_text16 interface.  STMT is a prepared statement.
1571241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1572241db313Sdrh ** binds a UTF-16 string STRING to the wildcard.  The string is BYTES bytes
1573241db313Sdrh ** long.
1574241db313Sdrh */
157551e3d8e2Sdanielk1977 static int test_bind_text16(
157651e3d8e2Sdanielk1977   void * clientData,
157751e3d8e2Sdanielk1977   Tcl_Interp *interp,
157851e3d8e2Sdanielk1977   int objc,
157951e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
158051e3d8e2Sdanielk1977 ){
15815436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
158251e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
158351e3d8e2Sdanielk1977   int idx;
158451e3d8e2Sdanielk1977   int bytes;
158551e3d8e2Sdanielk1977   char *value;
158651e3d8e2Sdanielk1977   int rc;
158751e3d8e2Sdanielk1977 
158851e3d8e2Sdanielk1977   if( objc!=5 ){
158951e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1590241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
159151e3d8e2Sdanielk1977     return TCL_ERROR;
159251e3d8e2Sdanielk1977   }
159351e3d8e2Sdanielk1977 
159451e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
159551e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
159651e3d8e2Sdanielk1977   value = Tcl_GetByteArrayFromObj(objv[3], 0);
159751e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
159851e3d8e2Sdanielk1977 
1599d8123366Sdanielk1977   rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, SQLITE_TRANSIENT);
1600c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
160151e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
160251e3d8e2Sdanielk1977     return TCL_ERROR;
160351e3d8e2Sdanielk1977   }
160451e3d8e2Sdanielk1977 
16055436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
160651e3d8e2Sdanielk1977   return TCL_OK;
160751e3d8e2Sdanielk1977 }
160851e3d8e2Sdanielk1977 
1609241db313Sdrh /*
1610241db313Sdrh ** Usage:   sqlite3_bind_blob  STMT N DATA BYTES
1611241db313Sdrh **
1612241db313Sdrh ** Test the sqlite3_bind_blob interface.  STMT is a prepared statement.
1613241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1614241db313Sdrh ** binds a BLOB to the wildcard.  The BLOB is BYTES bytes in size.
1615241db313Sdrh */
161651e3d8e2Sdanielk1977 static int test_bind_blob(
161751e3d8e2Sdanielk1977   void * clientData,
161851e3d8e2Sdanielk1977   Tcl_Interp *interp,
161951e3d8e2Sdanielk1977   int objc,
162051e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
162151e3d8e2Sdanielk1977 ){
162251e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
162351e3d8e2Sdanielk1977   int idx;
162451e3d8e2Sdanielk1977   int bytes;
162551e3d8e2Sdanielk1977   char *value;
162651e3d8e2Sdanielk1977   int rc;
162751e3d8e2Sdanielk1977 
162851e3d8e2Sdanielk1977   if( objc!=5 ){
162951e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1630241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
163151e3d8e2Sdanielk1977     return TCL_ERROR;
163251e3d8e2Sdanielk1977   }
163351e3d8e2Sdanielk1977 
163451e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
163551e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
163651e3d8e2Sdanielk1977   value = Tcl_GetString(objv[3]);
163749e4643eSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
163851e3d8e2Sdanielk1977 
1639d8123366Sdanielk1977   rc = sqlite3_bind_blob(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
1640c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
164151e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
164251e3d8e2Sdanielk1977     return TCL_ERROR;
164351e3d8e2Sdanielk1977   }
164451e3d8e2Sdanielk1977 
164551e3d8e2Sdanielk1977   return TCL_OK;
164651e3d8e2Sdanielk1977 }
164751e3d8e2Sdanielk1977 
164899ee3600Sdrh /*
164975f6a032Sdrh ** Usage:   sqlite3_bind_parameter_count  STMT
165075f6a032Sdrh **
165175f6a032Sdrh ** Return the number of wildcards in the given statement.
165275f6a032Sdrh */
165375f6a032Sdrh static int test_bind_parameter_count(
165475f6a032Sdrh   void * clientData,
165575f6a032Sdrh   Tcl_Interp *interp,
165675f6a032Sdrh   int objc,
165775f6a032Sdrh   Tcl_Obj *CONST objv[]
165875f6a032Sdrh ){
165975f6a032Sdrh   sqlite3_stmt *pStmt;
166075f6a032Sdrh 
166175f6a032Sdrh   if( objc!=2 ){
166275f6a032Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "STMT");
166375f6a032Sdrh     return TCL_ERROR;
166475f6a032Sdrh   }
166575f6a032Sdrh   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
166675f6a032Sdrh   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
166775f6a032Sdrh   return TCL_OK;
166875f6a032Sdrh }
166975f6a032Sdrh 
167075f6a032Sdrh /*
1671895d7472Sdrh ** Usage:   sqlite3_bind_parameter_name  STMT  N
1672895d7472Sdrh **
1673895d7472Sdrh ** Return the name of the Nth wildcard.  The first wildcard is 1.
1674895d7472Sdrh ** An empty string is returned if N is out of range or if the wildcard
1675895d7472Sdrh ** is nameless.
1676895d7472Sdrh */
1677895d7472Sdrh static int test_bind_parameter_name(
1678895d7472Sdrh   void * clientData,
1679895d7472Sdrh   Tcl_Interp *interp,
1680895d7472Sdrh   int objc,
1681895d7472Sdrh   Tcl_Obj *CONST objv[]
1682895d7472Sdrh ){
1683895d7472Sdrh   sqlite3_stmt *pStmt;
1684895d7472Sdrh   int i;
1685895d7472Sdrh 
1686895d7472Sdrh   if( objc!=3 ){
1687895d7472Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
1688895d7472Sdrh     return TCL_ERROR;
1689895d7472Sdrh   }
1690895d7472Sdrh   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1691895d7472Sdrh   if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
1692895d7472Sdrh   Tcl_SetObjResult(interp,
1693895d7472Sdrh      Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
1694895d7472Sdrh   );
1695895d7472Sdrh   return TCL_OK;
1696895d7472Sdrh }
1697895d7472Sdrh 
1698895d7472Sdrh /*
1699fa6bc000Sdrh ** Usage:   sqlite3_bind_parameter_index  STMT  NAME
1700fa6bc000Sdrh **
1701fa6bc000Sdrh ** Return the index of the wildcard called NAME.  Return 0 if there is
1702fa6bc000Sdrh ** no such wildcard.
1703fa6bc000Sdrh */
1704fa6bc000Sdrh static int test_bind_parameter_index(
1705fa6bc000Sdrh   void * clientData,
1706fa6bc000Sdrh   Tcl_Interp *interp,
1707fa6bc000Sdrh   int objc,
1708fa6bc000Sdrh   Tcl_Obj *CONST objv[]
1709fa6bc000Sdrh ){
1710fa6bc000Sdrh   sqlite3_stmt *pStmt;
1711fa6bc000Sdrh 
1712fa6bc000Sdrh   if( objc!=3 ){
1713fa6bc000Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
1714fa6bc000Sdrh     return TCL_ERROR;
1715fa6bc000Sdrh   }
1716fa6bc000Sdrh   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1717fa6bc000Sdrh   Tcl_SetObjResult(interp,
1718fa6bc000Sdrh      Tcl_NewIntObj(
1719fa6bc000Sdrh        sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
1720fa6bc000Sdrh      )
1721fa6bc000Sdrh   );
1722fa6bc000Sdrh   return TCL_OK;
1723fa6bc000Sdrh }
1724fa6bc000Sdrh 
1725fa6bc000Sdrh /*
1726600dd0baSdanielk1977 ** Usage:   sqlite3_clear_bindings STMT
1727600dd0baSdanielk1977 **
1728600dd0baSdanielk1977 */
1729600dd0baSdanielk1977 #if 0
1730600dd0baSdanielk1977 static int test_clear_bindings(
1731600dd0baSdanielk1977   void * clientData,
1732600dd0baSdanielk1977   Tcl_Interp *interp,
1733600dd0baSdanielk1977   int objc,
1734600dd0baSdanielk1977   Tcl_Obj *CONST objv[]
1735600dd0baSdanielk1977 ){
1736600dd0baSdanielk1977   sqlite3_stmt *pStmt;
1737600dd0baSdanielk1977 
1738600dd0baSdanielk1977   if( objc!=2 ){
1739600dd0baSdanielk1977     Tcl_WrongNumArgs(interp, 1, objv, "STMT");
1740600dd0baSdanielk1977     return TCL_ERROR;
1741600dd0baSdanielk1977   }
1742600dd0baSdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1743600dd0baSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
1744600dd0baSdanielk1977   return TCL_OK;
1745600dd0baSdanielk1977 }
1746600dd0baSdanielk1977 #endif
1747600dd0baSdanielk1977 
1748600dd0baSdanielk1977 /*
17496622cce3Sdanielk1977 ** Usage: sqlite3_errcode DB
17506622cce3Sdanielk1977 **
17516622cce3Sdanielk1977 ** Return the string representation of the most recent sqlite3_* API
17526622cce3Sdanielk1977 ** error code. e.g. "SQLITE_ERROR".
17536622cce3Sdanielk1977 */
17546622cce3Sdanielk1977 static int test_errcode(
17556622cce3Sdanielk1977   void * clientData,
17566622cce3Sdanielk1977   Tcl_Interp *interp,
17576622cce3Sdanielk1977   int objc,
17586622cce3Sdanielk1977   Tcl_Obj *CONST objv[]
17596622cce3Sdanielk1977 ){
17606622cce3Sdanielk1977   sqlite3 *db;
17616622cce3Sdanielk1977 
17626622cce3Sdanielk1977   if( objc!=2 ){
17636622cce3Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
17646622cce3Sdanielk1977        Tcl_GetString(objv[0]), " DB", 0);
17656622cce3Sdanielk1977     return TCL_ERROR;
17666622cce3Sdanielk1977   }
17676622cce3Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
17686622cce3Sdanielk1977   Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0);
17696622cce3Sdanielk1977   return TCL_OK;
17706622cce3Sdanielk1977 }
17716622cce3Sdanielk1977 
17726622cce3Sdanielk1977 /*
17736622cce3Sdanielk1977 ** Usage:   test_errmsg DB
17746622cce3Sdanielk1977 **
17756622cce3Sdanielk1977 ** Returns the UTF-8 representation of the error message string for the
17766622cce3Sdanielk1977 ** most recent sqlite3_* API call.
17776622cce3Sdanielk1977 */
17786622cce3Sdanielk1977 static int test_errmsg(
17796622cce3Sdanielk1977   void * clientData,
17806622cce3Sdanielk1977   Tcl_Interp *interp,
17816622cce3Sdanielk1977   int objc,
17826622cce3Sdanielk1977   Tcl_Obj *CONST objv[]
17836622cce3Sdanielk1977 ){
17849bb575fdSdrh   sqlite3 *db;
17856622cce3Sdanielk1977   const char *zErr;
17866622cce3Sdanielk1977 
17876622cce3Sdanielk1977   if( objc!=2 ){
17886622cce3Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
17896622cce3Sdanielk1977        Tcl_GetString(objv[0]), " DB", 0);
17906622cce3Sdanielk1977     return TCL_ERROR;
17916622cce3Sdanielk1977   }
17926622cce3Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
17936622cce3Sdanielk1977 
17946622cce3Sdanielk1977   zErr = sqlite3_errmsg(db);
17956622cce3Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
17966622cce3Sdanielk1977   return TCL_OK;
17976622cce3Sdanielk1977 }
17986622cce3Sdanielk1977 
17996622cce3Sdanielk1977 /*
18006622cce3Sdanielk1977 ** Usage:   test_errmsg16 DB
18016622cce3Sdanielk1977 **
18026622cce3Sdanielk1977 ** Returns the UTF-16 representation of the error message string for the
18036622cce3Sdanielk1977 ** most recent sqlite3_* API call. This is a byte array object at the TCL
18046622cce3Sdanielk1977 ** level, and it includes the 0x00 0x00 terminator bytes at the end of the
18056622cce3Sdanielk1977 ** UTF-16 string.
18066622cce3Sdanielk1977 */
18076622cce3Sdanielk1977 static int test_errmsg16(
18086622cce3Sdanielk1977   void * clientData,
18096622cce3Sdanielk1977   Tcl_Interp *interp,
18106622cce3Sdanielk1977   int objc,
18116622cce3Sdanielk1977   Tcl_Obj *CONST objv[]
18126622cce3Sdanielk1977 ){
18135436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
18149bb575fdSdrh   sqlite3 *db;
18156622cce3Sdanielk1977   const void *zErr;
18166622cce3Sdanielk1977   int bytes;
18176622cce3Sdanielk1977 
18186622cce3Sdanielk1977   if( objc!=2 ){
18196622cce3Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
18206622cce3Sdanielk1977        Tcl_GetString(objv[0]), " DB", 0);
18216622cce3Sdanielk1977     return TCL_ERROR;
18226622cce3Sdanielk1977   }
18236622cce3Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
18246622cce3Sdanielk1977 
18256622cce3Sdanielk1977   zErr = sqlite3_errmsg16(db);
18266622cce3Sdanielk1977   bytes = sqlite3utf16ByteLen(zErr, -1);
18276622cce3Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
18285436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
18296622cce3Sdanielk1977   return TCL_OK;
18306622cce3Sdanielk1977 }
18316622cce3Sdanielk1977 
18326622cce3Sdanielk1977 /*
18336622cce3Sdanielk1977 ** Usage: sqlite3_prepare DB sql bytes tailvar
18346622cce3Sdanielk1977 **
18356622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
18366622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global
18376622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A
18386622cce3Sdanielk1977 ** STMT handle is returned.
18396622cce3Sdanielk1977 */
18406622cce3Sdanielk1977 static int test_prepare(
18416622cce3Sdanielk1977   void * clientData,
18426622cce3Sdanielk1977   Tcl_Interp *interp,
18436622cce3Sdanielk1977   int objc,
18446622cce3Sdanielk1977   Tcl_Obj *CONST objv[]
18456622cce3Sdanielk1977 ){
18466622cce3Sdanielk1977   sqlite3 *db;
18476622cce3Sdanielk1977   const char *zSql;
18486622cce3Sdanielk1977   int bytes;
18496622cce3Sdanielk1977   const char *zTail = 0;
18506622cce3Sdanielk1977   sqlite3_stmt *pStmt = 0;
18516622cce3Sdanielk1977   char zBuf[50];
18524ad1713cSdanielk1977   int rc;
18536622cce3Sdanielk1977 
18546622cce3Sdanielk1977   if( objc!=5 ){
18556622cce3Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
18566622cce3Sdanielk1977        Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
18576622cce3Sdanielk1977     return TCL_ERROR;
18586622cce3Sdanielk1977   }
18596622cce3Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
18606622cce3Sdanielk1977   zSql = Tcl_GetString(objv[2]);
18616622cce3Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
18626622cce3Sdanielk1977 
18634ad1713cSdanielk1977   rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail);
1864c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
18656622cce3Sdanielk1977   if( zTail ){
18666622cce3Sdanielk1977     if( bytes>=0 ){
18676622cce3Sdanielk1977       bytes = bytes - (zTail-zSql);
18686622cce3Sdanielk1977     }
18696622cce3Sdanielk1977     Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
18706622cce3Sdanielk1977   }
18714ad1713cSdanielk1977   if( rc!=SQLITE_OK ){
18724ad1713cSdanielk1977     assert( pStmt==0 );
18734ad1713cSdanielk1977     sprintf(zBuf, "(%d) ", rc);
18744ad1713cSdanielk1977     Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
18754ad1713cSdanielk1977     return TCL_ERROR;
18764ad1713cSdanielk1977   }
18776622cce3Sdanielk1977 
18784ad1713cSdanielk1977   if( pStmt ){
18796622cce3Sdanielk1977     if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
18806622cce3Sdanielk1977     Tcl_AppendResult(interp, zBuf, 0);
18814ad1713cSdanielk1977   }
18826622cce3Sdanielk1977   return TCL_OK;
18836622cce3Sdanielk1977 }
18846622cce3Sdanielk1977 
18856622cce3Sdanielk1977 /*
18866622cce3Sdanielk1977 ** Usage: sqlite3_prepare DB sql bytes tailvar
18876622cce3Sdanielk1977 **
18886622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
18896622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global
18906622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A
18916622cce3Sdanielk1977 ** STMT handle is returned.
18926622cce3Sdanielk1977 */
18936622cce3Sdanielk1977 static int test_prepare16(
18946622cce3Sdanielk1977   void * clientData,
18956622cce3Sdanielk1977   Tcl_Interp *interp,
18966622cce3Sdanielk1977   int objc,
18976622cce3Sdanielk1977   Tcl_Obj *CONST objv[]
18986622cce3Sdanielk1977 ){
18995436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
19006622cce3Sdanielk1977   sqlite3 *db;
19016622cce3Sdanielk1977   const void *zSql;
19026622cce3Sdanielk1977   const void *zTail = 0;
19036622cce3Sdanielk1977   Tcl_Obj *pTail = 0;
19046622cce3Sdanielk1977   sqlite3_stmt *pStmt = 0;
19056622cce3Sdanielk1977   char zBuf[50];
1906c60d0446Sdrh   int rc;
19076622cce3Sdanielk1977   int bytes;                /* The integer specified as arg 3 */
19086622cce3Sdanielk1977   int objlen;               /* The byte-array length of arg 2 */
19096622cce3Sdanielk1977 
19106622cce3Sdanielk1977   if( objc!=5 ){
19116622cce3Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
19126622cce3Sdanielk1977        Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
19136622cce3Sdanielk1977     return TCL_ERROR;
19146622cce3Sdanielk1977   }
19156622cce3Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
19166622cce3Sdanielk1977   zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
19176622cce3Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
19186622cce3Sdanielk1977 
1919c60d0446Sdrh   rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail);
1920c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
1921c60d0446Sdrh   if( rc ){
19226622cce3Sdanielk1977     return TCL_ERROR;
19236622cce3Sdanielk1977   }
19246622cce3Sdanielk1977 
19256622cce3Sdanielk1977   if( zTail ){
19266622cce3Sdanielk1977     objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
19276622cce3Sdanielk1977   }else{
19286622cce3Sdanielk1977     objlen = 0;
19296622cce3Sdanielk1977   }
19306622cce3Sdanielk1977   pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
19316622cce3Sdanielk1977   Tcl_IncrRefCount(pTail);
19326622cce3Sdanielk1977   Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
19334ad1713cSdanielk1977   Tcl_DecrRefCount(pTail);
19346622cce3Sdanielk1977 
19354ad1713cSdanielk1977   if( pStmt ){
19366622cce3Sdanielk1977     if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
19374ad1713cSdanielk1977   }
19386622cce3Sdanielk1977   Tcl_AppendResult(interp, zBuf, 0);
19395436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
19406622cce3Sdanielk1977   return TCL_OK;
19416622cce3Sdanielk1977 }
19426622cce3Sdanielk1977 
19434ad1713cSdanielk1977 /*
19444ad1713cSdanielk1977 ** Usage: sqlite3_open filename ?options-list?
19454ad1713cSdanielk1977 */
19464ad1713cSdanielk1977 static int test_open(
19474ad1713cSdanielk1977   void * clientData,
19484ad1713cSdanielk1977   Tcl_Interp *interp,
19494ad1713cSdanielk1977   int objc,
19504ad1713cSdanielk1977   Tcl_Obj *CONST objv[]
19514ad1713cSdanielk1977 ){
19524ad1713cSdanielk1977   const char *zFilename;
19534ad1713cSdanielk1977   sqlite3 *db;
19544ad1713cSdanielk1977   int rc;
19554ad1713cSdanielk1977   char zBuf[100];
19564ad1713cSdanielk1977 
19574ad1713cSdanielk1977   if( objc!=3 && objc!=2 ){
19584ad1713cSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
19594ad1713cSdanielk1977        Tcl_GetString(objv[0]), " filename options-list", 0);
19604ad1713cSdanielk1977     return TCL_ERROR;
19614ad1713cSdanielk1977   }
19624ad1713cSdanielk1977 
19634ad1713cSdanielk1977   zFilename = Tcl_GetString(objv[1]);
19644f057f90Sdanielk1977   rc = sqlite3_open(zFilename, &db);
19654ad1713cSdanielk1977 
19664ad1713cSdanielk1977   if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
19674ad1713cSdanielk1977   Tcl_AppendResult(interp, zBuf, 0);
19684ad1713cSdanielk1977   return TCL_OK;
19694ad1713cSdanielk1977 }
19704ad1713cSdanielk1977 
19714ad1713cSdanielk1977 /*
19724ad1713cSdanielk1977 ** Usage: sqlite3_open16 filename options
19734ad1713cSdanielk1977 */
19744ad1713cSdanielk1977 static int test_open16(
19754ad1713cSdanielk1977   void * clientData,
19764ad1713cSdanielk1977   Tcl_Interp *interp,
19774ad1713cSdanielk1977   int objc,
19784ad1713cSdanielk1977   Tcl_Obj *CONST objv[]
19794ad1713cSdanielk1977 ){
19805436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
19814ad1713cSdanielk1977   const void *zFilename;
19824ad1713cSdanielk1977   sqlite3 *db;
19834ad1713cSdanielk1977   int rc;
19844ad1713cSdanielk1977   char zBuf[100];
19854ad1713cSdanielk1977 
19864ad1713cSdanielk1977   if( objc!=3 ){
19874ad1713cSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
19884ad1713cSdanielk1977        Tcl_GetString(objv[0]), " filename options-list", 0);
19894ad1713cSdanielk1977     return TCL_ERROR;
19904ad1713cSdanielk1977   }
19914ad1713cSdanielk1977 
19924ad1713cSdanielk1977   zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
19934f057f90Sdanielk1977   rc = sqlite3_open16(zFilename, &db);
19944ad1713cSdanielk1977 
19954ad1713cSdanielk1977   if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
19964ad1713cSdanielk1977   Tcl_AppendResult(interp, zBuf, 0);
19975436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
19984ad1713cSdanielk1977   return TCL_OK;
19994ad1713cSdanielk1977 }
2000d3d39e93Sdrh 
2001d3d39e93Sdrh /*
2002bc6ada41Sdanielk1977 ** Usage: sqlite3_complete16 <UTF-16 string>
2003bc6ada41Sdanielk1977 **
2004bc6ada41Sdanielk1977 ** Return 1 if the supplied argument is a complete SQL statement, or zero
2005bc6ada41Sdanielk1977 ** otherwise.
2006bc6ada41Sdanielk1977 */
2007bc6ada41Sdanielk1977 static int test_complete16(
2008bc6ada41Sdanielk1977   void * clientData,
2009bc6ada41Sdanielk1977   Tcl_Interp *interp,
2010bc6ada41Sdanielk1977   int objc,
2011bc6ada41Sdanielk1977   Tcl_Obj *CONST objv[]
2012bc6ada41Sdanielk1977 ){
20135436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
2014bc6ada41Sdanielk1977   char *zBuf;
2015bc6ada41Sdanielk1977 
2016bc6ada41Sdanielk1977   if( objc!=2 ){
2017bc6ada41Sdanielk1977     Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
2018bc6ada41Sdanielk1977     return TCL_ERROR;
2019bc6ada41Sdanielk1977   }
2020bc6ada41Sdanielk1977 
2021bc6ada41Sdanielk1977   zBuf = Tcl_GetByteArrayFromObj(objv[1], 0);
2022bc6ada41Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
20235436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
2024bc6ada41Sdanielk1977   return TCL_OK;
2025bc6ada41Sdanielk1977 }
2026bc6ada41Sdanielk1977 
2027bc6ada41Sdanielk1977 /*
2028106bb236Sdanielk1977 ** Usage: sqlite3_step STMT
2029106bb236Sdanielk1977 **
2030106bb236Sdanielk1977 ** Advance the statement to the next row.
2031106bb236Sdanielk1977 */
203217240fd9Sdanielk1977 static int test_step(
2033106bb236Sdanielk1977   void * clientData,
2034106bb236Sdanielk1977   Tcl_Interp *interp,
2035106bb236Sdanielk1977   int objc,
2036106bb236Sdanielk1977   Tcl_Obj *CONST objv[]
2037106bb236Sdanielk1977 ){
2038106bb236Sdanielk1977   sqlite3_stmt *pStmt;
2039106bb236Sdanielk1977   int rc;
2040106bb236Sdanielk1977 
2041e1cd9874Sdanielk1977   if( objc!=2 ){
2042106bb236Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
2043106bb236Sdanielk1977        Tcl_GetString(objv[0]), " STMT", 0);
2044106bb236Sdanielk1977     return TCL_ERROR;
2045106bb236Sdanielk1977   }
2046106bb236Sdanielk1977 
2047106bb236Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
204817240fd9Sdanielk1977   rc = sqlite3_step(pStmt);
2049106bb236Sdanielk1977 
2050fbcd585fSdanielk1977   /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
20516590493dSdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), 0);
2052e1cd9874Sdanielk1977   return TCL_OK;
2053e1cd9874Sdanielk1977 }
2054e1cd9874Sdanielk1977 
2055e1cd9874Sdanielk1977 /*
205617240fd9Sdanielk1977 ** Usage: sqlite3_column_count STMT
205717240fd9Sdanielk1977 **
205817240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT.
205917240fd9Sdanielk1977 */
206017240fd9Sdanielk1977 static int test_column_count(
206117240fd9Sdanielk1977   void * clientData,
206217240fd9Sdanielk1977   Tcl_Interp *interp,
206317240fd9Sdanielk1977   int objc,
206417240fd9Sdanielk1977   Tcl_Obj *CONST objv[]
206517240fd9Sdanielk1977 ){
206617240fd9Sdanielk1977   sqlite3_stmt *pStmt;
206717240fd9Sdanielk1977 
206817240fd9Sdanielk1977   if( objc!=2 ){
206917240fd9Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
207017240fd9Sdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
207117240fd9Sdanielk1977     return TCL_ERROR;
207217240fd9Sdanielk1977   }
207317240fd9Sdanielk1977 
207417240fd9Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
207517240fd9Sdanielk1977 
207617240fd9Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
207717240fd9Sdanielk1977   return TCL_OK;
207817240fd9Sdanielk1977 }
207917240fd9Sdanielk1977 
208017240fd9Sdanielk1977 /*
20813cf86063Sdanielk1977 ** Usage: sqlite3_column_type STMT column
20823cf86063Sdanielk1977 **
20833cf86063Sdanielk1977 ** Return the type of the data in column 'column' of the current row.
20843cf86063Sdanielk1977 */
20853cf86063Sdanielk1977 static int test_column_type(
20863cf86063Sdanielk1977   void * clientData,
20873cf86063Sdanielk1977   Tcl_Interp *interp,
20883cf86063Sdanielk1977   int objc,
20893cf86063Sdanielk1977   Tcl_Obj *CONST objv[]
20903cf86063Sdanielk1977 ){
20913cf86063Sdanielk1977   sqlite3_stmt *pStmt;
20923cf86063Sdanielk1977   int col;
20933cf86063Sdanielk1977   int tp;
20943cf86063Sdanielk1977 
20953cf86063Sdanielk1977   if( objc!=3 ){
20963cf86063Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
20973cf86063Sdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
20983cf86063Sdanielk1977     return TCL_ERROR;
20993cf86063Sdanielk1977   }
21003cf86063Sdanielk1977 
21013cf86063Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
21023cf86063Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
21033cf86063Sdanielk1977 
21043cf86063Sdanielk1977   tp = sqlite3_column_type(pStmt, col);
21053cf86063Sdanielk1977   switch( tp ){
21069c054830Sdrh     case SQLITE_INTEGER:
21073cf86063Sdanielk1977       Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
21083cf86063Sdanielk1977       break;
21099c054830Sdrh     case SQLITE_NULL:
21103cf86063Sdanielk1977       Tcl_SetResult(interp, "NULL", TCL_STATIC);
21113cf86063Sdanielk1977       break;
21129c054830Sdrh     case SQLITE_FLOAT:
21133cf86063Sdanielk1977       Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
21143cf86063Sdanielk1977       break;
21159c054830Sdrh     case SQLITE_TEXT:
21163cf86063Sdanielk1977       Tcl_SetResult(interp, "TEXT", TCL_STATIC);
21173cf86063Sdanielk1977       break;
21189c054830Sdrh     case SQLITE_BLOB:
21193cf86063Sdanielk1977       Tcl_SetResult(interp, "BLOB", TCL_STATIC);
21203cf86063Sdanielk1977       break;
21213cf86063Sdanielk1977     default:
21223cf86063Sdanielk1977       assert(0);
21233cf86063Sdanielk1977   }
21243cf86063Sdanielk1977 
21253cf86063Sdanielk1977   return TCL_OK;
21263cf86063Sdanielk1977 }
21273cf86063Sdanielk1977 
21283cf86063Sdanielk1977 /*
212904f2e68dSdanielk1977 ** Usage: sqlite3_column_int64 STMT column
21303cf86063Sdanielk1977 **
21313cf86063Sdanielk1977 ** Return the data in column 'column' of the current row cast as an
213204f2e68dSdanielk1977 ** wide (64-bit) integer.
21333cf86063Sdanielk1977 */
213404f2e68dSdanielk1977 static int test_column_int64(
21353cf86063Sdanielk1977   void * clientData,
21363cf86063Sdanielk1977   Tcl_Interp *interp,
21373cf86063Sdanielk1977   int objc,
21383cf86063Sdanielk1977   Tcl_Obj *CONST objv[]
21393cf86063Sdanielk1977 ){
21403cf86063Sdanielk1977   sqlite3_stmt *pStmt;
21413cf86063Sdanielk1977   int col;
214204f2e68dSdanielk1977   i64 iVal;
21433cf86063Sdanielk1977 
21443cf86063Sdanielk1977   if( objc!=3 ){
21453cf86063Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
21463cf86063Sdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
21473cf86063Sdanielk1977     return TCL_ERROR;
21483cf86063Sdanielk1977   }
21493cf86063Sdanielk1977 
21503cf86063Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
21513cf86063Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
21523cf86063Sdanielk1977 
215304f2e68dSdanielk1977   iVal = sqlite3_column_int64(pStmt, col);
215404f2e68dSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
215504f2e68dSdanielk1977   return TCL_OK;
215604f2e68dSdanielk1977 }
215704f2e68dSdanielk1977 
215804f2e68dSdanielk1977 /*
2159ea61b2c4Sdanielk1977 ** Usage: sqlite3_column_blob STMT column
2160ea61b2c4Sdanielk1977 */
2161ea61b2c4Sdanielk1977 static int test_column_blob(
2162ea61b2c4Sdanielk1977   void * clientData,
2163ea61b2c4Sdanielk1977   Tcl_Interp *interp,
2164ea61b2c4Sdanielk1977   int objc,
2165ea61b2c4Sdanielk1977   Tcl_Obj *CONST objv[]
2166ea61b2c4Sdanielk1977 ){
2167ea61b2c4Sdanielk1977   sqlite3_stmt *pStmt;
2168ea61b2c4Sdanielk1977   int col;
2169ea61b2c4Sdanielk1977 
2170ea61b2c4Sdanielk1977   int len;
2171c572ef7fSdanielk1977   const void *pBlob;
2172ea61b2c4Sdanielk1977 
2173ea61b2c4Sdanielk1977   if( objc!=3 ){
2174ea61b2c4Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
2175ea61b2c4Sdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
2176ea61b2c4Sdanielk1977     return TCL_ERROR;
2177ea61b2c4Sdanielk1977   }
2178ea61b2c4Sdanielk1977 
2179ea61b2c4Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2180ea61b2c4Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2181ea61b2c4Sdanielk1977 
2182ea61b2c4Sdanielk1977   pBlob = sqlite3_column_blob(pStmt, col);
2183ea61b2c4Sdanielk1977   len = sqlite3_column_bytes(pStmt, col);
2184ea61b2c4Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
2185ea61b2c4Sdanielk1977   return TCL_OK;
2186ea61b2c4Sdanielk1977 }
2187ea61b2c4Sdanielk1977 
2188ea61b2c4Sdanielk1977 /*
218904f2e68dSdanielk1977 ** Usage: sqlite3_column_double STMT column
219004f2e68dSdanielk1977 **
219104f2e68dSdanielk1977 ** Return the data in column 'column' of the current row cast as a double.
219204f2e68dSdanielk1977 */
219304f2e68dSdanielk1977 static int test_column_double(
219404f2e68dSdanielk1977   void * clientData,
219504f2e68dSdanielk1977   Tcl_Interp *interp,
219604f2e68dSdanielk1977   int objc,
219704f2e68dSdanielk1977   Tcl_Obj *CONST objv[]
219804f2e68dSdanielk1977 ){
219904f2e68dSdanielk1977   sqlite3_stmt *pStmt;
220004f2e68dSdanielk1977   int col;
220104f2e68dSdanielk1977   double rVal;
220204f2e68dSdanielk1977 
220304f2e68dSdanielk1977   if( objc!=3 ){
220404f2e68dSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
220504f2e68dSdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
220604f2e68dSdanielk1977     return TCL_ERROR;
220704f2e68dSdanielk1977   }
220804f2e68dSdanielk1977 
220904f2e68dSdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
221004f2e68dSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
221104f2e68dSdanielk1977 
221204f2e68dSdanielk1977   rVal = sqlite3_column_double(pStmt, col);
2213c572ef7fSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
22143cf86063Sdanielk1977   return TCL_OK;
22153cf86063Sdanielk1977 }
22163cf86063Sdanielk1977 
22173cf86063Sdanielk1977 /*
221817240fd9Sdanielk1977 ** Usage: sqlite3_data_count STMT
221917240fd9Sdanielk1977 **
222017240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT.
222117240fd9Sdanielk1977 */
222217240fd9Sdanielk1977 static int test_data_count(
222317240fd9Sdanielk1977   void * clientData,
222417240fd9Sdanielk1977   Tcl_Interp *interp,
222517240fd9Sdanielk1977   int objc,
222617240fd9Sdanielk1977   Tcl_Obj *CONST objv[]
222717240fd9Sdanielk1977 ){
222817240fd9Sdanielk1977   sqlite3_stmt *pStmt;
222917240fd9Sdanielk1977 
223017240fd9Sdanielk1977   if( objc!=2 ){
223117240fd9Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
223217240fd9Sdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
223317240fd9Sdanielk1977     return TCL_ERROR;
223417240fd9Sdanielk1977   }
223517240fd9Sdanielk1977 
223617240fd9Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
223717240fd9Sdanielk1977 
223817240fd9Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
223917240fd9Sdanielk1977   return TCL_OK;
224017240fd9Sdanielk1977 }
224117240fd9Sdanielk1977 
224217240fd9Sdanielk1977 /*
224304f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column
224404f2e68dSdanielk1977 **
224504f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column
224604f2e68dSdanielk1977 **
224704f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column
224804f2e68dSdanielk1977 */
224904f2e68dSdanielk1977 static int test_stmt_utf8(
2250241db313Sdrh   void * clientData,        /* Pointer to SQLite API function to be invoke */
225104f2e68dSdanielk1977   Tcl_Interp *interp,
225204f2e68dSdanielk1977   int objc,
225304f2e68dSdanielk1977   Tcl_Obj *CONST objv[]
225404f2e68dSdanielk1977 ){
225504f2e68dSdanielk1977   sqlite3_stmt *pStmt;
225604f2e68dSdanielk1977   int col;
2257c572ef7fSdanielk1977   const char *(*xFunc)(sqlite3_stmt*, int) = clientData;
2258f93bbbeaSdanielk1977   const char *zRet;
225904f2e68dSdanielk1977 
226004f2e68dSdanielk1977   if( objc!=3 ){
226104f2e68dSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
226204f2e68dSdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
226304f2e68dSdanielk1977     return TCL_ERROR;
226404f2e68dSdanielk1977   }
226504f2e68dSdanielk1977 
226604f2e68dSdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
226704f2e68dSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2268f93bbbeaSdanielk1977   zRet = xFunc(pStmt, col);
2269f93bbbeaSdanielk1977   if( zRet ){
2270f93bbbeaSdanielk1977     Tcl_SetResult(interp, (char *)zRet, 0);
2271f93bbbeaSdanielk1977   }
227204f2e68dSdanielk1977   return TCL_OK;
227304f2e68dSdanielk1977 }
227404f2e68dSdanielk1977 
227504f2e68dSdanielk1977 /*
227604f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column
227704f2e68dSdanielk1977 **
227804f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column
227904f2e68dSdanielk1977 **
228004f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column
228104f2e68dSdanielk1977 */
228204f2e68dSdanielk1977 static int test_stmt_utf16(
2283241db313Sdrh   void * clientData,     /* Pointer to SQLite API function to be invoked */
228404f2e68dSdanielk1977   Tcl_Interp *interp,
228504f2e68dSdanielk1977   int objc,
228604f2e68dSdanielk1977   Tcl_Obj *CONST objv[]
228704f2e68dSdanielk1977 ){
22885436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
228904f2e68dSdanielk1977   sqlite3_stmt *pStmt;
229004f2e68dSdanielk1977   int col;
229104f2e68dSdanielk1977   Tcl_Obj *pRet;
229204f2e68dSdanielk1977   const void *zName16;
2293c572ef7fSdanielk1977   const void *(*xFunc)(sqlite3_stmt*, int) = clientData;
229404f2e68dSdanielk1977 
229504f2e68dSdanielk1977   if( objc!=3 ){
229604f2e68dSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
229704f2e68dSdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
229804f2e68dSdanielk1977     return TCL_ERROR;
229904f2e68dSdanielk1977   }
230004f2e68dSdanielk1977 
230104f2e68dSdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
230204f2e68dSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
230304f2e68dSdanielk1977 
230404f2e68dSdanielk1977   zName16 = xFunc(pStmt, col);
2305f93bbbeaSdanielk1977   if( zName16 ){
230604f2e68dSdanielk1977     pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2);
230704f2e68dSdanielk1977     Tcl_SetObjResult(interp, pRet);
2308f93bbbeaSdanielk1977   }
23095436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
231004f2e68dSdanielk1977 
231104f2e68dSdanielk1977   return TCL_OK;
231204f2e68dSdanielk1977 }
231304f2e68dSdanielk1977 
231404f2e68dSdanielk1977 /*
231504f2e68dSdanielk1977 ** Usage: sqlite3_column_int STMT column
231604f2e68dSdanielk1977 **
231704f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes STMT column
231804f2e68dSdanielk1977 **
231904f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes16 STMT column
232004f2e68dSdanielk1977 **
232104f2e68dSdanielk1977 */
232204f2e68dSdanielk1977 static int test_stmt_int(
2323241db313Sdrh   void * clientData,    /* Pointer to SQLite API function to be invoked */
232404f2e68dSdanielk1977   Tcl_Interp *interp,
232504f2e68dSdanielk1977   int objc,
232604f2e68dSdanielk1977   Tcl_Obj *CONST objv[]
232704f2e68dSdanielk1977 ){
232804f2e68dSdanielk1977   sqlite3_stmt *pStmt;
232904f2e68dSdanielk1977   int col;
2330c572ef7fSdanielk1977   int (*xFunc)(sqlite3_stmt*, int) = clientData;
233104f2e68dSdanielk1977 
233204f2e68dSdanielk1977   if( objc!=3 ){
233304f2e68dSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
233404f2e68dSdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
233504f2e68dSdanielk1977     return TCL_ERROR;
233604f2e68dSdanielk1977   }
233704f2e68dSdanielk1977 
233804f2e68dSdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
233904f2e68dSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
234004f2e68dSdanielk1977 
234104f2e68dSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
234204f2e68dSdanielk1977   return TCL_OK;
234304f2e68dSdanielk1977 }
234404f2e68dSdanielk1977 
23459a1d0abeSdanielk1977 /*
23469a1d0abeSdanielk1977 ** Usage:  sqlite3OsOpenReadWrite <filename>
23479a1d0abeSdanielk1977 */
23489a1d0abeSdanielk1977 static int test_sqlite3OsOpenReadWrite(
23499a1d0abeSdanielk1977   void * clientData,
23509a1d0abeSdanielk1977   Tcl_Interp *interp,
23519a1d0abeSdanielk1977   int objc,
23529a1d0abeSdanielk1977   Tcl_Obj *CONST objv[]
23539a1d0abeSdanielk1977 ){
23549a1d0abeSdanielk1977   OsFile * pFile;
23559a1d0abeSdanielk1977   int rc;
23569a1d0abeSdanielk1977   int dummy;
23579a1d0abeSdanielk1977   char zBuf[100];
235804f2e68dSdanielk1977 
23599a1d0abeSdanielk1977   if( objc!=2 ){
23609a1d0abeSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
23619a1d0abeSdanielk1977        Tcl_GetString(objv[0]), " filename", 0);
23629a1d0abeSdanielk1977     return TCL_ERROR;
23639a1d0abeSdanielk1977   }
23649a1d0abeSdanielk1977 
23659a1d0abeSdanielk1977   pFile = sqliteMalloc(sizeof(OsFile));
23669a1d0abeSdanielk1977   rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), pFile, &dummy);
23679a1d0abeSdanielk1977   if( rc!=SQLITE_OK ){
23689a1d0abeSdanielk1977     sqliteFree(pFile);
23699a1d0abeSdanielk1977     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
23709a1d0abeSdanielk1977     return TCL_ERROR;
23719a1d0abeSdanielk1977   }
23729a1d0abeSdanielk1977   makePointerStr(interp, zBuf, pFile);
23739a1d0abeSdanielk1977   Tcl_SetResult(interp, zBuf, 0);
23749a1d0abeSdanielk1977   return TCL_ERROR;
23759a1d0abeSdanielk1977 }
23769a1d0abeSdanielk1977 
23779a1d0abeSdanielk1977 /*
23789a1d0abeSdanielk1977 ** Usage:  sqlite3OsClose <file handle>
23799a1d0abeSdanielk1977 */
23809a1d0abeSdanielk1977 static int test_sqlite3OsClose(
23819a1d0abeSdanielk1977   void * clientData,
23829a1d0abeSdanielk1977   Tcl_Interp *interp,
23839a1d0abeSdanielk1977   int objc,
23849a1d0abeSdanielk1977   Tcl_Obj *CONST objv[]
23859a1d0abeSdanielk1977 ){
23869a1d0abeSdanielk1977   OsFile * pFile;
23879a1d0abeSdanielk1977   int rc;
23889a1d0abeSdanielk1977 
23899a1d0abeSdanielk1977   if( objc!=2 ){
23909a1d0abeSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
23919a1d0abeSdanielk1977        Tcl_GetString(objv[0]), " filehandle", 0);
23929a1d0abeSdanielk1977     return TCL_ERROR;
23939a1d0abeSdanielk1977   }
23949a1d0abeSdanielk1977 
23959a1d0abeSdanielk1977   if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
23969a1d0abeSdanielk1977     return TCL_ERROR;
23979a1d0abeSdanielk1977   }
23989a1d0abeSdanielk1977   rc = sqlite3OsClose(pFile);
23999a1d0abeSdanielk1977   if( rc!=SQLITE_OK ){
24009a1d0abeSdanielk1977     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
24019a1d0abeSdanielk1977     return TCL_ERROR;
24029a1d0abeSdanielk1977   }
24039a1d0abeSdanielk1977   sqliteFree(pFile);
24049a1d0abeSdanielk1977   return TCL_OK;
24059a1d0abeSdanielk1977 }
24069a1d0abeSdanielk1977 
24079a1d0abeSdanielk1977 /*
24089a1d0abeSdanielk1977 ** Usage:  sqlite3OsLock <file handle> <locktype>
24099a1d0abeSdanielk1977 */
24109a1d0abeSdanielk1977 static int test_sqlite3OsLock(
24119a1d0abeSdanielk1977   void * clientData,
24129a1d0abeSdanielk1977   Tcl_Interp *interp,
24139a1d0abeSdanielk1977   int objc,
24149a1d0abeSdanielk1977   Tcl_Obj *CONST objv[]
24159a1d0abeSdanielk1977 ){
24169a1d0abeSdanielk1977   OsFile * pFile;
24179a1d0abeSdanielk1977   int rc;
24189a1d0abeSdanielk1977 
24199a1d0abeSdanielk1977   if( objc!=3 ){
24209a1d0abeSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
24219a1d0abeSdanielk1977         Tcl_GetString(objv[0]),
24229a1d0abeSdanielk1977         " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
24239a1d0abeSdanielk1977     return TCL_ERROR;
24249a1d0abeSdanielk1977   }
24259a1d0abeSdanielk1977 
24269a1d0abeSdanielk1977   if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
24279a1d0abeSdanielk1977     return TCL_ERROR;
24289a1d0abeSdanielk1977   }
24299a1d0abeSdanielk1977 
24309a1d0abeSdanielk1977   if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){
24319a1d0abeSdanielk1977     rc = sqlite3OsLock(pFile, SHARED_LOCK);
24329a1d0abeSdanielk1977   }
24339a1d0abeSdanielk1977   else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){
24349a1d0abeSdanielk1977     rc = sqlite3OsLock(pFile, RESERVED_LOCK);
24359a1d0abeSdanielk1977   }
24369a1d0abeSdanielk1977   else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){
24379a1d0abeSdanielk1977     rc = sqlite3OsLock(pFile, PENDING_LOCK);
24389a1d0abeSdanielk1977   }
24399a1d0abeSdanielk1977   else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){
24409a1d0abeSdanielk1977     rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK);
24419a1d0abeSdanielk1977   }else{
24429a1d0abeSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
24439a1d0abeSdanielk1977         Tcl_GetString(objv[0]),
24449a1d0abeSdanielk1977         " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
24459a1d0abeSdanielk1977     return TCL_ERROR;
24469a1d0abeSdanielk1977   }
24479a1d0abeSdanielk1977 
24489a1d0abeSdanielk1977   if( rc!=SQLITE_OK ){
24499a1d0abeSdanielk1977     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
24509a1d0abeSdanielk1977     return TCL_ERROR;
24519a1d0abeSdanielk1977   }
24529a1d0abeSdanielk1977   return TCL_OK;
24539a1d0abeSdanielk1977 }
24549a1d0abeSdanielk1977 
24559a1d0abeSdanielk1977 /*
24569a1d0abeSdanielk1977 ** Usage:  sqlite3OsUnlock <file handle>
24579a1d0abeSdanielk1977 */
24589a1d0abeSdanielk1977 static int test_sqlite3OsUnlock(
24599a1d0abeSdanielk1977   void * clientData,
24609a1d0abeSdanielk1977   Tcl_Interp *interp,
24619a1d0abeSdanielk1977   int objc,
24629a1d0abeSdanielk1977   Tcl_Obj *CONST objv[]
24639a1d0abeSdanielk1977 ){
24649a1d0abeSdanielk1977   OsFile * pFile;
24659a1d0abeSdanielk1977   int rc;
24669a1d0abeSdanielk1977 
24679a1d0abeSdanielk1977   if( objc!=2 ){
24689a1d0abeSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
24699a1d0abeSdanielk1977        Tcl_GetString(objv[0]), " filehandle", 0);
24709a1d0abeSdanielk1977     return TCL_ERROR;
24719a1d0abeSdanielk1977   }
24729a1d0abeSdanielk1977 
24739a1d0abeSdanielk1977   if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
24749a1d0abeSdanielk1977     return TCL_ERROR;
24759a1d0abeSdanielk1977   }
2476a6abd041Sdrh   rc = sqlite3OsUnlock(pFile, NO_LOCK);
24779a1d0abeSdanielk1977   if( rc!=SQLITE_OK ){
24789a1d0abeSdanielk1977     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
24799a1d0abeSdanielk1977     return TCL_ERROR;
24809a1d0abeSdanielk1977   }
24819a1d0abeSdanielk1977   return TCL_OK;
24829a1d0abeSdanielk1977 }
2483d3d39e93Sdrh 
2484ab3f9feaSdrh /*
2485ab3f9feaSdrh ** Usage:  sqlite3OsTempFileName
2486ab3f9feaSdrh */
2487ab3f9feaSdrh static int test_sqlite3OsTempFileName(
2488ab3f9feaSdrh   void * clientData,
2489ab3f9feaSdrh   Tcl_Interp *interp,
2490ab3f9feaSdrh   int objc,
2491ab3f9feaSdrh   Tcl_Obj *CONST objv[]
2492ab3f9feaSdrh ){
2493ab3f9feaSdrh   char zFile[SQLITE_TEMPNAME_SIZE];
2494ab3f9feaSdrh   int rc;
2495ab3f9feaSdrh 
2496ab3f9feaSdrh   rc = sqlite3OsTempFileName(zFile);
2497ab3f9feaSdrh   if( rc!=SQLITE_OK ){
2498ab3f9feaSdrh     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2499ab3f9feaSdrh     return TCL_ERROR;
2500ab3f9feaSdrh   }
2501ab3f9feaSdrh   Tcl_AppendResult(interp, zFile, 0);
2502ab3f9feaSdrh   return TCL_OK;
2503ab3f9feaSdrh }
2504d8123366Sdanielk1977 
25056622cce3Sdanielk1977 /*
2506cacb208eSdrh ** Usage:  sqlite_set_magic  DB  MAGIC-NUMBER
2507cacb208eSdrh **
2508cacb208eSdrh ** Set the db->magic value.  This is used to test error recovery logic.
2509cacb208eSdrh */
2510cacb208eSdrh static int sqlite_set_magic(
2511cacb208eSdrh   void * clientData,
2512cacb208eSdrh   Tcl_Interp *interp,
2513cacb208eSdrh   int argc,
2514cacb208eSdrh   char **argv
2515cacb208eSdrh ){
2516cacb208eSdrh   sqlite3 *db;
2517cacb208eSdrh   if( argc!=3 ){
2518cacb208eSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2519cacb208eSdrh          " DB MAGIC", 0);
2520cacb208eSdrh     return TCL_ERROR;
2521cacb208eSdrh   }
2522cacb208eSdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2523cacb208eSdrh   if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
2524cacb208eSdrh     db->magic = SQLITE_MAGIC_OPEN;
2525cacb208eSdrh   }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
2526cacb208eSdrh     db->magic = SQLITE_MAGIC_CLOSED;
2527cacb208eSdrh   }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
2528cacb208eSdrh     db->magic = SQLITE_MAGIC_BUSY;
2529cacb208eSdrh   }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
2530cacb208eSdrh     db->magic = SQLITE_MAGIC_ERROR;
2531cacb208eSdrh   }else if( Tcl_GetInt(interp, argv[2], &db->magic) ){
2532cacb208eSdrh     return TCL_ERROR;
2533cacb208eSdrh   }
2534cacb208eSdrh   return TCL_OK;
2535cacb208eSdrh }
2536cacb208eSdrh 
2537cacb208eSdrh /*
2538c5cdca61Sdrh ** Usage:  sqlite3_interrupt  DB
2539c5cdca61Sdrh **
2540c5cdca61Sdrh ** Trigger an interrupt on DB
2541c5cdca61Sdrh */
2542c5cdca61Sdrh static int test_interrupt(
2543c5cdca61Sdrh   void * clientData,
2544c5cdca61Sdrh   Tcl_Interp *interp,
2545c5cdca61Sdrh   int argc,
2546c5cdca61Sdrh   char **argv
2547c5cdca61Sdrh ){
2548c5cdca61Sdrh   sqlite3 *db;
2549c5cdca61Sdrh   if( argc!=2 ){
2550c5cdca61Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
2551c5cdca61Sdrh     return TCL_ERROR;
2552c5cdca61Sdrh   }
2553c5cdca61Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2554c5cdca61Sdrh   sqlite3_interrupt(db);
2555c5cdca61Sdrh   return TCL_OK;
2556c5cdca61Sdrh }
2557c5cdca61Sdrh 
2558c5cdca61Sdrh /*
2559600dd0baSdanielk1977 ** Usage:  sqlite3_sleep ms
2560600dd0baSdanielk1977 **
2561600dd0baSdanielk1977 ** Sleep for the specified number of ms.
2562600dd0baSdanielk1977 */
2563600dd0baSdanielk1977 #if 0
2564600dd0baSdanielk1977 static int test_sleep(
2565600dd0baSdanielk1977   void * clientData,
2566600dd0baSdanielk1977   Tcl_Interp *interp,
2567600dd0baSdanielk1977   int argc,
2568600dd0baSdanielk1977   char **argv
2569600dd0baSdanielk1977 ){
2570600dd0baSdanielk1977   sqlite3 *db;
2571600dd0baSdanielk1977   if( argc!=2 ){
2572600dd0baSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ms", 0);
2573600dd0baSdanielk1977     return TCL_ERROR;
2574600dd0baSdanielk1977   }
2575600dd0baSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(atoi(argv[1]))));
2576600dd0baSdanielk1977   return TCL_OK;
2577600dd0baSdanielk1977 }
2578600dd0baSdanielk1977 #endif
2579600dd0baSdanielk1977 
2580600dd0baSdanielk1977 /*
258192febd92Sdrh ** Usage:  tcl_variable_type VARIABLENAME
258292febd92Sdrh **
258392febd92Sdrh ** Return the name of the internal representation for the
258492febd92Sdrh ** value of the given variable.
258592febd92Sdrh */
258692febd92Sdrh static int tcl_variable_type(
258792febd92Sdrh   void * clientData,
258892febd92Sdrh   Tcl_Interp *interp,
258992febd92Sdrh   int objc,
259092febd92Sdrh   Tcl_Obj *CONST objv[]
259192febd92Sdrh ){
259292febd92Sdrh   Tcl_Obj *pVar;
259392febd92Sdrh   if( objc!=2 ){
259492febd92Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
259592febd92Sdrh     return TCL_ERROR;
259692febd92Sdrh   }
259792febd92Sdrh   pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
259892febd92Sdrh   if( pVar==0 ) return TCL_ERROR;
259992febd92Sdrh   if( pVar->typePtr ){
260092febd92Sdrh     Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
260192febd92Sdrh   }
260292febd92Sdrh   return TCL_OK;
260392febd92Sdrh }
260492febd92Sdrh 
260592febd92Sdrh /*
260627d258a3Sdrh ** This routine sets entries in the global ::sqlite_options() array variable
260727d258a3Sdrh ** according to the compile-time configuration of the database.  Test
260827d258a3Sdrh ** procedures use this to determine when tests should be omitted.
260927d258a3Sdrh */
261027d258a3Sdrh static void set_options(Tcl_Interp *interp){
26111c8c23ccSdanielk1977 #ifdef SQLITE_OMIT_ALTERTABLE
26121c8c23ccSdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "altertable", "0", TCL_GLOBAL_ONLY);
26131c8c23ccSdanielk1977 #else
26141c8c23ccSdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "altertable", "1", TCL_GLOBAL_ONLY);
26151c8c23ccSdanielk1977 #endif
261613d7042aSdrh 
261713d7042aSdrh #ifdef SQLITE_OMIT_AUTHORIZATION
261813d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "auth", "0", TCL_GLOBAL_ONLY);
261913d7042aSdrh #else
262013d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "auth", "1", TCL_GLOBAL_ONLY);
262113d7042aSdrh #endif
262213d7042aSdrh 
2623f3388144Sdrh #ifdef SQLITE_OMIT_AUTOINCREMENT
2624f3388144Sdrh   Tcl_SetVar2(interp, "sqlite_options", "autoinc", "0", TCL_GLOBAL_ONLY);
2625f3388144Sdrh #else
2626f3388144Sdrh   Tcl_SetVar2(interp, "sqlite_options", "autoinc", "1", TCL_GLOBAL_ONLY);
2627f3388144Sdrh #endif
2628f3388144Sdrh 
262945901d62Sdanielk1977 #ifdef SQLITE_OMIT_AUTOVACUUM
263045901d62Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "0", TCL_GLOBAL_ONLY);
263145901d62Sdanielk1977 #else
263245901d62Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "1", TCL_GLOBAL_ONLY);
2633f3388144Sdrh #endif /* SQLITE_OMIT_AUTOVACUUM */
26344d36b81eSdanielk1977 #if !defined(SQLITE_DEFAULT_AUTOVACUUM) || SQLITE_DEFAULT_AUTOVACUUM==0
263545901d62Sdanielk1977   Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","0",TCL_GLOBAL_ONLY);
263645901d62Sdanielk1977 #else
263745901d62Sdanielk1977   Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","1",TCL_GLOBAL_ONLY);
263845901d62Sdanielk1977 #endif
263913d7042aSdrh 
264013d7042aSdrh #ifdef SQLITE_OMIT_BLOB_LITERAL
264113d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "bloblit", "0", TCL_GLOBAL_ONLY);
264213d7042aSdrh #else
264313d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY);
264413d7042aSdrh #endif
264513d7042aSdrh 
264613d7042aSdrh #ifdef SQLITE_OMIT_COMPOUND_SELECT
264713d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "compound", "0", TCL_GLOBAL_ONLY);
264813d7042aSdrh #else
264913d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "compound", "1", TCL_GLOBAL_ONLY);
265013d7042aSdrh #endif
265113d7042aSdrh 
265213d7042aSdrh #ifdef SQLITE_OMIT_CONFLICT_CLAUSE
265313d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "conflict", "0", TCL_GLOBAL_ONLY);
265413d7042aSdrh #else
265513d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY);
265613d7042aSdrh #endif
265713d7042aSdrh 
2658b6c29897Sdrh #ifdef SQLITE_OMIT_CURSOR
2659b6c29897Sdrh   Tcl_SetVar2(interp, "sqlite_options", "cursor", "0", TCL_GLOBAL_ONLY);
2660b6c29897Sdrh #else
2661b6c29897Sdrh   Tcl_SetVar2(interp, "sqlite_options", "cursor", "1", TCL_GLOBAL_ONLY);
2662b6c29897Sdrh #endif
2663b6c29897Sdrh 
266413d7042aSdrh #ifdef SQLITE_OMIT_DATETIME_FUNCS
266513d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY);
266613d7042aSdrh #else
266713d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY);
266813d7042aSdrh #endif
266913d7042aSdrh 
267013d7042aSdrh #ifdef SQLITE_OMIT_EXPLAIN
267113d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "explain", "0", TCL_GLOBAL_ONLY);
267213d7042aSdrh #else
267313d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "explain", "1", TCL_GLOBAL_ONLY);
267413d7042aSdrh #endif
267513d7042aSdrh 
267613d7042aSdrh #ifdef SQLITE_OMIT_FLOATING_POINT
267713d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "0", TCL_GLOBAL_ONLY);
267813d7042aSdrh #else
267913d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "1", TCL_GLOBAL_ONLY);
268013d7042aSdrh #endif
268113d7042aSdrh 
268213d7042aSdrh #ifdef SQLITE_OMIT_FOREIGN_KEY
268313d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "0", TCL_GLOBAL_ONLY);
268413d7042aSdrh #else
268513d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "1", TCL_GLOBAL_ONLY);
268613d7042aSdrh #endif
268713d7042aSdrh 
268813d7042aSdrh #ifdef SQLITE_OMIT_INTEGRITY_CHECK
268913d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
269013d7042aSdrh #else
269113d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "integrityck", "1", TCL_GLOBAL_ONLY);
269213d7042aSdrh #endif
269313d7042aSdrh 
269413d7042aSdrh #ifdef SQLITE_OMIT_MEMORYDB
269513d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY);
269613d7042aSdrh #else
269713d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "memorydb", "1", TCL_GLOBAL_ONLY);
269813d7042aSdrh #endif
269913d7042aSdrh 
270013d7042aSdrh #ifdef SQLITE_OMIT_PAGER_PRAGMAS
270113d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY);
270213d7042aSdrh #else
270313d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "1", TCL_GLOBAL_ONLY);
270413d7042aSdrh #endif
270513d7042aSdrh 
270613d7042aSdrh #ifdef SQLITE_OMIT_PRAGMA
270713d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "pragma", "0", TCL_GLOBAL_ONLY);
270813d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
270913d7042aSdrh #else
271013d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "pragma", "1", TCL_GLOBAL_ONLY);
271113d7042aSdrh #endif
271213d7042aSdrh 
271313d7042aSdrh #ifdef SQLITE_OMIT_PROGRESS_CALLBACK
271413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "progress", "0", TCL_GLOBAL_ONLY);
271513d7042aSdrh #else
271613d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY);
271713d7042aSdrh #endif
271813d7042aSdrh 
271913d7042aSdrh #ifdef SQLITE_OMIT_REINDEX
272013d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "reindex", "0", TCL_GLOBAL_ONLY);
272113d7042aSdrh #else
272213d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "reindex", "1", TCL_GLOBAL_ONLY);
272313d7042aSdrh #endif
272413d7042aSdrh 
272513d7042aSdrh #ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
272613d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "0", TCL_GLOBAL_ONLY);
272713d7042aSdrh #else
272813d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "1", TCL_GLOBAL_ONLY);
272913d7042aSdrh #endif
273013d7042aSdrh 
273113d7042aSdrh #ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
273213d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "schema_version", "0", TCL_GLOBAL_ONLY);
273313d7042aSdrh #else
273413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY);
273513d7042aSdrh #endif
273613d7042aSdrh 
2737*3e8c37e7Sdanielk1977 #ifdef SQLITE_OMIT_SUBQUERY
2738*3e8c37e7Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "subquery", "0", TCL_GLOBAL_ONLY);
2739*3e8c37e7Sdanielk1977 #else
2740*3e8c37e7Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "subquery", "1", TCL_GLOBAL_ONLY);
2741*3e8c37e7Sdanielk1977 #endif
2742*3e8c37e7Sdanielk1977 
274313d7042aSdrh #ifdef SQLITE_OMIT_TCL_VARIABLE
274413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY);
274513d7042aSdrh #else
274613d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY);
274713d7042aSdrh #endif
274813d7042aSdrh 
274913d7042aSdrh #if defined(THREADSAFE) && THREADSAFE
275013d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY);
275113d7042aSdrh #else
275213d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "0", TCL_GLOBAL_ONLY);
275313d7042aSdrh #endif
275413d7042aSdrh 
275513d7042aSdrh #ifdef SQLITE_OMIT_TRIGGER
275613d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "trigger", "0", TCL_GLOBAL_ONLY);
275713d7042aSdrh #else
275813d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "trigger", "1", TCL_GLOBAL_ONLY);
275913d7042aSdrh #endif
276013d7042aSdrh 
276113d7042aSdrh #ifdef SQLITE_OMIT_UTF16
276213d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY);
276313d7042aSdrh #else
276413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "utf16", "1", TCL_GLOBAL_ONLY);
276513d7042aSdrh #endif
276613d7042aSdrh 
276713d7042aSdrh #ifdef SQLITE_OMIT_VACUUM
276813d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "vacuum", "0", TCL_GLOBAL_ONLY);
276913d7042aSdrh #else
277013d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "vacuum", "1", TCL_GLOBAL_ONLY);
277113d7042aSdrh #endif
277213d7042aSdrh 
277313d7042aSdrh #ifdef SQLITE_OMIT_VIEW
277413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "view", "0", TCL_GLOBAL_ONLY);
277513d7042aSdrh #else
277613d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "view", "1", TCL_GLOBAL_ONLY);
277713d7042aSdrh #endif
277827d258a3Sdrh }
277927d258a3Sdrh 
278027d258a3Sdrh /*
2781d1bf3512Sdrh ** Register commands with the TCL interpreter.
2782d1bf3512Sdrh */
2783d1bf3512Sdrh int Sqlitetest1_Init(Tcl_Interp *interp){
27846f8a503dSdanielk1977   extern int sqlite3_search_count;
27856f8a503dSdanielk1977   extern int sqlite3_interrupt_count;
27866f8a503dSdanielk1977   extern int sqlite3_open_file_count;
27876bf89570Sdrh   extern int sqlite3_sort_count;
27886f8a503dSdanielk1977   extern int sqlite3_current_time;
2789c2eef3b3Sdrh   static struct {
2790c2eef3b3Sdrh      char *zName;
2791c2eef3b3Sdrh      Tcl_CmdProc *xProc;
2792c2eef3b3Sdrh   } aCmd[] = {
27936f8a503dSdanielk1977      { "sqlite3_mprintf_int",           (Tcl_CmdProc*)sqlite3_mprintf_int    },
2794e9707671Sdrh      { "sqlite3_mprintf_int64",         (Tcl_CmdProc*)sqlite3_mprintf_int64  },
27956f8a503dSdanielk1977      { "sqlite3_mprintf_str",           (Tcl_CmdProc*)sqlite3_mprintf_str    },
2796e29b1a05Sdrh      { "sqlite3_mprintf_stronly",       (Tcl_CmdProc*)sqlite3_mprintf_stronly},
27976f8a503dSdanielk1977      { "sqlite3_mprintf_double",        (Tcl_CmdProc*)sqlite3_mprintf_double },
27986f8a503dSdanielk1977      { "sqlite3_mprintf_scaled",        (Tcl_CmdProc*)sqlite3_mprintf_scaled },
27996f8a503dSdanielk1977      { "sqlite3_mprintf_z_test",        (Tcl_CmdProc*)test_mprintf_z        },
28006f8a503dSdanielk1977      { "sqlite3_last_insert_rowid",     (Tcl_CmdProc*)test_last_rowid       },
28016f8a503dSdanielk1977      { "sqlite3_exec_printf",           (Tcl_CmdProc*)test_exec_printf      },
28026f8a503dSdanielk1977      { "sqlite3_get_table_printf",      (Tcl_CmdProc*)test_get_table_printf },
28036f8a503dSdanielk1977      { "sqlite3_close",                 (Tcl_CmdProc*)sqlite_test_close     },
28046f8a503dSdanielk1977      { "sqlite3_create_function",       (Tcl_CmdProc*)test_create_function  },
28056f8a503dSdanielk1977      { "sqlite3_create_aggregate",      (Tcl_CmdProc*)test_create_aggregate },
2806c2eef3b3Sdrh      { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func    },
2807c2eef3b3Sdrh      { "sqlite_abort",                  (Tcl_CmdProc*)sqlite_abort          },
28082c336549Sdanielk1977 #ifdef SQLITE_MEMDEBUG
2809c2eef3b3Sdrh      { "sqlite_malloc_fail",            (Tcl_CmdProc*)sqlite_malloc_fail    },
2810c2eef3b3Sdrh      { "sqlite_malloc_stat",            (Tcl_CmdProc*)sqlite_malloc_stat    },
2811c2eef3b3Sdrh #endif
281296fc5fe6Sdanielk1977      { "sqlite_bind",                   (Tcl_CmdProc*)test_bind             },
281399ee3600Sdrh      { "breakpoint",                    (Tcl_CmdProc*)test_breakpoint       },
281425d6543dSdrh      { "sqlite3_key",                   (Tcl_CmdProc*)test_key              },
281525d6543dSdrh      { "sqlite3_rekey",                 (Tcl_CmdProc*)test_rekey            },
2816cacb208eSdrh      { "sqlite_set_magic",              (Tcl_CmdProc*)sqlite_set_magic      },
2817c5cdca61Sdrh      { "sqlite3_interrupt",             (Tcl_CmdProc*)test_interrupt        },
2818600dd0baSdanielk1977 #if 0
2819600dd0baSdanielk1977      { "sqlite3_sleep",                 (Tcl_CmdProc*)test_sleep            },
2820600dd0baSdanielk1977 #endif
2821c2eef3b3Sdrh   };
282251e3d8e2Sdanielk1977   static struct {
282351e3d8e2Sdanielk1977      char *zName;
282451e3d8e2Sdanielk1977      Tcl_ObjCmdProc *xProc;
282504f2e68dSdanielk1977      void *clientData;
282651e3d8e2Sdanielk1977   } aObjCmd[] = {
2827241db313Sdrh      { "sqlite3_bind_int",              test_bind_int,      0 },
282804f2e68dSdanielk1977      { "sqlite3_bind_int64",            test_bind_int64,    0 },
282904f2e68dSdanielk1977      { "sqlite3_bind_double",           test_bind_double,   0 },
283004f2e68dSdanielk1977      { "sqlite3_bind_null",             test_bind_null     ,0 },
283104f2e68dSdanielk1977      { "sqlite3_bind_text",             test_bind_text     ,0 },
283204f2e68dSdanielk1977      { "sqlite3_bind_text16",           test_bind_text16   ,0 },
283304f2e68dSdanielk1977      { "sqlite3_bind_blob",             test_bind_blob     ,0 },
283475f6a032Sdrh      { "sqlite3_bind_parameter_count",  test_bind_parameter_count, 0},
2835895d7472Sdrh      { "sqlite3_bind_parameter_name",   test_bind_parameter_name,  0},
2836fa6bc000Sdrh      { "sqlite3_bind_parameter_index",  test_bind_parameter_index, 0},
2837600dd0baSdanielk1977 #if 0
2838600dd0baSdanielk1977      { "sqlite3_clear_bindings",        test_clear_bindings, 0},
2839600dd0baSdanielk1977 #endif
284004f2e68dSdanielk1977      { "sqlite3_errcode",               test_errcode       ,0 },
284104f2e68dSdanielk1977      { "sqlite3_errmsg",                test_errmsg        ,0 },
284204f2e68dSdanielk1977      { "sqlite3_errmsg16",              test_errmsg16      ,0 },
284304f2e68dSdanielk1977      { "sqlite3_open",                  test_open          ,0 },
284404f2e68dSdanielk1977      { "sqlite3_open16",                test_open16        ,0 },
2845bc6ada41Sdanielk1977      { "sqlite3_complete16",            test_complete16    ,0 },
284604f2e68dSdanielk1977 
284704f2e68dSdanielk1977      { "sqlite3_prepare",               test_prepare       ,0 },
284804f2e68dSdanielk1977      { "sqlite3_prepare16",             test_prepare16     ,0 },
284904f2e68dSdanielk1977      { "sqlite3_finalize",              test_finalize      ,0 },
285004f2e68dSdanielk1977      { "sqlite3_reset",                 test_reset         ,0 },
2851fbcd585fSdanielk1977      { "sqlite3_changes",               test_changes       ,0 },
285204f2e68dSdanielk1977      { "sqlite3_step",                  test_step          ,0 },
285304f2e68dSdanielk1977 
285404f2e68dSdanielk1977      /* sqlite3_column_*() API */
285504f2e68dSdanielk1977      { "sqlite3_column_count",          test_column_count  ,0 },
285604f2e68dSdanielk1977      { "sqlite3_data_count",            test_data_count    ,0 },
285704f2e68dSdanielk1977      { "sqlite3_column_type",           test_column_type   ,0 },
2858ea61b2c4Sdanielk1977      { "sqlite3_column_blob",           test_column_blob   ,0 },
285904f2e68dSdanielk1977      { "sqlite3_column_double",         test_column_double ,0 },
286004f2e68dSdanielk1977      { "sqlite3_column_int64",          test_column_int64  ,0 },
286104f2e68dSdanielk1977      { "sqlite3_column_text",       test_stmt_utf8,  sqlite3_column_text      },
286204f2e68dSdanielk1977      { "sqlite3_column_decltype",   test_stmt_utf8,  sqlite3_column_decltype  },
286304f2e68dSdanielk1977      { "sqlite3_column_name",       test_stmt_utf8,  sqlite3_column_name      },
28646c62608fSdrh      { "sqlite3_column_int",        test_stmt_int,   sqlite3_column_int       },
28656c62608fSdrh      { "sqlite3_column_bytes",      test_stmt_int,   sqlite3_column_bytes     },
28666c62608fSdrh #ifndef SQLITE_OMIT_UTF16
28676c62608fSdrh      { "sqlite3_column_bytes16",    test_stmt_int,   sqlite3_column_bytes16   },
286804f2e68dSdanielk1977      { "sqlite3_column_text16",     test_stmt_utf16, sqlite3_column_text16    },
286904f2e68dSdanielk1977      { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16},
287004f2e68dSdanielk1977      { "sqlite3_column_name16",     test_stmt_utf16, sqlite3_column_name16    },
28716c62608fSdrh #endif
287204f2e68dSdanielk1977 
28739a1d0abeSdanielk1977      /* Functions from os.h */
28749a1d0abeSdanielk1977      { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
28759a1d0abeSdanielk1977      { "sqlite3OsClose",        test_sqlite3OsClose, 0 },
28769a1d0abeSdanielk1977      { "sqlite3OsLock",         test_sqlite3OsLock, 0 },
2877ab3f9feaSdrh      { "sqlite3OsTempFileName", test_sqlite3OsTempFileName, 0 },
2878312d6b36Sdanielk1977 
2879312d6b36Sdanielk1977      /* Custom test interfaces */
28809a1d0abeSdanielk1977      { "sqlite3OsUnlock",         test_sqlite3OsUnlock, 0    },
28815436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
28824e6af134Sdanielk1977      { "add_test_collate",        test_collate, 0            },
2883312d6b36Sdanielk1977      { "add_test_collate_needed", test_collate_needed, 0     },
2884c8e9a2dfSdanielk1977      { "add_test_function",       test_function, 0           },
28855436dc2dSdrh #endif
2886c8e9a2dfSdanielk1977      { "sqlite3_crashparams",     sqlite3_crashparams, 0     },
2887312d6b36Sdanielk1977      { "sqlite3_test_errstr",     test_errstr, 0             },
288892febd92Sdrh      { "tcl_variable_type",       tcl_variable_type, 0       },
288951e3d8e2Sdanielk1977   };
28901398ad36Sdrh   static int bitmask_size = sizeof(Bitmask)*8;
2891c2eef3b3Sdrh   int i;
28922ac3ee97Sdrh   extern int sqlite3_os_trace;
2893c2eef3b3Sdrh 
28941398ad36Sdrh 
2895c2eef3b3Sdrh   for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
2896c2eef3b3Sdrh     Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
2897c2eef3b3Sdrh   }
289851e3d8e2Sdanielk1977   for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
2899c572ef7fSdanielk1977     Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
2900c572ef7fSdanielk1977         aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
290151e3d8e2Sdanielk1977   }
29026490bebdSdanielk1977   Tcl_LinkVar(interp, "sqlite_search_count",
29036f8a503dSdanielk1977       (char*)&sqlite3_search_count, TCL_LINK_INT);
29046bf89570Sdrh   Tcl_LinkVar(interp, "sqlite_sort_count",
29056bf89570Sdrh       (char*)&sqlite3_sort_count, TCL_LINK_INT);
29066490bebdSdanielk1977   Tcl_LinkVar(interp, "sqlite_interrupt_count",
29076f8a503dSdanielk1977       (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
29086490bebdSdanielk1977   Tcl_LinkVar(interp, "sqlite_open_file_count",
29096f8a503dSdanielk1977       (char*)&sqlite3_open_file_count, TCL_LINK_INT);
29106490bebdSdanielk1977   Tcl_LinkVar(interp, "sqlite_current_time",
29116f8a503dSdanielk1977       (char*)&sqlite3_current_time, TCL_LINK_INT);
29122ac3ee97Sdrh   Tcl_LinkVar(interp, "sqlite_os_trace",
29132ac3ee97Sdrh       (char*)&sqlite3_os_trace, TCL_LINK_INT);
29147c972decSdrh   Tcl_LinkVar(interp, "sqlite_static_bind_value",
29157c972decSdrh       (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
2916ab3f9feaSdrh   Tcl_LinkVar(interp, "sqlite_temp_directory",
2917effd02bcSdrh       (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
29181398ad36Sdrh   Tcl_LinkVar(interp, "bitmask_size",
29191398ad36Sdrh       (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
292027d258a3Sdrh   set_options(interp);
2921d1bf3512Sdrh   return TCL_OK;
2922d1bf3512Sdrh }
2923