xref: /sqlite-3.40.0/src/test1.c (revision 9f18e8a0)
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*9f18e8a0Sdrh ** $Id: test1.c,v 1.147 2005/07/08 12:13:05 drh Exp $
17d1bf3512Sdrh */
18d1bf3512Sdrh #include "sqliteInt.h"
19d1bf3512Sdrh #include "tcl.h"
2094e92032Sdrh #include "os.h"
21d1bf3512Sdrh #include <stdlib.h>
22d1bf3512Sdrh #include <string.h>
23d1bf3512Sdrh 
242e66f0b9Sdrh const char *sqlite3TestErrorName(int rc){
256622cce3Sdanielk1977   const char *zName = 0;
266622cce3Sdanielk1977   switch( rc ){
276622cce3Sdanielk1977     case SQLITE_OK:         zName = "SQLITE_OK";          break;
286622cce3Sdanielk1977     case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break;
296622cce3Sdanielk1977     case SQLITE_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 }
602e66f0b9Sdrh #define errorName sqlite3TestErrorName
616622cce3Sdanielk1977 
62d1bf3512Sdrh /*
63c60d0446Sdrh ** Convert an sqlite3_stmt* into an sqlite3*.  This depends on the
64c60d0446Sdrh ** fact that the sqlite3* is the first field in the Vdbe structure.
65c60d0446Sdrh */
6651942bc3Sdrh #define StmtToDb(X)   sqlite3_db_handle(X)
67c60d0446Sdrh 
68c60d0446Sdrh /*
69c60d0446Sdrh ** Check a return value to make sure it agrees with the results
70c60d0446Sdrh ** from sqlite3_errcode.
71c60d0446Sdrh */
72c60d0446Sdrh int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
73c60d0446Sdrh   if( rc!=SQLITE_MISUSE && rc!=SQLITE_OK && sqlite3_errcode(db)!=rc ){
74c60d0446Sdrh     char zBuf[200];
75c60d0446Sdrh     int r2 = sqlite3_errcode(db);
76c60d0446Sdrh     sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)",
77c60d0446Sdrh        errorName(rc), rc, errorName(r2), r2);
78c60d0446Sdrh     Tcl_ResetResult(interp);
79c60d0446Sdrh     Tcl_AppendResult(interp, zBuf, 0);
80c60d0446Sdrh     return 1;
81c60d0446Sdrh   }
82c60d0446Sdrh   return 0;
83c60d0446Sdrh }
84c60d0446Sdrh 
85c60d0446Sdrh /*
869bb575fdSdrh ** Decode a pointer to an sqlite3 object.
87b86ccfb2Sdrh */
889bb575fdSdrh static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
89fe63d1c9Sdrh   *ppDb = (sqlite3*)sqlite3TextToPtr(zA);
90b86ccfb2Sdrh   return TCL_OK;
91b86ccfb2Sdrh }
92b86ccfb2Sdrh 
93b86ccfb2Sdrh /*
9451e3d8e2Sdanielk1977 ** Decode a pointer to an sqlite3_stmt object.
9551e3d8e2Sdanielk1977 */
9651e3d8e2Sdanielk1977 static int getStmtPointer(
9751e3d8e2Sdanielk1977   Tcl_Interp *interp,
9851e3d8e2Sdanielk1977   const char *zArg,
9951e3d8e2Sdanielk1977   sqlite3_stmt **ppStmt
10051e3d8e2Sdanielk1977 ){
101fe63d1c9Sdrh   *ppStmt = (sqlite3_stmt*)sqlite3TextToPtr(zArg);
10251e3d8e2Sdanielk1977   return TCL_OK;
10351e3d8e2Sdanielk1977 }
10451e3d8e2Sdanielk1977 
10551e3d8e2Sdanielk1977 /*
1069a1d0abeSdanielk1977 ** Decode a pointer to an sqlite3_stmt object.
1079a1d0abeSdanielk1977 */
1089a1d0abeSdanielk1977 static int getFilePointer(
1099a1d0abeSdanielk1977   Tcl_Interp *interp,
1109a1d0abeSdanielk1977   const char *zArg,
1119a1d0abeSdanielk1977   OsFile **ppFile
1129a1d0abeSdanielk1977 ){
113fe63d1c9Sdrh   *ppFile = (OsFile*)sqlite3TextToPtr(zArg);
1149a1d0abeSdanielk1977   return TCL_OK;
1159a1d0abeSdanielk1977 }
1169a1d0abeSdanielk1977 
1179a1d0abeSdanielk1977 /*
1187d8085a8Sdrh ** Generate a text representation of a pointer that can be understood
1197d8085a8Sdrh ** by the getDbPointer and getVmPointer routines above.
1207d8085a8Sdrh **
1217d8085a8Sdrh ** The problem is, on some machines (Solaris) if you do a printf with
1227d8085a8Sdrh ** "%p" you cannot turn around and do a scanf with the same "%p" and
1237d8085a8Sdrh ** get your pointer back.  You have to prepend a "0x" before it will
1247d8085a8Sdrh ** work.  Or at least that is what is reported to me (drh).  But this
1257d8085a8Sdrh ** behavior varies from machine to machine.  The solution used her is
1267d8085a8Sdrh ** to test the string right after it is generated to see if it can be
1277d8085a8Sdrh ** understood by scanf, and if not, try prepending an "0x" to see if
1287d8085a8Sdrh ** that helps.  If nothing works, a fatal error is generated.
1297d8085a8Sdrh */
1307d8085a8Sdrh static int makePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
131fe63d1c9Sdrh   sqlite3_snprintf(100, zPtr, "%p", p);
1327d8085a8Sdrh   return TCL_OK;
1337d8085a8Sdrh }
1347d8085a8Sdrh 
1357d8085a8Sdrh /*
1366f8a503dSdanielk1977 ** The callback routine for sqlite3_exec_printf().
137d1bf3512Sdrh */
138d1bf3512Sdrh static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
139d1bf3512Sdrh   Tcl_DString *str = (Tcl_DString*)pArg;
140d1bf3512Sdrh   int i;
141d1bf3512Sdrh 
142d1bf3512Sdrh   if( Tcl_DStringLength(str)==0 ){
143d1bf3512Sdrh     for(i=0; i<argc; i++){
144d1bf3512Sdrh       Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
145d1bf3512Sdrh     }
146d1bf3512Sdrh   }
147d1bf3512Sdrh   for(i=0; i<argc; i++){
148d1bf3512Sdrh     Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
149d1bf3512Sdrh   }
150d1bf3512Sdrh   return 0;
151d1bf3512Sdrh }
152d1bf3512Sdrh 
153d1bf3512Sdrh /*
1546f8a503dSdanielk1977 ** Usage:  sqlite3_exec_printf  DB  FORMAT  STRING
155d1bf3512Sdrh **
1566f8a503dSdanielk1977 ** Invoke the sqlite3_exec_printf() interface using the open database
157d1bf3512Sdrh ** DB.  The SQL is the string FORMAT.  The format string should contain
158d1bf3512Sdrh ** one %s or %q.  STRING is the value inserted into %s or %q.
159d1bf3512Sdrh */
160d1bf3512Sdrh static int test_exec_printf(
161d1bf3512Sdrh   void *NotUsed,
162d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
163d1bf3512Sdrh   int argc,              /* Number of arguments */
164d1bf3512Sdrh   char **argv            /* Text of each argument */
165d1bf3512Sdrh ){
1669bb575fdSdrh   sqlite3 *db;
167d1bf3512Sdrh   Tcl_DString str;
168d1bf3512Sdrh   int rc;
169d1bf3512Sdrh   char *zErr = 0;
1701211de37Sdrh   char *zSql;
171d1bf3512Sdrh   char zBuf[30];
172d1bf3512Sdrh   if( argc!=4 ){
173d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
174d1bf3512Sdrh        " DB FORMAT STRING", 0);
175d1bf3512Sdrh     return TCL_ERROR;
176d1bf3512Sdrh   }
177b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
178d1bf3512Sdrh   Tcl_DStringInit(&str);
1791211de37Sdrh   zSql = sqlite3_mprintf(argv[2], argv[3]);
1801211de37Sdrh   rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
1811211de37Sdrh   sqlite3_free(zSql);
182d1bf3512Sdrh   sprintf(zBuf, "%d", rc);
183d1bf3512Sdrh   Tcl_AppendElement(interp, zBuf);
184d1bf3512Sdrh   Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
185d1bf3512Sdrh   Tcl_DStringFree(&str);
186d1bf3512Sdrh   if( zErr ) free(zErr);
187c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
188d1bf3512Sdrh   return TCL_OK;
189d1bf3512Sdrh }
190d1bf3512Sdrh 
191d1bf3512Sdrh /*
1926f8a503dSdanielk1977 ** Usage:  sqlite3_mprintf_z_test  SEPARATOR  ARG0  ARG1 ...
193d93d8a81Sdrh **
194d93d8a81Sdrh ** Test the %z format of mprintf().  Use multiple mprintf() calls to
195d93d8a81Sdrh ** concatenate arg0 through argn using separator as the separator.
196d93d8a81Sdrh ** Return the result.
197d93d8a81Sdrh */
198d93d8a81Sdrh static int test_mprintf_z(
199d93d8a81Sdrh   void *NotUsed,
200d93d8a81Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
201d93d8a81Sdrh   int argc,              /* Number of arguments */
202d93d8a81Sdrh   char **argv            /* Text of each argument */
203d93d8a81Sdrh ){
204d93d8a81Sdrh   char *zResult = 0;
205d93d8a81Sdrh   int i;
206d93d8a81Sdrh 
207d93d8a81Sdrh   for(i=2; i<argc; i++){
2084adee20fSdanielk1977     zResult = sqlite3MPrintf("%z%s%s", zResult, argv[1], argv[i]);
209d93d8a81Sdrh   }
210d93d8a81Sdrh   Tcl_AppendResult(interp, zResult, 0);
2115f968436Sdrh   sqliteFree(zResult);
212d93d8a81Sdrh   return TCL_OK;
213d93d8a81Sdrh }
214d93d8a81Sdrh 
215d93d8a81Sdrh /*
2166f8a503dSdanielk1977 ** Usage:  sqlite3_get_table_printf  DB  FORMAT  STRING
217d1bf3512Sdrh **
2186f8a503dSdanielk1977 ** Invoke the sqlite3_get_table_printf() interface using the open database
219d1bf3512Sdrh ** DB.  The SQL is the string FORMAT.  The format string should contain
220d1bf3512Sdrh ** one %s or %q.  STRING is the value inserted into %s or %q.
221d1bf3512Sdrh */
222d1bf3512Sdrh static int test_get_table_printf(
223d1bf3512Sdrh   void *NotUsed,
224d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
225d1bf3512Sdrh   int argc,              /* Number of arguments */
226d1bf3512Sdrh   char **argv            /* Text of each argument */
227d1bf3512Sdrh ){
2289bb575fdSdrh   sqlite3 *db;
229d1bf3512Sdrh   Tcl_DString str;
230d1bf3512Sdrh   int rc;
231d1bf3512Sdrh   char *zErr = 0;
232d1bf3512Sdrh   int nRow, nCol;
233d1bf3512Sdrh   char **aResult;
234d1bf3512Sdrh   int i;
235d1bf3512Sdrh   char zBuf[30];
2361211de37Sdrh   char *zSql;
237d1bf3512Sdrh   if( argc!=4 ){
238d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
239d1bf3512Sdrh        " DB FORMAT STRING", 0);
240d1bf3512Sdrh     return TCL_ERROR;
241d1bf3512Sdrh   }
242b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
243d1bf3512Sdrh   Tcl_DStringInit(&str);
2441211de37Sdrh   zSql = sqlite3_mprintf(argv[2],argv[3]);
2451211de37Sdrh   rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
2461211de37Sdrh   sqlite3_free(zSql);
247d1bf3512Sdrh   sprintf(zBuf, "%d", rc);
248d1bf3512Sdrh   Tcl_AppendElement(interp, zBuf);
249d1bf3512Sdrh   if( rc==SQLITE_OK ){
250d1bf3512Sdrh     sprintf(zBuf, "%d", nRow);
251d1bf3512Sdrh     Tcl_AppendElement(interp, zBuf);
252d1bf3512Sdrh     sprintf(zBuf, "%d", nCol);
253d1bf3512Sdrh     Tcl_AppendElement(interp, zBuf);
254d1bf3512Sdrh     for(i=0; i<(nRow+1)*nCol; i++){
255d1bf3512Sdrh       Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
256d1bf3512Sdrh     }
257d1bf3512Sdrh   }else{
258d1bf3512Sdrh     Tcl_AppendElement(interp, zErr);
259d1bf3512Sdrh   }
2606f8a503dSdanielk1977   sqlite3_free_table(aResult);
261d1bf3512Sdrh   if( zErr ) free(zErr);
262c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
263d1bf3512Sdrh   return TCL_OK;
264d1bf3512Sdrh }
265d1bf3512Sdrh 
266af9ff33aSdrh 
267af9ff33aSdrh /*
2686f8a503dSdanielk1977 ** Usage:  sqlite3_last_insert_rowid DB
269af9ff33aSdrh **
270af9ff33aSdrh ** Returns the integer ROWID of the most recent insert.
271af9ff33aSdrh */
272af9ff33aSdrh static int test_last_rowid(
273af9ff33aSdrh   void *NotUsed,
274af9ff33aSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
275af9ff33aSdrh   int argc,              /* Number of arguments */
276af9ff33aSdrh   char **argv            /* Text of each argument */
277af9ff33aSdrh ){
2789bb575fdSdrh   sqlite3 *db;
279af9ff33aSdrh   char zBuf[30];
280af9ff33aSdrh 
281af9ff33aSdrh   if( argc!=2 ){
282af9ff33aSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
283af9ff33aSdrh     return TCL_ERROR;
284af9ff33aSdrh   }
285b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
286c572ef7fSdanielk1977   sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db));
287af9ff33aSdrh   Tcl_AppendResult(interp, zBuf, 0);
288af9ff33aSdrh   return SQLITE_OK;
289af9ff33aSdrh }
290af9ff33aSdrh 
291d1bf3512Sdrh /*
29225d6543dSdrh ** Usage:  sqlite3_key DB KEY
29325d6543dSdrh **
29425d6543dSdrh ** Set the codec key.
29525d6543dSdrh */
29625d6543dSdrh static int test_key(
29725d6543dSdrh   void *NotUsed,
29825d6543dSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
29925d6543dSdrh   int argc,              /* Number of arguments */
30025d6543dSdrh   char **argv            /* Text of each argument */
30125d6543dSdrh ){
3029bb575fdSdrh   sqlite3 *db;
30325d6543dSdrh   const char *zKey;
30425d6543dSdrh   int nKey;
30525d6543dSdrh   if( argc!=3 ){
30625d6543dSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
30725d6543dSdrh        " FILENAME\"", 0);
30825d6543dSdrh     return TCL_ERROR;
30925d6543dSdrh   }
31025d6543dSdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
31125d6543dSdrh   zKey = argv[2];
31225d6543dSdrh   nKey = strlen(zKey);
31325d6543dSdrh #ifdef SQLITE_HAS_CODEC
31425d6543dSdrh   sqlite3_key(db, zKey, nKey);
31525d6543dSdrh #endif
31625d6543dSdrh   return TCL_OK;
31725d6543dSdrh }
31825d6543dSdrh 
31925d6543dSdrh /*
32025d6543dSdrh ** Usage:  sqlite3_rekey DB KEY
32125d6543dSdrh **
32225d6543dSdrh ** Change the codec key.
32325d6543dSdrh */
32425d6543dSdrh static int test_rekey(
32525d6543dSdrh   void *NotUsed,
32625d6543dSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
32725d6543dSdrh   int argc,              /* Number of arguments */
32825d6543dSdrh   char **argv            /* Text of each argument */
32925d6543dSdrh ){
3309bb575fdSdrh   sqlite3 *db;
33125d6543dSdrh   const char *zKey;
33225d6543dSdrh   int nKey;
33325d6543dSdrh   if( argc!=3 ){
33425d6543dSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
33525d6543dSdrh        " FILENAME\"", 0);
33625d6543dSdrh     return TCL_ERROR;
33725d6543dSdrh   }
33825d6543dSdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
33925d6543dSdrh   zKey = argv[2];
34025d6543dSdrh   nKey = strlen(zKey);
34125d6543dSdrh #ifdef SQLITE_HAS_CODEC
34225d6543dSdrh   sqlite3_rekey(db, zKey, nKey);
34325d6543dSdrh #endif
34425d6543dSdrh   return TCL_OK;
34525d6543dSdrh }
34625d6543dSdrh 
34725d6543dSdrh /*
3486f8a503dSdanielk1977 ** Usage:  sqlite3_close DB
349d1bf3512Sdrh **
3506f8a503dSdanielk1977 ** Closes the database opened by sqlite3_open.
351d1bf3512Sdrh */
352d1bf3512Sdrh static int sqlite_test_close(
353d1bf3512Sdrh   void *NotUsed,
354d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
355d1bf3512Sdrh   int argc,              /* Number of arguments */
356d1bf3512Sdrh   char **argv            /* Text of each argument */
357d1bf3512Sdrh ){
3589bb575fdSdrh   sqlite3 *db;
35996d81f99Sdanielk1977   int rc;
360d1bf3512Sdrh   if( argc!=2 ){
361d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
362d1bf3512Sdrh        " FILENAME\"", 0);
363d1bf3512Sdrh     return TCL_ERROR;
364d1bf3512Sdrh   }
365b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
36696d81f99Sdanielk1977   rc = sqlite3_close(db);
367f9d64d2cSdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
368d1bf3512Sdrh   return TCL_OK;
369d1bf3512Sdrh }
370d1bf3512Sdrh 
371d1bf3512Sdrh /*
372c22bd47dSdrh ** Implementation of the x_coalesce() function.
373c22bd47dSdrh ** Return the first argument non-NULL argument.
374c22bd47dSdrh */
3750ae8b831Sdanielk1977 static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
376c22bd47dSdrh   int i;
377c22bd47dSdrh   for(i=0; i<argc; i++){
3789c054830Sdrh     if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
379d8123366Sdanielk1977       sqlite3_result_text(context, sqlite3_value_text(argv[i]), -1,
380d8123366Sdanielk1977           SQLITE_TRANSIENT);
381c22bd47dSdrh       break;
382c22bd47dSdrh     }
383c22bd47dSdrh   }
384c22bd47dSdrh }
385c22bd47dSdrh 
386c22bd47dSdrh /*
387d1d9fc33Sdrh ** A structure into which to accumulate text.
388d1d9fc33Sdrh */
389d1d9fc33Sdrh struct dstr {
390d1d9fc33Sdrh   int nAlloc;  /* Space allocated */
391d1d9fc33Sdrh   int nUsed;   /* Space used */
392d1d9fc33Sdrh   char *z;     /* The space */
393d1d9fc33Sdrh };
394d1d9fc33Sdrh 
395d1d9fc33Sdrh /*
396d1d9fc33Sdrh ** Append text to a dstr
397d1d9fc33Sdrh */
398d1d9fc33Sdrh static void dstrAppend(struct dstr *p, const char *z, int divider){
399d1d9fc33Sdrh   int n = strlen(z);
400d1d9fc33Sdrh   if( p->nUsed + n + 2 > p->nAlloc ){
401d1d9fc33Sdrh     char *zNew;
402d1d9fc33Sdrh     p->nAlloc = p->nAlloc*2 + n + 200;
403d1d9fc33Sdrh     zNew = sqliteRealloc(p->z, p->nAlloc);
404d1d9fc33Sdrh     if( zNew==0 ){
405d1d9fc33Sdrh       sqliteFree(p->z);
406d1d9fc33Sdrh       memset(p, 0, sizeof(*p));
407d1d9fc33Sdrh       return;
408d1d9fc33Sdrh     }
409d1d9fc33Sdrh     p->z = zNew;
410d1d9fc33Sdrh   }
411d1d9fc33Sdrh   if( divider && p->nUsed>0 ){
412d1d9fc33Sdrh     p->z[p->nUsed++] = divider;
413d1d9fc33Sdrh   }
414d1d9fc33Sdrh   memcpy(&p->z[p->nUsed], z, n+1);
415d1d9fc33Sdrh   p->nUsed += n;
416d1d9fc33Sdrh }
417d1d9fc33Sdrh 
418d1d9fc33Sdrh /*
4194adee20fSdanielk1977 ** Invoked for each callback from sqlite3ExecFunc
420d1d9fc33Sdrh */
421d1d9fc33Sdrh static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
422d1d9fc33Sdrh   struct dstr *p = (struct dstr*)pData;
423d1d9fc33Sdrh   int i;
424d1d9fc33Sdrh   for(i=0; i<argc; i++){
425d1d9fc33Sdrh     if( argv[i]==0 ){
426d1d9fc33Sdrh       dstrAppend(p, "NULL", ' ');
427d1d9fc33Sdrh     }else{
428d1d9fc33Sdrh       dstrAppend(p, argv[i], ' ');
429d1d9fc33Sdrh     }
430d1d9fc33Sdrh   }
431d1d9fc33Sdrh   return 0;
432d1d9fc33Sdrh }
433d1d9fc33Sdrh 
434d1d9fc33Sdrh /*
435e35ee196Sdanielk1977 ** Implementation of the x_sqlite_exec() function.  This function takes
436c22bd47dSdrh ** a single argument and attempts to execute that argument as SQL code.
4376cbe1f1bSdrh ** This is illegal and should set the SQLITE_MISUSE flag on the database.
438c22bd47dSdrh **
4396f8a503dSdanielk1977 ** 2004-Jan-07:  We have changed this to make it legal to call sqlite3_exec()
440d1d9fc33Sdrh ** from within a function call.
441d1d9fc33Sdrh **
442c22bd47dSdrh ** This routine simulates the effect of having two threads attempt to
443c22bd47dSdrh ** use the same database at the same time.
444c22bd47dSdrh */
44551ad0ecdSdanielk1977 static void sqlite3ExecFunc(
4460ae8b831Sdanielk1977   sqlite3_context *context,
44751ad0ecdSdanielk1977   int argc,
44851ad0ecdSdanielk1977   sqlite3_value **argv
44951ad0ecdSdanielk1977 ){
450d1d9fc33Sdrh   struct dstr x;
451d1d9fc33Sdrh   memset(&x, 0, sizeof(x));
4529bb575fdSdrh   sqlite3_exec((sqlite3*)sqlite3_user_data(context),
4534f26d6c4Sdrh       sqlite3_value_text(argv[0]),
454d1d9fc33Sdrh       execFuncCallback, &x, 0);
455d8123366Sdanielk1977   sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
456d1d9fc33Sdrh   sqliteFree(x.z);
457c22bd47dSdrh }
458c22bd47dSdrh 
459c22bd47dSdrh /*
460c22bd47dSdrh ** Usage:  sqlite_test_create_function DB
461c22bd47dSdrh **
4626f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order
463c22bd47dSdrh ** to create a function named "x_coalesce".  This function does the same thing
464c22bd47dSdrh ** as the "coalesce" function.  This function also registers an SQL function
465e35ee196Sdanielk1977 ** named "x_sqlite_exec" that invokes sqlite3_exec().  Invoking sqlite3_exec()
466c22bd47dSdrh ** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
467c22bd47dSdrh ** The effect is similar to trying to use the same database connection from
468c22bd47dSdrh ** two threads at the same time.
469c22bd47dSdrh **
470c22bd47dSdrh ** The original motivation for this routine was to be able to call the
4716f8a503dSdanielk1977 ** sqlite3_create_function function while a query is in progress in order
472c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic.
473c22bd47dSdrh */
474c2eef3b3Sdrh static int test_create_function(
475c22bd47dSdrh   void *NotUsed,
476c22bd47dSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
477c22bd47dSdrh   int argc,              /* Number of arguments */
478c22bd47dSdrh   char **argv            /* Text of each argument */
479c22bd47dSdrh ){
480c60d0446Sdrh   int rc;
4819bb575fdSdrh   sqlite3 *db;
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 ){
497576ec6b3Sdanielk1977     sqlite3_value *pVal;
498312d6b36Sdanielk1977     pVal = sqlite3ValueNew();
499312d6b36Sdanielk1977     sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
500c60d0446Sdrh     rc = sqlite3_create_function16(db,
501c60d0446Sdrh               sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),
502312d6b36Sdanielk1977               1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
503312d6b36Sdanielk1977     sqlite3ValueFree(pVal);
504c60d0446Sdrh   }
5055436dc2dSdrh #endif
5065436dc2dSdrh 
507c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
5084397de57Sdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), 0);
509c22bd47dSdrh   return TCL_OK;
510c22bd47dSdrh }
511c22bd47dSdrh 
512c22bd47dSdrh /*
513c22bd47dSdrh ** Routines to implement the x_count() aggregate function.
514c22bd47dSdrh */
515c22bd47dSdrh typedef struct CountCtx CountCtx;
516c22bd47dSdrh struct CountCtx {
517c22bd47dSdrh   int n;
518c22bd47dSdrh };
5190ae8b831Sdanielk1977 static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
520c22bd47dSdrh   CountCtx *p;
5214f26d6c4Sdrh   p = sqlite3_aggregate_context(context, sizeof(*p));
5229c054830Sdrh   if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
523c22bd47dSdrh     p->n++;
524c22bd47dSdrh   }
525c22bd47dSdrh }
5260ae8b831Sdanielk1977 static void countFinalize(sqlite3_context *context){
527c22bd47dSdrh   CountCtx *p;
5284f26d6c4Sdrh   p = sqlite3_aggregate_context(context, sizeof(*p));
529c572ef7fSdanielk1977   sqlite3_result_int(context, p ? p->n : 0);
530c22bd47dSdrh }
531c22bd47dSdrh 
532c22bd47dSdrh /*
533c22bd47dSdrh ** Usage:  sqlite_test_create_aggregate DB
534c22bd47dSdrh **
5356f8a503dSdanielk1977 ** Call the sqlite3_create_function API on the given database in order
536c22bd47dSdrh ** to create a function named "x_count".  This function does the same thing
537c22bd47dSdrh ** as the "md5sum" function.
538c22bd47dSdrh **
539c22bd47dSdrh ** The original motivation for this routine was to be able to call the
5406f8a503dSdanielk1977 ** sqlite3_create_aggregate function while a query is in progress in order
541c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic.
542c22bd47dSdrh */
543c2eef3b3Sdrh static int test_create_aggregate(
544c22bd47dSdrh   void *NotUsed,
545c22bd47dSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
546c22bd47dSdrh   int argc,              /* Number of arguments */
547c22bd47dSdrh   char **argv            /* Text of each argument */
548c22bd47dSdrh ){
5499bb575fdSdrh   sqlite3 *db;
550c60d0446Sdrh   int rc;
551c22bd47dSdrh   if( argc!=2 ){
552c22bd47dSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
553c22bd47dSdrh        " FILENAME\"", 0);
554c22bd47dSdrh     return TCL_ERROR;
555c22bd47dSdrh   }
556b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
557c60d0446Sdrh   rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
558d8123366Sdanielk1977       countStep,countFinalize);
559c60d0446Sdrh   if( rc==SQLITE_OK ){
560f9d64d2cSdanielk1977     sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
561d8123366Sdanielk1977         countStep,countFinalize);
562c60d0446Sdrh   }
563c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
564c22bd47dSdrh   return TCL_OK;
565c22bd47dSdrh }
566c22bd47dSdrh 
567c22bd47dSdrh 
568c22bd47dSdrh 
569c22bd47dSdrh /*
5706f8a503dSdanielk1977 ** Usage:  sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
571d1bf3512Sdrh **
572d1bf3512Sdrh ** Call mprintf with three integer arguments
573d1bf3512Sdrh */
5746f8a503dSdanielk1977 static int sqlite3_mprintf_int(
575d1bf3512Sdrh   void *NotUsed,
576d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
577d1bf3512Sdrh   int argc,              /* Number of arguments */
578d1bf3512Sdrh   char **argv            /* Text of each argument */
579d1bf3512Sdrh ){
580d1bf3512Sdrh   int a[3], i;
581d1bf3512Sdrh   char *z;
582d1bf3512Sdrh   if( argc!=5 ){
583d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
584d1bf3512Sdrh        " FORMAT INT INT INT\"", 0);
585d1bf3512Sdrh     return TCL_ERROR;
586d1bf3512Sdrh   }
587d1bf3512Sdrh   for(i=2; i<5; i++){
588d1bf3512Sdrh     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
589d1bf3512Sdrh   }
5906f8a503dSdanielk1977   z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
591d1bf3512Sdrh   Tcl_AppendResult(interp, z, 0);
5923f4fedb2Sdrh   sqlite3_free(z);
593d1bf3512Sdrh   return TCL_OK;
594d1bf3512Sdrh }
595d1bf3512Sdrh 
596d1bf3512Sdrh /*
5979d213ef0Sdrh ** If zNum represents an integer that will fit in 64-bits, then set
5989d213ef0Sdrh ** *pValue to that integer and return true.  Otherwise return false.
5999d213ef0Sdrh */
6009d213ef0Sdrh static int sqlite3GetInt64(const char *zNum, i64 *pValue){
6019d213ef0Sdrh   if( sqlite3FitsIn64Bits(zNum) ){
6029d213ef0Sdrh     sqlite3atoi64(zNum, pValue);
6039d213ef0Sdrh     return 1;
6049d213ef0Sdrh   }
6059d213ef0Sdrh   return 0;
6069d213ef0Sdrh }
6079d213ef0Sdrh 
6089d213ef0Sdrh /*
609e9707671Sdrh ** Usage:  sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
610e9707671Sdrh **
611e9707671Sdrh ** Call mprintf with three 64-bit integer arguments
612e9707671Sdrh */
613e9707671Sdrh static int sqlite3_mprintf_int64(
614e9707671Sdrh   void *NotUsed,
615e9707671Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
616e9707671Sdrh   int argc,              /* Number of arguments */
617e9707671Sdrh   char **argv            /* Text of each argument */
618e9707671Sdrh ){
619e9707671Sdrh   int i;
620e9707671Sdrh   sqlite_int64 a[3];
621e9707671Sdrh   char *z;
622e9707671Sdrh   if( argc!=5 ){
623e9707671Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
624e9707671Sdrh        " FORMAT INT INT INT\"", 0);
625e9707671Sdrh     return TCL_ERROR;
626e9707671Sdrh   }
627e9707671Sdrh   for(i=2; i<5; i++){
628e9707671Sdrh     if( !sqlite3GetInt64(argv[i], &a[i-2]) ){
629e9707671Sdrh       Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
630e9707671Sdrh       return TCL_ERROR;
631e9707671Sdrh     }
632e9707671Sdrh   }
633e9707671Sdrh   z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
634e9707671Sdrh   Tcl_AppendResult(interp, z, 0);
635e9707671Sdrh   sqlite3_free(z);
636e9707671Sdrh   return TCL_OK;
637e9707671Sdrh }
638e9707671Sdrh 
639e9707671Sdrh /*
6406f8a503dSdanielk1977 ** Usage:  sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
641d1bf3512Sdrh **
642d1bf3512Sdrh ** Call mprintf with two integer arguments and one string argument
643d1bf3512Sdrh */
6446f8a503dSdanielk1977 static int sqlite3_mprintf_str(
645d1bf3512Sdrh   void *NotUsed,
646d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
647d1bf3512Sdrh   int argc,              /* Number of arguments */
648d1bf3512Sdrh   char **argv            /* Text of each argument */
649d1bf3512Sdrh ){
650d1bf3512Sdrh   int a[3], i;
651d1bf3512Sdrh   char *z;
652f220b24fSchw   if( argc<4 || argc>5 ){
653d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
654f220b24fSchw        " FORMAT INT INT ?STRING?\"", 0);
655d1bf3512Sdrh     return TCL_ERROR;
656d1bf3512Sdrh   }
657d1bf3512Sdrh   for(i=2; i<4; i++){
658d1bf3512Sdrh     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
659d1bf3512Sdrh   }
6606f8a503dSdanielk1977   z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
661d1bf3512Sdrh   Tcl_AppendResult(interp, z, 0);
6623f4fedb2Sdrh   sqlite3_free(z);
663d1bf3512Sdrh   return TCL_OK;
664d1bf3512Sdrh }
665d1bf3512Sdrh 
666d1bf3512Sdrh /*
6676f8a503dSdanielk1977 ** Usage:  sqlite3_mprintf_str FORMAT INTEGER INTEGER DOUBLE
668d1bf3512Sdrh **
669d1bf3512Sdrh ** Call mprintf with two integer arguments and one double argument
670d1bf3512Sdrh */
6716f8a503dSdanielk1977 static int sqlite3_mprintf_double(
672d1bf3512Sdrh   void *NotUsed,
673d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
674d1bf3512Sdrh   int argc,              /* Number of arguments */
675d1bf3512Sdrh   char **argv            /* Text of each argument */
676d1bf3512Sdrh ){
677d1bf3512Sdrh   int a[3], i;
678d1bf3512Sdrh   double r;
679d1bf3512Sdrh   char *z;
680d1bf3512Sdrh   if( argc!=5 ){
681d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
682d1bf3512Sdrh        " FORMAT INT INT STRING\"", 0);
683d1bf3512Sdrh     return TCL_ERROR;
684d1bf3512Sdrh   }
685d1bf3512Sdrh   for(i=2; i<4; i++){
686d1bf3512Sdrh     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
687d1bf3512Sdrh   }
688d1bf3512Sdrh   if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
6896f8a503dSdanielk1977   z = sqlite3_mprintf(argv[1], a[0], a[1], r);
690d1bf3512Sdrh   Tcl_AppendResult(interp, z, 0);
6913f4fedb2Sdrh   sqlite3_free(z);
692d1bf3512Sdrh   return TCL_OK;
693d1bf3512Sdrh }
694d1bf3512Sdrh 
695d1bf3512Sdrh /*
6966f8a503dSdanielk1977 ** Usage:  sqlite3_mprintf_str FORMAT DOUBLE DOUBLE
697b621c237Sdrh **
698b621c237Sdrh ** Call mprintf with a single double argument which is the product of the
699b621c237Sdrh ** two arguments given above.  This is used to generate overflow and underflow
700b621c237Sdrh ** doubles to test that they are converted properly.
701b621c237Sdrh */
7026f8a503dSdanielk1977 static int sqlite3_mprintf_scaled(
703b621c237Sdrh   void *NotUsed,
704b621c237Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
705b621c237Sdrh   int argc,              /* Number of arguments */
706b621c237Sdrh   char **argv            /* Text of each argument */
707b621c237Sdrh ){
708b621c237Sdrh   int i;
709b621c237Sdrh   double r[2];
710b621c237Sdrh   char *z;
711b621c237Sdrh   if( argc!=4 ){
712b621c237Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
713b621c237Sdrh        " FORMAT DOUBLE DOUBLE\"", 0);
714b621c237Sdrh     return TCL_ERROR;
715b621c237Sdrh   }
716b621c237Sdrh   for(i=2; i<4; i++){
717b621c237Sdrh     if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
718b621c237Sdrh   }
7196f8a503dSdanielk1977   z = sqlite3_mprintf(argv[1], r[0]*r[1]);
720b621c237Sdrh   Tcl_AppendResult(interp, z, 0);
7213f4fedb2Sdrh   sqlite3_free(z);
722b621c237Sdrh   return TCL_OK;
723b621c237Sdrh }
724b621c237Sdrh 
725b621c237Sdrh /*
726e29b1a05Sdrh ** Usage:  sqlite3_mprintf_stronly FORMAT STRING
727e29b1a05Sdrh **
728e29b1a05Sdrh ** Call mprintf with a single double argument which is the product of the
729e29b1a05Sdrh ** two arguments given above.  This is used to generate overflow and underflow
730e29b1a05Sdrh ** doubles to test that they are converted properly.
731e29b1a05Sdrh */
732e29b1a05Sdrh static int sqlite3_mprintf_stronly(
733e29b1a05Sdrh   void *NotUsed,
734e29b1a05Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
735e29b1a05Sdrh   int argc,              /* Number of arguments */
736e29b1a05Sdrh   char **argv            /* Text of each argument */
737e29b1a05Sdrh ){
738e29b1a05Sdrh   char *z;
739e29b1a05Sdrh   if( argc!=3 ){
740e29b1a05Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
741e29b1a05Sdrh        " FORMAT STRING\"", 0);
742e29b1a05Sdrh     return TCL_ERROR;
743e29b1a05Sdrh   }
744e29b1a05Sdrh   z = sqlite3_mprintf(argv[1], argv[2]);
745e29b1a05Sdrh   Tcl_AppendResult(interp, z, 0);
746e29b1a05Sdrh   sqlite3_free(z);
747e29b1a05Sdrh   return TCL_OK;
748e29b1a05Sdrh }
749e29b1a05Sdrh 
750e29b1a05Sdrh /*
7514693423bSdrh ** Usage: sqlite_malloc_fail N  ?REPEAT-INTERVAL?
752daffd0e5Sdrh **
7534693423bSdrh ** Rig sqliteMalloc() to fail on the N-th call and every REPEAT-INTERVAL call
7544693423bSdrh ** after that.  If REPEAT-INTERVAL is 0 or is omitted, then only a single
7554693423bSdrh ** malloc will fail.  If REPEAT-INTERVAL is 1 then all mallocs after the
7564693423bSdrh ** first failure will continue to fail on every call.  If REPEAT-INTERVAL is
7574693423bSdrh ** 2 then every other malloc will fail.  And so forth.
7584693423bSdrh **
7594693423bSdrh ** Turn off this mechanism and reset the sqlite3_malloc_failed variable is N==0.
760daffd0e5Sdrh */
7612c336549Sdanielk1977 #ifdef SQLITE_MEMDEBUG
762daffd0e5Sdrh static int sqlite_malloc_fail(
763daffd0e5Sdrh   void *NotUsed,
764daffd0e5Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
765daffd0e5Sdrh   int argc,              /* Number of arguments */
766daffd0e5Sdrh   char **argv            /* Text of each argument */
767daffd0e5Sdrh ){
768daffd0e5Sdrh   int n;
7694693423bSdrh   int rep;
7704693423bSdrh   if( argc!=2 && argc!=3 ){
771daffd0e5Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0);
772daffd0e5Sdrh     return TCL_ERROR;
773daffd0e5Sdrh   }
774daffd0e5Sdrh   if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
7754693423bSdrh   if( argc==3 ){
7764693423bSdrh     if( Tcl_GetInt(interp, argv[2], &rep) ) return TCL_ERROR;
7774693423bSdrh   }else{
7784693423bSdrh     rep = 0;
7794693423bSdrh   }
7806f8a503dSdanielk1977   sqlite3_iMallocFail = n;
7814693423bSdrh   sqlite3_iMallocReset = rep;
7826f8a503dSdanielk1977   sqlite3_malloc_failed = 0;
783daffd0e5Sdrh   return TCL_OK;
784daffd0e5Sdrh }
785daffd0e5Sdrh #endif
786daffd0e5Sdrh 
787daffd0e5Sdrh /*
788daffd0e5Sdrh ** Usage: sqlite_malloc_stat
789daffd0e5Sdrh **
790daffd0e5Sdrh ** Return the number of prior calls to sqliteMalloc() and sqliteFree().
791daffd0e5Sdrh */
7922c336549Sdanielk1977 #ifdef SQLITE_MEMDEBUG
793daffd0e5Sdrh static int sqlite_malloc_stat(
794daffd0e5Sdrh   void *NotUsed,
795daffd0e5Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
796daffd0e5Sdrh   int argc,              /* Number of arguments */
797daffd0e5Sdrh   char **argv            /* Text of each argument */
798daffd0e5Sdrh ){
799daffd0e5Sdrh   char zBuf[200];
8006f8a503dSdanielk1977   sprintf(zBuf, "%d %d %d", sqlite3_nMalloc, sqlite3_nFree, sqlite3_iMallocFail);
801daffd0e5Sdrh   Tcl_AppendResult(interp, zBuf, 0);
802daffd0e5Sdrh   return TCL_OK;
803daffd0e5Sdrh }
804daffd0e5Sdrh #endif
805daffd0e5Sdrh 
806daffd0e5Sdrh /*
80728b4e489Sdrh ** Usage:  sqlite_abort
80828b4e489Sdrh **
80928b4e489Sdrh ** Shutdown the process immediately.  This is not a clean shutdown.
81028b4e489Sdrh ** This command is used to test the recoverability of a database in
81128b4e489Sdrh ** the event of a program crash.
81228b4e489Sdrh */
81328b4e489Sdrh static int sqlite_abort(
81428b4e489Sdrh   void *NotUsed,
81528b4e489Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
81628b4e489Sdrh   int argc,              /* Number of arguments */
81728b4e489Sdrh   char **argv            /* Text of each argument */
81828b4e489Sdrh ){
81928b4e489Sdrh   assert( interp==0 );   /* This will always fail */
82028b4e489Sdrh   return TCL_OK;
82128b4e489Sdrh }
82228b4e489Sdrh 
82328b4e489Sdrh /*
8246cbe1f1bSdrh ** The following routine is a user-defined SQL function whose purpose
8256cbe1f1bSdrh ** is to test the sqlite_set_result() API.
8266cbe1f1bSdrh */
8270ae8b831Sdanielk1977 static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
8286cbe1f1bSdrh   while( argc>=2 ){
8294f26d6c4Sdrh     const char *zArg0 = sqlite3_value_text(argv[0]);
8306d88bad4Sdanielk1977     if( zArg0 ){
8316d88bad4Sdanielk1977       if( 0==sqlite3StrICmp(zArg0, "int") ){
8326d88bad4Sdanielk1977         sqlite3_result_int(context, sqlite3_value_int(argv[1]));
8336d88bad4Sdanielk1977       }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
8346d88bad4Sdanielk1977         sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
83551ad0ecdSdanielk1977       }else if( sqlite3StrICmp(zArg0,"string")==0 ){
836d8123366Sdanielk1977         sqlite3_result_text(context, sqlite3_value_text(argv[1]), -1,
837d8123366Sdanielk1977             SQLITE_TRANSIENT);
83851ad0ecdSdanielk1977       }else if( sqlite3StrICmp(zArg0,"double")==0 ){
8396d88bad4Sdanielk1977         sqlite3_result_double(context, sqlite3_value_double(argv[1]));
8406d88bad4Sdanielk1977       }else if( sqlite3StrICmp(zArg0,"null")==0 ){
8416d88bad4Sdanielk1977         sqlite3_result_null(context);
8426d88bad4Sdanielk1977       }else if( sqlite3StrICmp(zArg0,"value")==0 ){
8436d88bad4Sdanielk1977         sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
8446cbe1f1bSdrh       }else{
8456d88bad4Sdanielk1977         goto error_out;
8466d88bad4Sdanielk1977       }
8476d88bad4Sdanielk1977     }else{
8486d88bad4Sdanielk1977       goto error_out;
8496cbe1f1bSdrh     }
8506cbe1f1bSdrh     argc -= 2;
8516cbe1f1bSdrh     argv += 2;
8526cbe1f1bSdrh   }
8536d88bad4Sdanielk1977   return;
8546d88bad4Sdanielk1977 
8556d88bad4Sdanielk1977 error_out:
8566d88bad4Sdanielk1977   sqlite3_result_error(context,"first argument should be one of: "
8576d88bad4Sdanielk1977       "int int64 string double null value", -1);
8586cbe1f1bSdrh }
8596cbe1f1bSdrh 
8606cbe1f1bSdrh /*
8616cbe1f1bSdrh ** Usage:   sqlite_register_test_function  DB  NAME
8626cbe1f1bSdrh **
8636cbe1f1bSdrh ** Register the test SQL function on the database DB under the name NAME.
8646cbe1f1bSdrh */
865c2eef3b3Sdrh static int test_register_func(
8666cbe1f1bSdrh   void *NotUsed,
8676cbe1f1bSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
8686cbe1f1bSdrh   int argc,              /* Number of arguments */
8696cbe1f1bSdrh   char **argv            /* Text of each argument */
8706cbe1f1bSdrh ){
8719bb575fdSdrh   sqlite3 *db;
8726cbe1f1bSdrh   int rc;
8736cbe1f1bSdrh   if( argc!=3 ){
8746cbe1f1bSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
8756cbe1f1bSdrh        " DB FUNCTION-NAME", 0);
8766cbe1f1bSdrh     return TCL_ERROR;
8776cbe1f1bSdrh   }
878b86ccfb2Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
879f9d64d2cSdanielk1977   rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
880d8123366Sdanielk1977       testFunc, 0, 0);
8816cbe1f1bSdrh   if( rc!=0 ){
882f20b21c8Sdanielk1977     Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
8836cbe1f1bSdrh     return TCL_ERROR;
8846cbe1f1bSdrh   }
885c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
8866cbe1f1bSdrh   return TCL_OK;
8876cbe1f1bSdrh }
8886cbe1f1bSdrh 
8896cbe1f1bSdrh /*
890106bb236Sdanielk1977 ** Usage:  sqlite3_finalize  STMT
891b86ccfb2Sdrh **
892106bb236Sdanielk1977 ** Finalize a statement handle.
893b86ccfb2Sdrh */
894b86ccfb2Sdrh static int test_finalize(
895106bb236Sdanielk1977   void * clientData,
896106bb236Sdanielk1977   Tcl_Interp *interp,
897106bb236Sdanielk1977   int objc,
898106bb236Sdanielk1977   Tcl_Obj *CONST objv[]
899b86ccfb2Sdrh ){
900106bb236Sdanielk1977   sqlite3_stmt *pStmt;
901b86ccfb2Sdrh   int rc;
902c60d0446Sdrh   sqlite3 *db;
903106bb236Sdanielk1977 
904106bb236Sdanielk1977   if( objc!=2 ){
905106bb236Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
906106bb236Sdanielk1977         Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
907b86ccfb2Sdrh     return TCL_ERROR;
908b86ccfb2Sdrh   }
909106bb236Sdanielk1977 
910106bb236Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
911106bb236Sdanielk1977 
9124397de57Sdanielk1977   if( pStmt ){
913c60d0446Sdrh     db = StmtToDb(pStmt);
9144397de57Sdanielk1977   }
915fc57d7bfSdanielk1977   rc = sqlite3_finalize(pStmt);
916b77f5dadSdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
9174397de57Sdanielk1977   if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
918106bb236Sdanielk1977   return TCL_OK;
919106bb236Sdanielk1977 }
920106bb236Sdanielk1977 
921106bb236Sdanielk1977 /*
922106bb236Sdanielk1977 ** Usage:  sqlite3_reset  STMT
923106bb236Sdanielk1977 **
924106bb236Sdanielk1977 ** Finalize a statement handle.
925106bb236Sdanielk1977 */
926106bb236Sdanielk1977 static int test_reset(
927106bb236Sdanielk1977   void * clientData,
928106bb236Sdanielk1977   Tcl_Interp *interp,
929106bb236Sdanielk1977   int objc,
930106bb236Sdanielk1977   Tcl_Obj *CONST objv[]
931106bb236Sdanielk1977 ){
932106bb236Sdanielk1977   sqlite3_stmt *pStmt;
933106bb236Sdanielk1977   int rc;
934106bb236Sdanielk1977 
935106bb236Sdanielk1977   if( objc!=2 ){
936106bb236Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
937106bb236Sdanielk1977         Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
938106bb236Sdanielk1977     return TCL_ERROR;
939106bb236Sdanielk1977   }
940106bb236Sdanielk1977 
941106bb236Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
942106bb236Sdanielk1977 
943fc57d7bfSdanielk1977   rc = sqlite3_reset(pStmt);
9444397de57Sdanielk1977   if( pStmt &&
9454397de57Sdanielk1977       sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
9464397de57Sdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
947106bb236Sdanielk1977   if( rc ){
948b86ccfb2Sdrh     return TCL_ERROR;
949b86ccfb2Sdrh   }
950b86ccfb2Sdrh   return TCL_OK;
951b86ccfb2Sdrh }
952b86ccfb2Sdrh 
9535a38705eSdrh /*
954d89bd007Sdrh ** Usage:  sqlite3_expired STMT
955d89bd007Sdrh **
956d89bd007Sdrh ** Return TRUE if a recompilation of the statement is recommended.
957d89bd007Sdrh */
958d89bd007Sdrh static int test_expired(
959d89bd007Sdrh   void * clientData,
960d89bd007Sdrh   Tcl_Interp *interp,
961d89bd007Sdrh   int objc,
962d89bd007Sdrh   Tcl_Obj *CONST objv[]
963d89bd007Sdrh ){
964d89bd007Sdrh   sqlite3_stmt *pStmt;
965d89bd007Sdrh   if( objc!=2 ){
966d89bd007Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"",
967d89bd007Sdrh         Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
968d89bd007Sdrh     return TCL_ERROR;
969d89bd007Sdrh   }
970d89bd007Sdrh   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
971d89bd007Sdrh   Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt)));
972d89bd007Sdrh   return TCL_OK;
973d89bd007Sdrh }
974d89bd007Sdrh 
975d89bd007Sdrh /*
976f8db1bc0Sdrh ** Usage:  sqlite3_transfer_bindings FROMSTMT TOSTMT
977f8db1bc0Sdrh **
978f8db1bc0Sdrh ** Transfer all bindings from FROMSTMT over to TOSTMT
979f8db1bc0Sdrh */
980f8db1bc0Sdrh static int test_transfer_bind(
981f8db1bc0Sdrh   void * clientData,
982f8db1bc0Sdrh   Tcl_Interp *interp,
983f8db1bc0Sdrh   int objc,
984f8db1bc0Sdrh   Tcl_Obj *CONST objv[]
985f8db1bc0Sdrh ){
986f8db1bc0Sdrh   sqlite3_stmt *pStmt1, *pStmt2;
987f8db1bc0Sdrh   if( objc!=3 ){
988f8db1bc0Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"",
989f8db1bc0Sdrh         Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0);
990f8db1bc0Sdrh     return TCL_ERROR;
991f8db1bc0Sdrh   }
992f8db1bc0Sdrh   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR;
993f8db1bc0Sdrh   if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR;
994f8db1bc0Sdrh   Tcl_SetObjResult(interp,
995f8db1bc0Sdrh      Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2)));
996f8db1bc0Sdrh   return TCL_OK;
997f8db1bc0Sdrh }
998f8db1bc0Sdrh 
999f8db1bc0Sdrh /*
1000fbcd585fSdanielk1977 ** Usage:  sqlite3_changes DB
100150457896Sdrh **
1002fbcd585fSdanielk1977 ** Return the number of changes made to the database by the last SQL
1003fbcd585fSdanielk1977 ** execution.
100450457896Sdrh */
1005fbcd585fSdanielk1977 static int test_changes(
1006fbcd585fSdanielk1977   void * clientData,
1007fbcd585fSdanielk1977   Tcl_Interp *interp,
1008fbcd585fSdanielk1977   int objc,
1009fbcd585fSdanielk1977   Tcl_Obj *CONST objv[]
1010fbcd585fSdanielk1977 ){
1011fbcd585fSdanielk1977   sqlite3 *db;
1012fbcd585fSdanielk1977   if( objc!=2 ){
1013fbcd585fSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1014fbcd585fSdanielk1977        Tcl_GetString(objv[0]), " DB", 0);
1015fbcd585fSdanielk1977     return TCL_ERROR;
1016fbcd585fSdanielk1977   }
1017fbcd585fSdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1018fbcd585fSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
1019fbcd585fSdanielk1977   return TCL_OK;
1020fbcd585fSdanielk1977 }
102150457896Sdrh 
102250457896Sdrh /*
10237c972decSdrh ** This is the "static_bind_value" that variables are bound to when
10246f8a503dSdanielk1977 ** the FLAG option of sqlite3_bind is "static"
102550457896Sdrh */
10267c972decSdrh static char *sqlite_static_bind_value = 0;
10277c972decSdrh 
10287c972decSdrh /*
10296f8a503dSdanielk1977 ** Usage:  sqlite3_bind  VM  IDX  VALUE  FLAGS
10307c972decSdrh **
10317c972decSdrh ** Sets the value of the IDX-th occurance of "?" in the original SQL
10327c972decSdrh ** string.  VALUE is the new value.  If FLAGS=="null" then VALUE is
10337c972decSdrh ** ignored and the value is set to NULL.  If FLAGS=="static" then
10347c972decSdrh ** the value is set to the value of a static variable named
10357c972decSdrh ** "sqlite_static_bind_value".  If FLAGS=="normal" then a copy
10367c972decSdrh ** of the VALUE is made.
10377c972decSdrh */
10387c972decSdrh static int test_bind(
103950457896Sdrh   void *NotUsed,
104050457896Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
104150457896Sdrh   int argc,              /* Number of arguments */
104250457896Sdrh   char **argv            /* Text of each argument */
104350457896Sdrh ){
1044fc57d7bfSdanielk1977   sqlite3_stmt *pStmt;
104550457896Sdrh   int rc;
10467c972decSdrh   int idx;
10477c972decSdrh   if( argc!=5 ){
104850457896Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
10497c972decSdrh        " VM IDX VALUE (null|static|normal)\"", 0);
105050457896Sdrh     return TCL_ERROR;
105150457896Sdrh   }
1052fc57d7bfSdanielk1977   if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
10537c972decSdrh   if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
10547c972decSdrh   if( strcmp(argv[4],"null")==0 ){
1055fc57d7bfSdanielk1977     rc = sqlite3_bind_null(pStmt, idx);
10567c972decSdrh   }else if( strcmp(argv[4],"static")==0 ){
1057fc57d7bfSdanielk1977     rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
10587c972decSdrh   }else if( strcmp(argv[4],"normal")==0 ){
1059d8123366Sdanielk1977     rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
10607c972decSdrh   }else{
10617c972decSdrh     Tcl_AppendResult(interp, "4th argument should be "
10627c972decSdrh         "\"null\" or \"static\" or \"normal\"", 0);
10637c972decSdrh     return TCL_ERROR;
10647c972decSdrh   }
1065c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
106650457896Sdrh   if( rc ){
106750457896Sdrh     char zBuf[50];
106850457896Sdrh     sprintf(zBuf, "(%d) ", rc);
1069f20b21c8Sdanielk1977     Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
107050457896Sdrh     return TCL_ERROR;
107150457896Sdrh   }
107250457896Sdrh   return TCL_OK;
107350457896Sdrh }
107450457896Sdrh 
10755436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
10764e6af134Sdanielk1977 /*
10774e6af134Sdanielk1977 ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
10784e6af134Sdanielk1977 **
10794e6af134Sdanielk1977 ** This function is used to test that SQLite selects the correct collation
10804e6af134Sdanielk1977 ** sequence callback when multiple versions (for different text encodings)
10814e6af134Sdanielk1977 ** are available.
10824e6af134Sdanielk1977 **
10834e6af134Sdanielk1977 ** Calling this routine registers the collation sequence "test_collate"
10844e6af134Sdanielk1977 ** with database handle <db>. The second argument must be a list of three
10854e6af134Sdanielk1977 ** boolean values. If the first is true, then a version of test_collate is
10864e6af134Sdanielk1977 ** registered for UTF-8, if the second is true, a version is registered for
10874e6af134Sdanielk1977 ** UTF-16le, if the third is true, a UTF-16be version is available.
10884e6af134Sdanielk1977 ** Previous versions of test_collate are deleted.
10894e6af134Sdanielk1977 **
10904e6af134Sdanielk1977 ** The collation sequence test_collate is implemented by calling the
10914e6af134Sdanielk1977 ** following TCL script:
10924e6af134Sdanielk1977 **
10934e6af134Sdanielk1977 **   "test_collate <enc> <lhs> <rhs>"
10944e6af134Sdanielk1977 **
10954e6af134Sdanielk1977 ** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
10964e6af134Sdanielk1977 ** The <enc> parameter is the encoding of the collation function that
10974e6af134Sdanielk1977 ** SQLite selected to call. The TCL test script implements the
10984e6af134Sdanielk1977 ** "test_collate" proc.
10994e6af134Sdanielk1977 **
11004e6af134Sdanielk1977 ** Note that this will only work with one intepreter at a time, as the
11014e6af134Sdanielk1977 ** interp pointer to use when evaluating the TCL script is stored in
11024e6af134Sdanielk1977 ** pTestCollateInterp.
11034e6af134Sdanielk1977 */
11044e6af134Sdanielk1977 static Tcl_Interp* pTestCollateInterp;
11054e6af134Sdanielk1977 static int test_collate_func(
11064e6af134Sdanielk1977   void *pCtx,
11074e6af134Sdanielk1977   int nA, const void *zA,
11084e6af134Sdanielk1977   int nB, const void *zB
11094e6af134Sdanielk1977 ){
11104e6af134Sdanielk1977   Tcl_Interp *i = pTestCollateInterp;
11114e6af134Sdanielk1977   int encin = (int)pCtx;
11124e6af134Sdanielk1977   int res;
11134e6af134Sdanielk1977 
11144e6af134Sdanielk1977   sqlite3_value *pVal;
11154e6af134Sdanielk1977   Tcl_Obj *pX;
11164e6af134Sdanielk1977 
11174e6af134Sdanielk1977   pX = Tcl_NewStringObj("test_collate", -1);
11184e6af134Sdanielk1977   Tcl_IncrRefCount(pX);
11194e6af134Sdanielk1977 
11204e6af134Sdanielk1977   switch( encin ){
11214e6af134Sdanielk1977     case SQLITE_UTF8:
11224e6af134Sdanielk1977       Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
11234e6af134Sdanielk1977       break;
11244e6af134Sdanielk1977     case SQLITE_UTF16LE:
11254e6af134Sdanielk1977       Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
11264e6af134Sdanielk1977       break;
11274e6af134Sdanielk1977     case SQLITE_UTF16BE:
11284e6af134Sdanielk1977       Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
11294e6af134Sdanielk1977       break;
11304e6af134Sdanielk1977     default:
11314e6af134Sdanielk1977       assert(0);
11324e6af134Sdanielk1977   }
11334e6af134Sdanielk1977 
11344e6af134Sdanielk1977   pVal = sqlite3ValueNew();
1135bfd6cce5Sdanielk1977   sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
11364e6af134Sdanielk1977   Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1));
1137bfd6cce5Sdanielk1977   sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
11384e6af134Sdanielk1977   Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1));
11394e6af134Sdanielk1977   sqlite3ValueFree(pVal);
11404e6af134Sdanielk1977 
11414e6af134Sdanielk1977   Tcl_EvalObjEx(i, pX, 0);
11424e6af134Sdanielk1977   Tcl_DecrRefCount(pX);
11434e6af134Sdanielk1977   Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
11444e6af134Sdanielk1977   return res;
11454e6af134Sdanielk1977 }
11464e6af134Sdanielk1977 static int test_collate(
11474e6af134Sdanielk1977   void * clientData,
11484e6af134Sdanielk1977   Tcl_Interp *interp,
11494e6af134Sdanielk1977   int objc,
11504e6af134Sdanielk1977   Tcl_Obj *CONST objv[]
11514e6af134Sdanielk1977 ){
11524e6af134Sdanielk1977   sqlite3 *db;
11534e6af134Sdanielk1977   int val;
1154312d6b36Sdanielk1977   sqlite3_value *pVal;
1155c60d0446Sdrh   int rc;
11564e6af134Sdanielk1977 
11574e6af134Sdanielk1977   if( objc!=5 ) goto bad_args;
11584e6af134Sdanielk1977   pTestCollateInterp = interp;
11594e6af134Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
11604e6af134Sdanielk1977 
11614e6af134Sdanielk1977   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
1162c60d0446Sdrh   rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
11634e6af134Sdanielk1977           (void *)SQLITE_UTF8, val?test_collate_func:0);
1164c60d0446Sdrh   if( rc==SQLITE_OK ){
11654e6af134Sdanielk1977     if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1166c60d0446Sdrh     rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
11674e6af134Sdanielk1977             (void *)SQLITE_UTF16LE, val?test_collate_func:0);
11684e6af134Sdanielk1977     if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
1169312d6b36Sdanielk1977 
1170312d6b36Sdanielk1977     pVal = sqlite3ValueNew();
1171312d6b36Sdanielk1977     sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
1172312d6b36Sdanielk1977     sqlite3_create_collation16(db, sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),
1173312d6b36Sdanielk1977           SQLITE_UTF16BE, (void *)SQLITE_UTF16BE, val?test_collate_func:0);
1174312d6b36Sdanielk1977     sqlite3ValueFree(pVal);
1175c60d0446Sdrh   }
1176c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
11774e6af134Sdanielk1977   return TCL_OK;
11784e6af134Sdanielk1977 
11794e6af134Sdanielk1977 bad_args:
11804e6af134Sdanielk1977   Tcl_AppendResult(interp, "wrong # args: should be \"",
11814e6af134Sdanielk1977       Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
11824e6af134Sdanielk1977   return TCL_ERROR;
11834e6af134Sdanielk1977 }
11844e6af134Sdanielk1977 
1185312d6b36Sdanielk1977 static void test_collate_needed_cb(
1186312d6b36Sdanielk1977   void *pCtx,
1187312d6b36Sdanielk1977   sqlite3 *db,
1188312d6b36Sdanielk1977   int eTextRep,
1189312d6b36Sdanielk1977   const void *notUsed
1190312d6b36Sdanielk1977 ){
1191312d6b36Sdanielk1977   int enc = db->enc;
1192312d6b36Sdanielk1977   sqlite3_create_collation(
1193312d6b36Sdanielk1977       db, "test_collate", db->enc, (void *)enc, test_collate_func);
1194312d6b36Sdanielk1977 }
1195312d6b36Sdanielk1977 
1196312d6b36Sdanielk1977 /*
1197312d6b36Sdanielk1977 ** Usage: add_test_collate_needed DB
1198312d6b36Sdanielk1977 */
1199312d6b36Sdanielk1977 static int test_collate_needed(
1200312d6b36Sdanielk1977   void * clientData,
1201312d6b36Sdanielk1977   Tcl_Interp *interp,
1202312d6b36Sdanielk1977   int objc,
1203312d6b36Sdanielk1977   Tcl_Obj *CONST objv[]
1204312d6b36Sdanielk1977 ){
1205312d6b36Sdanielk1977   sqlite3 *db;
1206c60d0446Sdrh   int rc;
1207312d6b36Sdanielk1977 
1208312d6b36Sdanielk1977   if( objc!=2 ) goto bad_args;
1209312d6b36Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1210c60d0446Sdrh   rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
1211c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
1212312d6b36Sdanielk1977   return TCL_OK;
1213312d6b36Sdanielk1977 
1214312d6b36Sdanielk1977 bad_args:
1215312d6b36Sdanielk1977   Tcl_WrongNumArgs(interp, 1, objv, "DB");
1216312d6b36Sdanielk1977   return TCL_ERROR;
1217312d6b36Sdanielk1977 }
12185436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
1219312d6b36Sdanielk1977 
1220c8e9a2dfSdanielk1977 /*
1221c8e9a2dfSdanielk1977 ** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
1222c8e9a2dfSdanielk1977 **
1223c8e9a2dfSdanielk1977 ** This function is used to test that SQLite selects the correct user
1224c8e9a2dfSdanielk1977 ** function callback when multiple versions (for different text encodings)
1225c8e9a2dfSdanielk1977 ** are available.
1226c8e9a2dfSdanielk1977 **
1227c8e9a2dfSdanielk1977 ** Calling this routine registers up to three versions of the user function
1228c8e9a2dfSdanielk1977 ** "test_function" with database handle <db>.  If the second argument is
1229c8e9a2dfSdanielk1977 ** true, then a version of test_function is registered for UTF-8, if the
1230c8e9a2dfSdanielk1977 ** third is true, a version is registered for UTF-16le, if the fourth is
1231c8e9a2dfSdanielk1977 ** true, a UTF-16be version is available.  Previous versions of
1232c8e9a2dfSdanielk1977 ** test_function are deleted.
1233c8e9a2dfSdanielk1977 **
1234c8e9a2dfSdanielk1977 ** The user function is implemented by calling the following TCL script:
1235c8e9a2dfSdanielk1977 **
1236c8e9a2dfSdanielk1977 **   "test_function <enc> <arg>"
1237c8e9a2dfSdanielk1977 **
1238c8e9a2dfSdanielk1977 ** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
1239c8e9a2dfSdanielk1977 ** single argument passed to the SQL function. The value returned by
1240c8e9a2dfSdanielk1977 ** the TCL script is used as the return value of the SQL function. It
1241c8e9a2dfSdanielk1977 ** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
1242c8e9a2dfSdanielk1977 ** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
1243c8e9a2dfSdanielk1977 ** prefers UTF-16BE.
1244c8e9a2dfSdanielk1977 */
12455436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
1246c8e9a2dfSdanielk1977 static void test_function_utf8(
1247c8e9a2dfSdanielk1977   sqlite3_context *pCtx,
1248c8e9a2dfSdanielk1977   int nArg,
1249c8e9a2dfSdanielk1977   sqlite3_value **argv
1250c8e9a2dfSdanielk1977 ){
1251c8e9a2dfSdanielk1977   Tcl_Interp *interp;
1252c8e9a2dfSdanielk1977   Tcl_Obj *pX;
1253c8e9a2dfSdanielk1977   sqlite3_value *pVal;
1254c8e9a2dfSdanielk1977   interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1255c8e9a2dfSdanielk1977   pX = Tcl_NewStringObj("test_function", -1);
1256c8e9a2dfSdanielk1977   Tcl_IncrRefCount(pX);
1257c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
1258c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX,
1259c8e9a2dfSdanielk1977       Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
1260c8e9a2dfSdanielk1977   Tcl_EvalObjEx(interp, pX, 0);
1261c8e9a2dfSdanielk1977   Tcl_DecrRefCount(pX);
1262c8e9a2dfSdanielk1977   sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
1263c8e9a2dfSdanielk1977   pVal = sqlite3ValueNew();
1264c8e9a2dfSdanielk1977   sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1265c8e9a2dfSdanielk1977       SQLITE_UTF8, SQLITE_STATIC);
1266c8e9a2dfSdanielk1977   sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
1267c8e9a2dfSdanielk1977       -1, SQLITE_TRANSIENT);
1268c8e9a2dfSdanielk1977   sqlite3ValueFree(pVal);
1269c8e9a2dfSdanielk1977 }
1270c8e9a2dfSdanielk1977 static void test_function_utf16le(
1271c8e9a2dfSdanielk1977   sqlite3_context *pCtx,
1272c8e9a2dfSdanielk1977   int nArg,
1273c8e9a2dfSdanielk1977   sqlite3_value **argv
1274c8e9a2dfSdanielk1977 ){
1275c8e9a2dfSdanielk1977   Tcl_Interp *interp;
1276c8e9a2dfSdanielk1977   Tcl_Obj *pX;
1277c8e9a2dfSdanielk1977   sqlite3_value *pVal;
1278c8e9a2dfSdanielk1977   interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1279c8e9a2dfSdanielk1977   pX = Tcl_NewStringObj("test_function", -1);
1280c8e9a2dfSdanielk1977   Tcl_IncrRefCount(pX);
1281c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
1282c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX,
1283c8e9a2dfSdanielk1977       Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
1284c8e9a2dfSdanielk1977   Tcl_EvalObjEx(interp, pX, 0);
1285c8e9a2dfSdanielk1977   Tcl_DecrRefCount(pX);
1286c8e9a2dfSdanielk1977   pVal = sqlite3ValueNew();
1287c8e9a2dfSdanielk1977   sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1288c8e9a2dfSdanielk1977       SQLITE_UTF8, SQLITE_STATIC);
1289c8e9a2dfSdanielk1977   sqlite3_result_text(pCtx,sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
1290c8e9a2dfSdanielk1977   sqlite3ValueFree(pVal);
1291c8e9a2dfSdanielk1977 }
1292c8e9a2dfSdanielk1977 static void test_function_utf16be(
1293c8e9a2dfSdanielk1977   sqlite3_context *pCtx,
1294c8e9a2dfSdanielk1977   int nArg,
1295c8e9a2dfSdanielk1977   sqlite3_value **argv
1296c8e9a2dfSdanielk1977 ){
1297c8e9a2dfSdanielk1977   Tcl_Interp *interp;
1298c8e9a2dfSdanielk1977   Tcl_Obj *pX;
1299c8e9a2dfSdanielk1977   sqlite3_value *pVal;
1300c8e9a2dfSdanielk1977   interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1301c8e9a2dfSdanielk1977   pX = Tcl_NewStringObj("test_function", -1);
1302c8e9a2dfSdanielk1977   Tcl_IncrRefCount(pX);
1303c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
1304c8e9a2dfSdanielk1977   Tcl_ListObjAppendElement(interp, pX,
1305c8e9a2dfSdanielk1977       Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
1306c8e9a2dfSdanielk1977   Tcl_EvalObjEx(interp, pX, 0);
1307c8e9a2dfSdanielk1977   Tcl_DecrRefCount(pX);
1308c8e9a2dfSdanielk1977   pVal = sqlite3ValueNew();
1309c8e9a2dfSdanielk1977   sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1310c8e9a2dfSdanielk1977       SQLITE_UTF8, SQLITE_STATIC);
1311c8e9a2dfSdanielk1977   sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
1312c8e9a2dfSdanielk1977       -1, SQLITE_TRANSIENT);
1313c8e9a2dfSdanielk1977   sqlite3ValueFree(pVal);
1314c8e9a2dfSdanielk1977 }
13155436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
1316c8e9a2dfSdanielk1977 static int test_function(
1317c8e9a2dfSdanielk1977   void * clientData,
1318c8e9a2dfSdanielk1977   Tcl_Interp *interp,
1319c8e9a2dfSdanielk1977   int objc,
1320c8e9a2dfSdanielk1977   Tcl_Obj *CONST objv[]
1321c8e9a2dfSdanielk1977 ){
13225436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
1323c8e9a2dfSdanielk1977   sqlite3 *db;
1324c8e9a2dfSdanielk1977   int val;
1325c8e9a2dfSdanielk1977 
1326c8e9a2dfSdanielk1977   if( objc!=5 ) goto bad_args;
1327c8e9a2dfSdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1328c8e9a2dfSdanielk1977 
1329c8e9a2dfSdanielk1977   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
1330c8e9a2dfSdanielk1977   if( val ){
1331c8e9a2dfSdanielk1977     sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
1332c8e9a2dfSdanielk1977         interp, test_function_utf8, 0, 0);
1333c8e9a2dfSdanielk1977   }
1334c8e9a2dfSdanielk1977   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1335c8e9a2dfSdanielk1977   if( val ){
1336c8e9a2dfSdanielk1977     sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
1337c8e9a2dfSdanielk1977         interp, test_function_utf16le, 0, 0);
1338c8e9a2dfSdanielk1977   }
1339c8e9a2dfSdanielk1977   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
1340c8e9a2dfSdanielk1977   if( val ){
1341c8e9a2dfSdanielk1977     sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
1342c8e9a2dfSdanielk1977         interp, test_function_utf16be, 0, 0);
1343c8e9a2dfSdanielk1977   }
1344c8e9a2dfSdanielk1977 
1345c8e9a2dfSdanielk1977   return TCL_OK;
1346c8e9a2dfSdanielk1977 bad_args:
1347c8e9a2dfSdanielk1977   Tcl_AppendResult(interp, "wrong # args: should be \"",
1348c8e9a2dfSdanielk1977       Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
13495436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
1350c8e9a2dfSdanielk1977   return TCL_ERROR;
1351c8e9a2dfSdanielk1977 }
1352c8e9a2dfSdanielk1977 
1353312d6b36Sdanielk1977 /*
1354312d6b36Sdanielk1977 ** Usage:         test_errstr <err code>
1355312d6b36Sdanielk1977 **
1356312d6b36Sdanielk1977 ** Test that the english language string equivalents for sqlite error codes
1357312d6b36Sdanielk1977 ** are sane. The parameter is an integer representing an sqlite error code.
1358312d6b36Sdanielk1977 ** The result is a list of two elements, the string representation of the
1359312d6b36Sdanielk1977 ** error code and the english language explanation.
1360312d6b36Sdanielk1977 */
1361312d6b36Sdanielk1977 static int test_errstr(
1362312d6b36Sdanielk1977   void * clientData,
1363312d6b36Sdanielk1977   Tcl_Interp *interp,
1364312d6b36Sdanielk1977   int objc,
1365312d6b36Sdanielk1977   Tcl_Obj *CONST objv[]
1366312d6b36Sdanielk1977 ){
1367312d6b36Sdanielk1977   char *zCode;
1368312d6b36Sdanielk1977   int i;
1369312d6b36Sdanielk1977   if( objc!=1 ){
1370312d6b36Sdanielk1977     Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
1371312d6b36Sdanielk1977   }
1372312d6b36Sdanielk1977 
1373312d6b36Sdanielk1977   zCode = Tcl_GetString(objv[1]);
1374312d6b36Sdanielk1977   for(i=0; i<200; i++){
1375312d6b36Sdanielk1977     if( 0==strcmp(errorName(i), zCode) ) break;
1376312d6b36Sdanielk1977   }
1377312d6b36Sdanielk1977   Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
1378312d6b36Sdanielk1977   return TCL_OK;
1379312d6b36Sdanielk1977 }
1380312d6b36Sdanielk1977 
1381c8e9a2dfSdanielk1977 static int sqlite3_crashparams(
13828a6c550dSdanielk1977   void * clientData,
13838a6c550dSdanielk1977   Tcl_Interp *interp,
13848a6c550dSdanielk1977   int objc,
13858a6c550dSdanielk1977   Tcl_Obj *CONST objv[]
13868a6c550dSdanielk1977 ){
13878a6c550dSdanielk1977 #ifdef OS_TEST
1388c8e9a2dfSdanielk1977   int delay;
1389c8e9a2dfSdanielk1977   if( objc!=3 ) goto bad_args;
1390c8e9a2dfSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[1], &delay) ) return TCL_ERROR;
1391c8e9a2dfSdanielk1977   sqlite3SetCrashParams(delay, Tcl_GetString(objv[2]));
13928a6c550dSdanielk1977 #endif
13938a6c550dSdanielk1977   return TCL_OK;
13948a6c550dSdanielk1977 
1395241db313Sdrh #ifdef OS_TEST
13968a6c550dSdanielk1977 bad_args:
13978a6c550dSdanielk1977   Tcl_AppendResult(interp, "wrong # args: should be \"",
1398c8e9a2dfSdanielk1977       Tcl_GetStringFromObj(objv[0], 0), "<delay> <filename>", 0);
13998a6c550dSdanielk1977   return TCL_ERROR;
1400241db313Sdrh #endif
14018a6c550dSdanielk1977 }
14028a6c550dSdanielk1977 
14038a6c550dSdanielk1977 
140450457896Sdrh /*
140599ee3600Sdrh ** Usage:    breakpoint
140699ee3600Sdrh **
140799ee3600Sdrh ** This routine exists for one purpose - to provide a place to put a
140899ee3600Sdrh ** breakpoint with GDB that can be triggered using TCL code.  The use
140999ee3600Sdrh ** for this is when a particular test fails on (say) the 1485th iteration.
141099ee3600Sdrh ** In the TCL test script, we can add code like this:
141199ee3600Sdrh **
141299ee3600Sdrh **     if {$i==1485} breakpoint
141399ee3600Sdrh **
141499ee3600Sdrh ** Then run testfixture in the debugger and wait for the breakpoint to
141599ee3600Sdrh ** fire.  Then additional breakpoints can be set to trace down the bug.
141699ee3600Sdrh */
141799ee3600Sdrh static int test_breakpoint(
141899ee3600Sdrh   void *NotUsed,
141999ee3600Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
142099ee3600Sdrh   int argc,              /* Number of arguments */
142199ee3600Sdrh   char **argv            /* Text of each argument */
142299ee3600Sdrh ){
142399ee3600Sdrh   return TCL_OK;         /* Do nothing */
142499ee3600Sdrh }
142599ee3600Sdrh 
1426241db313Sdrh /*
1427241db313Sdrh ** Usage:   sqlite3_bind_int  STMT N VALUE
1428241db313Sdrh **
1429241db313Sdrh ** Test the sqlite3_bind_int interface.  STMT is a prepared statement.
1430241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1431241db313Sdrh ** binds a 32-bit integer VALUE to that wildcard.
1432241db313Sdrh */
1433241db313Sdrh static int test_bind_int(
143451e3d8e2Sdanielk1977   void * clientData,
143551e3d8e2Sdanielk1977   Tcl_Interp *interp,
143651e3d8e2Sdanielk1977   int objc,
143751e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
143851e3d8e2Sdanielk1977 ){
143951e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
144051e3d8e2Sdanielk1977   int idx;
144151e3d8e2Sdanielk1977   int value;
144251e3d8e2Sdanielk1977   int rc;
144351e3d8e2Sdanielk1977 
144451e3d8e2Sdanielk1977   if( objc!=4 ){
144551e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1446241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
144751e3d8e2Sdanielk1977     return TCL_ERROR;
144851e3d8e2Sdanielk1977   }
144951e3d8e2Sdanielk1977 
145051e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
145151e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
145251e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
145351e3d8e2Sdanielk1977 
1454c572ef7fSdanielk1977   rc = sqlite3_bind_int(pStmt, idx, value);
1455c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
145651e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
145751e3d8e2Sdanielk1977     return TCL_ERROR;
145851e3d8e2Sdanielk1977   }
145951e3d8e2Sdanielk1977 
146051e3d8e2Sdanielk1977   return TCL_OK;
146151e3d8e2Sdanielk1977 }
146251e3d8e2Sdanielk1977 
1463241db313Sdrh 
1464241db313Sdrh /*
1465241db313Sdrh ** Usage:   sqlite3_bind_int64  STMT N VALUE
1466241db313Sdrh **
1467241db313Sdrh ** Test the sqlite3_bind_int64 interface.  STMT is a prepared statement.
1468241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1469241db313Sdrh ** binds a 64-bit integer VALUE to that wildcard.
1470241db313Sdrh */
147151e3d8e2Sdanielk1977 static int test_bind_int64(
147251e3d8e2Sdanielk1977   void * clientData,
147351e3d8e2Sdanielk1977   Tcl_Interp *interp,
147451e3d8e2Sdanielk1977   int objc,
147551e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
147651e3d8e2Sdanielk1977 ){
147751e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
147851e3d8e2Sdanielk1977   int idx;
147951e3d8e2Sdanielk1977   i64 value;
148051e3d8e2Sdanielk1977   int rc;
148151e3d8e2Sdanielk1977 
148251e3d8e2Sdanielk1977   if( objc!=4 ){
148351e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1484241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
148551e3d8e2Sdanielk1977     return TCL_ERROR;
148651e3d8e2Sdanielk1977   }
148751e3d8e2Sdanielk1977 
148851e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
148951e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
149051e3d8e2Sdanielk1977   if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
149151e3d8e2Sdanielk1977 
149251e3d8e2Sdanielk1977   rc = sqlite3_bind_int64(pStmt, idx, value);
1493c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
149451e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
149551e3d8e2Sdanielk1977     return TCL_ERROR;
149651e3d8e2Sdanielk1977   }
149751e3d8e2Sdanielk1977 
149851e3d8e2Sdanielk1977   return TCL_OK;
149951e3d8e2Sdanielk1977 }
150051e3d8e2Sdanielk1977 
1501241db313Sdrh 
1502241db313Sdrh /*
1503241db313Sdrh ** Usage:   sqlite3_bind_double  STMT N VALUE
1504241db313Sdrh **
1505241db313Sdrh ** Test the sqlite3_bind_double interface.  STMT is a prepared statement.
1506241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1507241db313Sdrh ** binds a 64-bit integer VALUE to that wildcard.
1508241db313Sdrh */
150951e3d8e2Sdanielk1977 static int test_bind_double(
151051e3d8e2Sdanielk1977   void * clientData,
151151e3d8e2Sdanielk1977   Tcl_Interp *interp,
151251e3d8e2Sdanielk1977   int objc,
151351e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
151451e3d8e2Sdanielk1977 ){
151551e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
151651e3d8e2Sdanielk1977   int idx;
151751e3d8e2Sdanielk1977   double value;
151851e3d8e2Sdanielk1977   int rc;
151951e3d8e2Sdanielk1977 
152051e3d8e2Sdanielk1977   if( objc!=4 ){
152151e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1522241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
152351e3d8e2Sdanielk1977     return TCL_ERROR;
152451e3d8e2Sdanielk1977   }
152551e3d8e2Sdanielk1977 
152651e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
152751e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
152851e3d8e2Sdanielk1977   if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR;
152951e3d8e2Sdanielk1977 
153051e3d8e2Sdanielk1977   rc = sqlite3_bind_double(pStmt, idx, value);
1531c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
153251e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
153351e3d8e2Sdanielk1977     return TCL_ERROR;
153451e3d8e2Sdanielk1977   }
153551e3d8e2Sdanielk1977 
153651e3d8e2Sdanielk1977   return TCL_OK;
153751e3d8e2Sdanielk1977 }
153851e3d8e2Sdanielk1977 
1539241db313Sdrh /*
1540241db313Sdrh ** Usage:   sqlite3_bind_null  STMT N
1541241db313Sdrh **
1542241db313Sdrh ** Test the sqlite3_bind_null interface.  STMT is a prepared statement.
1543241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1544241db313Sdrh ** binds a NULL to the wildcard.
1545241db313Sdrh */
154651e3d8e2Sdanielk1977 static int test_bind_null(
154751e3d8e2Sdanielk1977   void * clientData,
154851e3d8e2Sdanielk1977   Tcl_Interp *interp,
154951e3d8e2Sdanielk1977   int objc,
155051e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
155151e3d8e2Sdanielk1977 ){
155251e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
155351e3d8e2Sdanielk1977   int idx;
155451e3d8e2Sdanielk1977   int rc;
155551e3d8e2Sdanielk1977 
155651e3d8e2Sdanielk1977   if( objc!=3 ){
155751e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1558241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
155951e3d8e2Sdanielk1977     return TCL_ERROR;
156051e3d8e2Sdanielk1977   }
156151e3d8e2Sdanielk1977 
156251e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
156351e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
156451e3d8e2Sdanielk1977 
156551e3d8e2Sdanielk1977   rc = sqlite3_bind_null(pStmt, idx);
1566c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
156751e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
156851e3d8e2Sdanielk1977     return TCL_ERROR;
156951e3d8e2Sdanielk1977   }
157051e3d8e2Sdanielk1977 
157151e3d8e2Sdanielk1977   return TCL_OK;
157251e3d8e2Sdanielk1977 }
157351e3d8e2Sdanielk1977 
1574241db313Sdrh /*
1575241db313Sdrh ** Usage:   sqlite3_bind_text  STMT N STRING BYTES
1576241db313Sdrh **
1577241db313Sdrh ** Test the sqlite3_bind_text interface.  STMT is a prepared statement.
1578241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1579241db313Sdrh ** binds a UTF-8 string STRING to the wildcard.  The string is BYTES bytes
1580241db313Sdrh ** long.
1581241db313Sdrh */
158251e3d8e2Sdanielk1977 static int test_bind_text(
158351e3d8e2Sdanielk1977   void * clientData,
158451e3d8e2Sdanielk1977   Tcl_Interp *interp,
158551e3d8e2Sdanielk1977   int objc,
158651e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
158751e3d8e2Sdanielk1977 ){
158851e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
158951e3d8e2Sdanielk1977   int idx;
159051e3d8e2Sdanielk1977   int bytes;
159151e3d8e2Sdanielk1977   char *value;
159251e3d8e2Sdanielk1977   int rc;
159351e3d8e2Sdanielk1977 
159451e3d8e2Sdanielk1977   if( objc!=5 ){
159551e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1596241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
159751e3d8e2Sdanielk1977     return TCL_ERROR;
159851e3d8e2Sdanielk1977   }
159951e3d8e2Sdanielk1977 
160051e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
160151e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
160251e3d8e2Sdanielk1977   value = Tcl_GetString(objv[3]);
160351e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
160451e3d8e2Sdanielk1977 
1605d8123366Sdanielk1977   rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
1606c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
160751e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
1608473d179dSdrh     Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
160951e3d8e2Sdanielk1977     return TCL_ERROR;
161051e3d8e2Sdanielk1977   }
161151e3d8e2Sdanielk1977 
161251e3d8e2Sdanielk1977   return TCL_OK;
161351e3d8e2Sdanielk1977 }
161451e3d8e2Sdanielk1977 
1615241db313Sdrh /*
1616241db313Sdrh ** Usage:   sqlite3_bind_text16  STMT N STRING BYTES
1617241db313Sdrh **
1618241db313Sdrh ** Test the sqlite3_bind_text16 interface.  STMT is a prepared statement.
1619241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1620241db313Sdrh ** binds a UTF-16 string STRING to the wildcard.  The string is BYTES bytes
1621241db313Sdrh ** long.
1622241db313Sdrh */
162351e3d8e2Sdanielk1977 static int test_bind_text16(
162451e3d8e2Sdanielk1977   void * clientData,
162551e3d8e2Sdanielk1977   Tcl_Interp *interp,
162651e3d8e2Sdanielk1977   int objc,
162751e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
162851e3d8e2Sdanielk1977 ){
16295436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
163051e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
163151e3d8e2Sdanielk1977   int idx;
163251e3d8e2Sdanielk1977   int bytes;
163351e3d8e2Sdanielk1977   char *value;
163451e3d8e2Sdanielk1977   int rc;
163551e3d8e2Sdanielk1977 
163651e3d8e2Sdanielk1977   if( objc!=5 ){
163751e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1638241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
163951e3d8e2Sdanielk1977     return TCL_ERROR;
164051e3d8e2Sdanielk1977   }
164151e3d8e2Sdanielk1977 
164251e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
164351e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
164451e3d8e2Sdanielk1977   value = Tcl_GetByteArrayFromObj(objv[3], 0);
164551e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
164651e3d8e2Sdanielk1977 
1647d8123366Sdanielk1977   rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, SQLITE_TRANSIENT);
1648c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
164951e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
165051e3d8e2Sdanielk1977     return TCL_ERROR;
165151e3d8e2Sdanielk1977   }
165251e3d8e2Sdanielk1977 
16535436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
165451e3d8e2Sdanielk1977   return TCL_OK;
165551e3d8e2Sdanielk1977 }
165651e3d8e2Sdanielk1977 
1657241db313Sdrh /*
1658241db313Sdrh ** Usage:   sqlite3_bind_blob  STMT N DATA BYTES
1659241db313Sdrh **
1660241db313Sdrh ** Test the sqlite3_bind_blob interface.  STMT is a prepared statement.
1661241db313Sdrh ** N is the index of a wildcard in the prepared statement.  This command
1662241db313Sdrh ** binds a BLOB to the wildcard.  The BLOB is BYTES bytes in size.
1663241db313Sdrh */
166451e3d8e2Sdanielk1977 static int test_bind_blob(
166551e3d8e2Sdanielk1977   void * clientData,
166651e3d8e2Sdanielk1977   Tcl_Interp *interp,
166751e3d8e2Sdanielk1977   int objc,
166851e3d8e2Sdanielk1977   Tcl_Obj *CONST objv[]
166951e3d8e2Sdanielk1977 ){
167051e3d8e2Sdanielk1977   sqlite3_stmt *pStmt;
167151e3d8e2Sdanielk1977   int idx;
167251e3d8e2Sdanielk1977   int bytes;
167351e3d8e2Sdanielk1977   char *value;
167451e3d8e2Sdanielk1977   int rc;
167551e3d8e2Sdanielk1977 
167651e3d8e2Sdanielk1977   if( objc!=5 ){
167751e3d8e2Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
1678241db313Sdrh         Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
167951e3d8e2Sdanielk1977     return TCL_ERROR;
168051e3d8e2Sdanielk1977   }
168151e3d8e2Sdanielk1977 
168251e3d8e2Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
168351e3d8e2Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
168451e3d8e2Sdanielk1977   value = Tcl_GetString(objv[3]);
168549e4643eSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
168651e3d8e2Sdanielk1977 
1687d8123366Sdanielk1977   rc = sqlite3_bind_blob(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
1688c60d0446Sdrh   if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
168951e3d8e2Sdanielk1977   if( rc!=SQLITE_OK ){
169051e3d8e2Sdanielk1977     return TCL_ERROR;
169151e3d8e2Sdanielk1977   }
169251e3d8e2Sdanielk1977 
169351e3d8e2Sdanielk1977   return TCL_OK;
169451e3d8e2Sdanielk1977 }
169551e3d8e2Sdanielk1977 
169699ee3600Sdrh /*
169775f6a032Sdrh ** Usage:   sqlite3_bind_parameter_count  STMT
169875f6a032Sdrh **
169975f6a032Sdrh ** Return the number of wildcards in the given statement.
170075f6a032Sdrh */
170175f6a032Sdrh static int test_bind_parameter_count(
170275f6a032Sdrh   void * clientData,
170375f6a032Sdrh   Tcl_Interp *interp,
170475f6a032Sdrh   int objc,
170575f6a032Sdrh   Tcl_Obj *CONST objv[]
170675f6a032Sdrh ){
170775f6a032Sdrh   sqlite3_stmt *pStmt;
170875f6a032Sdrh 
170975f6a032Sdrh   if( objc!=2 ){
171075f6a032Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "STMT");
171175f6a032Sdrh     return TCL_ERROR;
171275f6a032Sdrh   }
171375f6a032Sdrh   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
171475f6a032Sdrh   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
171575f6a032Sdrh   return TCL_OK;
171675f6a032Sdrh }
171775f6a032Sdrh 
171875f6a032Sdrh /*
1719895d7472Sdrh ** Usage:   sqlite3_bind_parameter_name  STMT  N
1720895d7472Sdrh **
1721895d7472Sdrh ** Return the name of the Nth wildcard.  The first wildcard is 1.
1722895d7472Sdrh ** An empty string is returned if N is out of range or if the wildcard
1723895d7472Sdrh ** is nameless.
1724895d7472Sdrh */
1725895d7472Sdrh static int test_bind_parameter_name(
1726895d7472Sdrh   void * clientData,
1727895d7472Sdrh   Tcl_Interp *interp,
1728895d7472Sdrh   int objc,
1729895d7472Sdrh   Tcl_Obj *CONST objv[]
1730895d7472Sdrh ){
1731895d7472Sdrh   sqlite3_stmt *pStmt;
1732895d7472Sdrh   int i;
1733895d7472Sdrh 
1734895d7472Sdrh   if( objc!=3 ){
1735895d7472Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
1736895d7472Sdrh     return TCL_ERROR;
1737895d7472Sdrh   }
1738895d7472Sdrh   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1739895d7472Sdrh   if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
1740895d7472Sdrh   Tcl_SetObjResult(interp,
1741895d7472Sdrh      Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
1742895d7472Sdrh   );
1743895d7472Sdrh   return TCL_OK;
1744895d7472Sdrh }
1745895d7472Sdrh 
1746895d7472Sdrh /*
1747fa6bc000Sdrh ** Usage:   sqlite3_bind_parameter_index  STMT  NAME
1748fa6bc000Sdrh **
1749fa6bc000Sdrh ** Return the index of the wildcard called NAME.  Return 0 if there is
1750fa6bc000Sdrh ** no such wildcard.
1751fa6bc000Sdrh */
1752fa6bc000Sdrh static int test_bind_parameter_index(
1753fa6bc000Sdrh   void * clientData,
1754fa6bc000Sdrh   Tcl_Interp *interp,
1755fa6bc000Sdrh   int objc,
1756fa6bc000Sdrh   Tcl_Obj *CONST objv[]
1757fa6bc000Sdrh ){
1758fa6bc000Sdrh   sqlite3_stmt *pStmt;
1759fa6bc000Sdrh 
1760fa6bc000Sdrh   if( objc!=3 ){
1761fa6bc000Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
1762fa6bc000Sdrh     return TCL_ERROR;
1763fa6bc000Sdrh   }
1764fa6bc000Sdrh   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1765fa6bc000Sdrh   Tcl_SetObjResult(interp,
1766fa6bc000Sdrh      Tcl_NewIntObj(
1767fa6bc000Sdrh        sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
1768fa6bc000Sdrh      )
1769fa6bc000Sdrh   );
1770fa6bc000Sdrh   return TCL_OK;
1771fa6bc000Sdrh }
1772fa6bc000Sdrh 
1773fa6bc000Sdrh /*
1774600dd0baSdanielk1977 ** Usage:   sqlite3_clear_bindings STMT
1775600dd0baSdanielk1977 **
1776600dd0baSdanielk1977 */
1777600dd0baSdanielk1977 #if 0
1778600dd0baSdanielk1977 static int test_clear_bindings(
1779600dd0baSdanielk1977   void * clientData,
1780600dd0baSdanielk1977   Tcl_Interp *interp,
1781600dd0baSdanielk1977   int objc,
1782600dd0baSdanielk1977   Tcl_Obj *CONST objv[]
1783600dd0baSdanielk1977 ){
1784600dd0baSdanielk1977   sqlite3_stmt *pStmt;
1785600dd0baSdanielk1977 
1786600dd0baSdanielk1977   if( objc!=2 ){
1787600dd0baSdanielk1977     Tcl_WrongNumArgs(interp, 1, objv, "STMT");
1788600dd0baSdanielk1977     return TCL_ERROR;
1789600dd0baSdanielk1977   }
1790600dd0baSdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1791600dd0baSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
1792600dd0baSdanielk1977   return TCL_OK;
1793600dd0baSdanielk1977 }
1794600dd0baSdanielk1977 #endif
1795600dd0baSdanielk1977 
1796600dd0baSdanielk1977 /*
17976622cce3Sdanielk1977 ** Usage: sqlite3_errcode DB
17986622cce3Sdanielk1977 **
17996622cce3Sdanielk1977 ** Return the string representation of the most recent sqlite3_* API
18006622cce3Sdanielk1977 ** error code. e.g. "SQLITE_ERROR".
18016622cce3Sdanielk1977 */
18026622cce3Sdanielk1977 static int test_errcode(
18036622cce3Sdanielk1977   void * clientData,
18046622cce3Sdanielk1977   Tcl_Interp *interp,
18056622cce3Sdanielk1977   int objc,
18066622cce3Sdanielk1977   Tcl_Obj *CONST objv[]
18076622cce3Sdanielk1977 ){
18086622cce3Sdanielk1977   sqlite3 *db;
18096622cce3Sdanielk1977 
18106622cce3Sdanielk1977   if( objc!=2 ){
18116622cce3Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
18126622cce3Sdanielk1977        Tcl_GetString(objv[0]), " DB", 0);
18136622cce3Sdanielk1977     return TCL_ERROR;
18146622cce3Sdanielk1977   }
18156622cce3Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
18166622cce3Sdanielk1977   Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0);
18176622cce3Sdanielk1977   return TCL_OK;
18186622cce3Sdanielk1977 }
18196622cce3Sdanielk1977 
18206622cce3Sdanielk1977 /*
18216622cce3Sdanielk1977 ** Usage:   test_errmsg DB
18226622cce3Sdanielk1977 **
18236622cce3Sdanielk1977 ** Returns the UTF-8 representation of the error message string for the
18246622cce3Sdanielk1977 ** most recent sqlite3_* API call.
18256622cce3Sdanielk1977 */
18266622cce3Sdanielk1977 static int test_errmsg(
18276622cce3Sdanielk1977   void * clientData,
18286622cce3Sdanielk1977   Tcl_Interp *interp,
18296622cce3Sdanielk1977   int objc,
18306622cce3Sdanielk1977   Tcl_Obj *CONST objv[]
18316622cce3Sdanielk1977 ){
18329bb575fdSdrh   sqlite3 *db;
18336622cce3Sdanielk1977   const char *zErr;
18346622cce3Sdanielk1977 
18356622cce3Sdanielk1977   if( objc!=2 ){
18366622cce3Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
18376622cce3Sdanielk1977        Tcl_GetString(objv[0]), " DB", 0);
18386622cce3Sdanielk1977     return TCL_ERROR;
18396622cce3Sdanielk1977   }
18406622cce3Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
18416622cce3Sdanielk1977 
18426622cce3Sdanielk1977   zErr = sqlite3_errmsg(db);
18436622cce3Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
18446622cce3Sdanielk1977   return TCL_OK;
18456622cce3Sdanielk1977 }
18466622cce3Sdanielk1977 
18476622cce3Sdanielk1977 /*
18486622cce3Sdanielk1977 ** Usage:   test_errmsg16 DB
18496622cce3Sdanielk1977 **
18506622cce3Sdanielk1977 ** Returns the UTF-16 representation of the error message string for the
18516622cce3Sdanielk1977 ** most recent sqlite3_* API call. This is a byte array object at the TCL
18526622cce3Sdanielk1977 ** level, and it includes the 0x00 0x00 terminator bytes at the end of the
18536622cce3Sdanielk1977 ** UTF-16 string.
18546622cce3Sdanielk1977 */
18556622cce3Sdanielk1977 static int test_errmsg16(
18566622cce3Sdanielk1977   void * clientData,
18576622cce3Sdanielk1977   Tcl_Interp *interp,
18586622cce3Sdanielk1977   int objc,
18596622cce3Sdanielk1977   Tcl_Obj *CONST objv[]
18606622cce3Sdanielk1977 ){
18615436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
18629bb575fdSdrh   sqlite3 *db;
18636622cce3Sdanielk1977   const void *zErr;
18646622cce3Sdanielk1977   int bytes;
18656622cce3Sdanielk1977 
18666622cce3Sdanielk1977   if( objc!=2 ){
18676622cce3Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
18686622cce3Sdanielk1977        Tcl_GetString(objv[0]), " DB", 0);
18696622cce3Sdanielk1977     return TCL_ERROR;
18706622cce3Sdanielk1977   }
18716622cce3Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
18726622cce3Sdanielk1977 
18736622cce3Sdanielk1977   zErr = sqlite3_errmsg16(db);
18746622cce3Sdanielk1977   bytes = sqlite3utf16ByteLen(zErr, -1);
18756622cce3Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
18765436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
18776622cce3Sdanielk1977   return TCL_OK;
18786622cce3Sdanielk1977 }
18796622cce3Sdanielk1977 
18806622cce3Sdanielk1977 /*
18816622cce3Sdanielk1977 ** Usage: sqlite3_prepare DB sql bytes tailvar
18826622cce3Sdanielk1977 **
18836622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
18846622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global
18856622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A
18866622cce3Sdanielk1977 ** STMT handle is returned.
18876622cce3Sdanielk1977 */
18886622cce3Sdanielk1977 static int test_prepare(
18896622cce3Sdanielk1977   void * clientData,
18906622cce3Sdanielk1977   Tcl_Interp *interp,
18916622cce3Sdanielk1977   int objc,
18926622cce3Sdanielk1977   Tcl_Obj *CONST objv[]
18936622cce3Sdanielk1977 ){
18946622cce3Sdanielk1977   sqlite3 *db;
18956622cce3Sdanielk1977   const char *zSql;
18966622cce3Sdanielk1977   int bytes;
18976622cce3Sdanielk1977   const char *zTail = 0;
18986622cce3Sdanielk1977   sqlite3_stmt *pStmt = 0;
18996622cce3Sdanielk1977   char zBuf[50];
19004ad1713cSdanielk1977   int rc;
19016622cce3Sdanielk1977 
19026622cce3Sdanielk1977   if( objc!=5 ){
19036622cce3Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
19046622cce3Sdanielk1977        Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
19056622cce3Sdanielk1977     return TCL_ERROR;
19066622cce3Sdanielk1977   }
19076622cce3Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
19086622cce3Sdanielk1977   zSql = Tcl_GetString(objv[2]);
19096622cce3Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
19106622cce3Sdanielk1977 
19114ad1713cSdanielk1977   rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail);
1912c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
19136622cce3Sdanielk1977   if( zTail ){
19146622cce3Sdanielk1977     if( bytes>=0 ){
19156622cce3Sdanielk1977       bytes = bytes - (zTail-zSql);
19166622cce3Sdanielk1977     }
19176622cce3Sdanielk1977     Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
19186622cce3Sdanielk1977   }
19194ad1713cSdanielk1977   if( rc!=SQLITE_OK ){
19204ad1713cSdanielk1977     assert( pStmt==0 );
19214ad1713cSdanielk1977     sprintf(zBuf, "(%d) ", rc);
19224ad1713cSdanielk1977     Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
19234ad1713cSdanielk1977     return TCL_ERROR;
19244ad1713cSdanielk1977   }
19256622cce3Sdanielk1977 
19264ad1713cSdanielk1977   if( pStmt ){
19276622cce3Sdanielk1977     if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
19286622cce3Sdanielk1977     Tcl_AppendResult(interp, zBuf, 0);
19294ad1713cSdanielk1977   }
19306622cce3Sdanielk1977   return TCL_OK;
19316622cce3Sdanielk1977 }
19326622cce3Sdanielk1977 
19336622cce3Sdanielk1977 /*
19346622cce3Sdanielk1977 ** Usage: sqlite3_prepare DB sql bytes tailvar
19356622cce3Sdanielk1977 **
19366622cce3Sdanielk1977 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
19376622cce3Sdanielk1977 ** database handle <DB>. The parameter <tailval> is the name of a global
19386622cce3Sdanielk1977 ** variable that is set to the unused portion of <sql> (if any). A
19396622cce3Sdanielk1977 ** STMT handle is returned.
19406622cce3Sdanielk1977 */
19416622cce3Sdanielk1977 static int test_prepare16(
19426622cce3Sdanielk1977   void * clientData,
19436622cce3Sdanielk1977   Tcl_Interp *interp,
19446622cce3Sdanielk1977   int objc,
19456622cce3Sdanielk1977   Tcl_Obj *CONST objv[]
19466622cce3Sdanielk1977 ){
19475436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
19486622cce3Sdanielk1977   sqlite3 *db;
19496622cce3Sdanielk1977   const void *zSql;
19506622cce3Sdanielk1977   const void *zTail = 0;
19516622cce3Sdanielk1977   Tcl_Obj *pTail = 0;
19526622cce3Sdanielk1977   sqlite3_stmt *pStmt = 0;
19536622cce3Sdanielk1977   char zBuf[50];
1954c60d0446Sdrh   int rc;
19556622cce3Sdanielk1977   int bytes;                /* The integer specified as arg 3 */
19566622cce3Sdanielk1977   int objlen;               /* The byte-array length of arg 2 */
19576622cce3Sdanielk1977 
19586622cce3Sdanielk1977   if( objc!=5 ){
19596622cce3Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
19606622cce3Sdanielk1977        Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
19616622cce3Sdanielk1977     return TCL_ERROR;
19626622cce3Sdanielk1977   }
19636622cce3Sdanielk1977   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
19646622cce3Sdanielk1977   zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
19656622cce3Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
19666622cce3Sdanielk1977 
1967c60d0446Sdrh   rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail);
1968c60d0446Sdrh   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
1969c60d0446Sdrh   if( rc ){
19706622cce3Sdanielk1977     return TCL_ERROR;
19716622cce3Sdanielk1977   }
19726622cce3Sdanielk1977 
19736622cce3Sdanielk1977   if( zTail ){
19746622cce3Sdanielk1977     objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
19756622cce3Sdanielk1977   }else{
19766622cce3Sdanielk1977     objlen = 0;
19776622cce3Sdanielk1977   }
19786622cce3Sdanielk1977   pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
19796622cce3Sdanielk1977   Tcl_IncrRefCount(pTail);
19806622cce3Sdanielk1977   Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
19814ad1713cSdanielk1977   Tcl_DecrRefCount(pTail);
19826622cce3Sdanielk1977 
19834ad1713cSdanielk1977   if( pStmt ){
19846622cce3Sdanielk1977     if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
19854ad1713cSdanielk1977   }
19866622cce3Sdanielk1977   Tcl_AppendResult(interp, zBuf, 0);
19875436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
19886622cce3Sdanielk1977   return TCL_OK;
19896622cce3Sdanielk1977 }
19906622cce3Sdanielk1977 
19914ad1713cSdanielk1977 /*
19924ad1713cSdanielk1977 ** Usage: sqlite3_open filename ?options-list?
19934ad1713cSdanielk1977 */
19944ad1713cSdanielk1977 static int test_open(
19954ad1713cSdanielk1977   void * clientData,
19964ad1713cSdanielk1977   Tcl_Interp *interp,
19974ad1713cSdanielk1977   int objc,
19984ad1713cSdanielk1977   Tcl_Obj *CONST objv[]
19994ad1713cSdanielk1977 ){
20004ad1713cSdanielk1977   const char *zFilename;
20014ad1713cSdanielk1977   sqlite3 *db;
20024ad1713cSdanielk1977   int rc;
20034ad1713cSdanielk1977   char zBuf[100];
20044ad1713cSdanielk1977 
20054ad1713cSdanielk1977   if( objc!=3 && objc!=2 ){
20064ad1713cSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
20074ad1713cSdanielk1977        Tcl_GetString(objv[0]), " filename options-list", 0);
20084ad1713cSdanielk1977     return TCL_ERROR;
20094ad1713cSdanielk1977   }
20104ad1713cSdanielk1977 
20114ad1713cSdanielk1977   zFilename = Tcl_GetString(objv[1]);
20124f057f90Sdanielk1977   rc = sqlite3_open(zFilename, &db);
20134ad1713cSdanielk1977 
20144ad1713cSdanielk1977   if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
20154ad1713cSdanielk1977   Tcl_AppendResult(interp, zBuf, 0);
20164ad1713cSdanielk1977   return TCL_OK;
20174ad1713cSdanielk1977 }
20184ad1713cSdanielk1977 
20194ad1713cSdanielk1977 /*
20204ad1713cSdanielk1977 ** Usage: sqlite3_open16 filename options
20214ad1713cSdanielk1977 */
20224ad1713cSdanielk1977 static int test_open16(
20234ad1713cSdanielk1977   void * clientData,
20244ad1713cSdanielk1977   Tcl_Interp *interp,
20254ad1713cSdanielk1977   int objc,
20264ad1713cSdanielk1977   Tcl_Obj *CONST objv[]
20274ad1713cSdanielk1977 ){
20285436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
20294ad1713cSdanielk1977   const void *zFilename;
20304ad1713cSdanielk1977   sqlite3 *db;
20314ad1713cSdanielk1977   int rc;
20324ad1713cSdanielk1977   char zBuf[100];
20334ad1713cSdanielk1977 
20344ad1713cSdanielk1977   if( objc!=3 ){
20354ad1713cSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
20364ad1713cSdanielk1977        Tcl_GetString(objv[0]), " filename options-list", 0);
20374ad1713cSdanielk1977     return TCL_ERROR;
20384ad1713cSdanielk1977   }
20394ad1713cSdanielk1977 
20404ad1713cSdanielk1977   zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
20414f057f90Sdanielk1977   rc = sqlite3_open16(zFilename, &db);
20424ad1713cSdanielk1977 
20434ad1713cSdanielk1977   if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
20444ad1713cSdanielk1977   Tcl_AppendResult(interp, zBuf, 0);
20455436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
20464ad1713cSdanielk1977   return TCL_OK;
20474ad1713cSdanielk1977 }
2048d3d39e93Sdrh 
2049d3d39e93Sdrh /*
2050bc6ada41Sdanielk1977 ** Usage: sqlite3_complete16 <UTF-16 string>
2051bc6ada41Sdanielk1977 **
2052bc6ada41Sdanielk1977 ** Return 1 if the supplied argument is a complete SQL statement, or zero
2053bc6ada41Sdanielk1977 ** otherwise.
2054bc6ada41Sdanielk1977 */
2055bc6ada41Sdanielk1977 static int test_complete16(
2056bc6ada41Sdanielk1977   void * clientData,
2057bc6ada41Sdanielk1977   Tcl_Interp *interp,
2058bc6ada41Sdanielk1977   int objc,
2059bc6ada41Sdanielk1977   Tcl_Obj *CONST objv[]
2060bc6ada41Sdanielk1977 ){
2061ccae6026Sdrh #if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16)
2062bc6ada41Sdanielk1977   char *zBuf;
2063bc6ada41Sdanielk1977 
2064bc6ada41Sdanielk1977   if( objc!=2 ){
2065bc6ada41Sdanielk1977     Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
2066bc6ada41Sdanielk1977     return TCL_ERROR;
2067bc6ada41Sdanielk1977   }
2068bc6ada41Sdanielk1977 
2069bc6ada41Sdanielk1977   zBuf = Tcl_GetByteArrayFromObj(objv[1], 0);
2070bc6ada41Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
2071ccae6026Sdrh #endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */
2072bc6ada41Sdanielk1977   return TCL_OK;
2073bc6ada41Sdanielk1977 }
2074bc6ada41Sdanielk1977 
2075bc6ada41Sdanielk1977 /*
2076106bb236Sdanielk1977 ** Usage: sqlite3_step STMT
2077106bb236Sdanielk1977 **
2078106bb236Sdanielk1977 ** Advance the statement to the next row.
2079106bb236Sdanielk1977 */
208017240fd9Sdanielk1977 static int test_step(
2081106bb236Sdanielk1977   void * clientData,
2082106bb236Sdanielk1977   Tcl_Interp *interp,
2083106bb236Sdanielk1977   int objc,
2084106bb236Sdanielk1977   Tcl_Obj *CONST objv[]
2085106bb236Sdanielk1977 ){
2086106bb236Sdanielk1977   sqlite3_stmt *pStmt;
2087106bb236Sdanielk1977   int rc;
2088106bb236Sdanielk1977 
2089e1cd9874Sdanielk1977   if( objc!=2 ){
2090106bb236Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
2091106bb236Sdanielk1977        Tcl_GetString(objv[0]), " STMT", 0);
2092106bb236Sdanielk1977     return TCL_ERROR;
2093106bb236Sdanielk1977   }
2094106bb236Sdanielk1977 
2095106bb236Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
209617240fd9Sdanielk1977   rc = sqlite3_step(pStmt);
2097106bb236Sdanielk1977 
2098fbcd585fSdanielk1977   /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
20996590493dSdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), 0);
2100e1cd9874Sdanielk1977   return TCL_OK;
2101e1cd9874Sdanielk1977 }
2102e1cd9874Sdanielk1977 
2103e1cd9874Sdanielk1977 /*
210417240fd9Sdanielk1977 ** Usage: sqlite3_column_count STMT
210517240fd9Sdanielk1977 **
210617240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT.
210717240fd9Sdanielk1977 */
210817240fd9Sdanielk1977 static int test_column_count(
210917240fd9Sdanielk1977   void * clientData,
211017240fd9Sdanielk1977   Tcl_Interp *interp,
211117240fd9Sdanielk1977   int objc,
211217240fd9Sdanielk1977   Tcl_Obj *CONST objv[]
211317240fd9Sdanielk1977 ){
211417240fd9Sdanielk1977   sqlite3_stmt *pStmt;
211517240fd9Sdanielk1977 
211617240fd9Sdanielk1977   if( objc!=2 ){
211717240fd9Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
211817240fd9Sdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
211917240fd9Sdanielk1977     return TCL_ERROR;
212017240fd9Sdanielk1977   }
212117240fd9Sdanielk1977 
212217240fd9Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
212317240fd9Sdanielk1977 
212417240fd9Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
212517240fd9Sdanielk1977   return TCL_OK;
212617240fd9Sdanielk1977 }
212717240fd9Sdanielk1977 
212817240fd9Sdanielk1977 /*
21293cf86063Sdanielk1977 ** Usage: sqlite3_column_type STMT column
21303cf86063Sdanielk1977 **
21313cf86063Sdanielk1977 ** Return the type of the data in column 'column' of the current row.
21323cf86063Sdanielk1977 */
21333cf86063Sdanielk1977 static int test_column_type(
21343cf86063Sdanielk1977   void * clientData,
21353cf86063Sdanielk1977   Tcl_Interp *interp,
21363cf86063Sdanielk1977   int objc,
21373cf86063Sdanielk1977   Tcl_Obj *CONST objv[]
21383cf86063Sdanielk1977 ){
21393cf86063Sdanielk1977   sqlite3_stmt *pStmt;
21403cf86063Sdanielk1977   int col;
21413cf86063Sdanielk1977   int tp;
21423cf86063Sdanielk1977 
21433cf86063Sdanielk1977   if( objc!=3 ){
21443cf86063Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
21453cf86063Sdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
21463cf86063Sdanielk1977     return TCL_ERROR;
21473cf86063Sdanielk1977   }
21483cf86063Sdanielk1977 
21493cf86063Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
21503cf86063Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
21513cf86063Sdanielk1977 
21523cf86063Sdanielk1977   tp = sqlite3_column_type(pStmt, col);
21533cf86063Sdanielk1977   switch( tp ){
21549c054830Sdrh     case SQLITE_INTEGER:
21553cf86063Sdanielk1977       Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
21563cf86063Sdanielk1977       break;
21579c054830Sdrh     case SQLITE_NULL:
21583cf86063Sdanielk1977       Tcl_SetResult(interp, "NULL", TCL_STATIC);
21593cf86063Sdanielk1977       break;
21609c054830Sdrh     case SQLITE_FLOAT:
21613cf86063Sdanielk1977       Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
21623cf86063Sdanielk1977       break;
21639c054830Sdrh     case SQLITE_TEXT:
21643cf86063Sdanielk1977       Tcl_SetResult(interp, "TEXT", TCL_STATIC);
21653cf86063Sdanielk1977       break;
21669c054830Sdrh     case SQLITE_BLOB:
21673cf86063Sdanielk1977       Tcl_SetResult(interp, "BLOB", TCL_STATIC);
21683cf86063Sdanielk1977       break;
21693cf86063Sdanielk1977     default:
21703cf86063Sdanielk1977       assert(0);
21713cf86063Sdanielk1977   }
21723cf86063Sdanielk1977 
21733cf86063Sdanielk1977   return TCL_OK;
21743cf86063Sdanielk1977 }
21753cf86063Sdanielk1977 
21763cf86063Sdanielk1977 /*
217704f2e68dSdanielk1977 ** Usage: sqlite3_column_int64 STMT column
21783cf86063Sdanielk1977 **
21793cf86063Sdanielk1977 ** Return the data in column 'column' of the current row cast as an
218004f2e68dSdanielk1977 ** wide (64-bit) integer.
21813cf86063Sdanielk1977 */
218204f2e68dSdanielk1977 static int test_column_int64(
21833cf86063Sdanielk1977   void * clientData,
21843cf86063Sdanielk1977   Tcl_Interp *interp,
21853cf86063Sdanielk1977   int objc,
21863cf86063Sdanielk1977   Tcl_Obj *CONST objv[]
21873cf86063Sdanielk1977 ){
21883cf86063Sdanielk1977   sqlite3_stmt *pStmt;
21893cf86063Sdanielk1977   int col;
219004f2e68dSdanielk1977   i64 iVal;
21913cf86063Sdanielk1977 
21923cf86063Sdanielk1977   if( objc!=3 ){
21933cf86063Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
21943cf86063Sdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
21953cf86063Sdanielk1977     return TCL_ERROR;
21963cf86063Sdanielk1977   }
21973cf86063Sdanielk1977 
21983cf86063Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
21993cf86063Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
22003cf86063Sdanielk1977 
220104f2e68dSdanielk1977   iVal = sqlite3_column_int64(pStmt, col);
220204f2e68dSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
220304f2e68dSdanielk1977   return TCL_OK;
220404f2e68dSdanielk1977 }
220504f2e68dSdanielk1977 
220604f2e68dSdanielk1977 /*
2207ea61b2c4Sdanielk1977 ** Usage: sqlite3_column_blob STMT column
2208ea61b2c4Sdanielk1977 */
2209ea61b2c4Sdanielk1977 static int test_column_blob(
2210ea61b2c4Sdanielk1977   void * clientData,
2211ea61b2c4Sdanielk1977   Tcl_Interp *interp,
2212ea61b2c4Sdanielk1977   int objc,
2213ea61b2c4Sdanielk1977   Tcl_Obj *CONST objv[]
2214ea61b2c4Sdanielk1977 ){
2215ea61b2c4Sdanielk1977   sqlite3_stmt *pStmt;
2216ea61b2c4Sdanielk1977   int col;
2217ea61b2c4Sdanielk1977 
2218ea61b2c4Sdanielk1977   int len;
2219c572ef7fSdanielk1977   const void *pBlob;
2220ea61b2c4Sdanielk1977 
2221ea61b2c4Sdanielk1977   if( objc!=3 ){
2222ea61b2c4Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
2223ea61b2c4Sdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
2224ea61b2c4Sdanielk1977     return TCL_ERROR;
2225ea61b2c4Sdanielk1977   }
2226ea61b2c4Sdanielk1977 
2227ea61b2c4Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2228ea61b2c4Sdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2229ea61b2c4Sdanielk1977 
2230ea61b2c4Sdanielk1977   pBlob = sqlite3_column_blob(pStmt, col);
2231ea61b2c4Sdanielk1977   len = sqlite3_column_bytes(pStmt, col);
2232ea61b2c4Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
2233ea61b2c4Sdanielk1977   return TCL_OK;
2234ea61b2c4Sdanielk1977 }
2235ea61b2c4Sdanielk1977 
2236ea61b2c4Sdanielk1977 /*
223704f2e68dSdanielk1977 ** Usage: sqlite3_column_double STMT column
223804f2e68dSdanielk1977 **
223904f2e68dSdanielk1977 ** Return the data in column 'column' of the current row cast as a double.
224004f2e68dSdanielk1977 */
224104f2e68dSdanielk1977 static int test_column_double(
224204f2e68dSdanielk1977   void * clientData,
224304f2e68dSdanielk1977   Tcl_Interp *interp,
224404f2e68dSdanielk1977   int objc,
224504f2e68dSdanielk1977   Tcl_Obj *CONST objv[]
224604f2e68dSdanielk1977 ){
224704f2e68dSdanielk1977   sqlite3_stmt *pStmt;
224804f2e68dSdanielk1977   int col;
224904f2e68dSdanielk1977   double rVal;
225004f2e68dSdanielk1977 
225104f2e68dSdanielk1977   if( objc!=3 ){
225204f2e68dSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
225304f2e68dSdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
225404f2e68dSdanielk1977     return TCL_ERROR;
225504f2e68dSdanielk1977   }
225604f2e68dSdanielk1977 
225704f2e68dSdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
225804f2e68dSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
225904f2e68dSdanielk1977 
226004f2e68dSdanielk1977   rVal = sqlite3_column_double(pStmt, col);
2261c572ef7fSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
22623cf86063Sdanielk1977   return TCL_OK;
22633cf86063Sdanielk1977 }
22643cf86063Sdanielk1977 
22653cf86063Sdanielk1977 /*
226617240fd9Sdanielk1977 ** Usage: sqlite3_data_count STMT
226717240fd9Sdanielk1977 **
226817240fd9Sdanielk1977 ** Return the number of columns returned by the sql statement STMT.
226917240fd9Sdanielk1977 */
227017240fd9Sdanielk1977 static int test_data_count(
227117240fd9Sdanielk1977   void * clientData,
227217240fd9Sdanielk1977   Tcl_Interp *interp,
227317240fd9Sdanielk1977   int objc,
227417240fd9Sdanielk1977   Tcl_Obj *CONST objv[]
227517240fd9Sdanielk1977 ){
227617240fd9Sdanielk1977   sqlite3_stmt *pStmt;
227717240fd9Sdanielk1977 
227817240fd9Sdanielk1977   if( objc!=2 ){
227917240fd9Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
228017240fd9Sdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
228117240fd9Sdanielk1977     return TCL_ERROR;
228217240fd9Sdanielk1977   }
228317240fd9Sdanielk1977 
228417240fd9Sdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
228517240fd9Sdanielk1977 
228617240fd9Sdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
228717240fd9Sdanielk1977   return TCL_OK;
228817240fd9Sdanielk1977 }
228917240fd9Sdanielk1977 
229017240fd9Sdanielk1977 /*
229104f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column
229204f2e68dSdanielk1977 **
229304f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column
229404f2e68dSdanielk1977 **
229504f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column
229604f2e68dSdanielk1977 */
229704f2e68dSdanielk1977 static int test_stmt_utf8(
2298241db313Sdrh   void * clientData,        /* Pointer to SQLite API function to be invoke */
229904f2e68dSdanielk1977   Tcl_Interp *interp,
230004f2e68dSdanielk1977   int objc,
230104f2e68dSdanielk1977   Tcl_Obj *CONST objv[]
230204f2e68dSdanielk1977 ){
230304f2e68dSdanielk1977   sqlite3_stmt *pStmt;
230404f2e68dSdanielk1977   int col;
2305c572ef7fSdanielk1977   const char *(*xFunc)(sqlite3_stmt*, int) = clientData;
2306f93bbbeaSdanielk1977   const char *zRet;
230704f2e68dSdanielk1977 
230804f2e68dSdanielk1977   if( objc!=3 ){
230904f2e68dSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
231004f2e68dSdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
231104f2e68dSdanielk1977     return TCL_ERROR;
231204f2e68dSdanielk1977   }
231304f2e68dSdanielk1977 
231404f2e68dSdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
231504f2e68dSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2316f93bbbeaSdanielk1977   zRet = xFunc(pStmt, col);
2317f93bbbeaSdanielk1977   if( zRet ){
2318f93bbbeaSdanielk1977     Tcl_SetResult(interp, (char *)zRet, 0);
2319f93bbbeaSdanielk1977   }
232004f2e68dSdanielk1977   return TCL_OK;
232104f2e68dSdanielk1977 }
232204f2e68dSdanielk1977 
23236b456a2bSdanielk1977 static int test_global_recover(
23246b456a2bSdanielk1977   void * clientData,
23256b456a2bSdanielk1977   Tcl_Interp *interp,
23266b456a2bSdanielk1977   int objc,
23276b456a2bSdanielk1977   Tcl_Obj *CONST objv[]
23286b456a2bSdanielk1977 ){
23296b456a2bSdanielk1977 #ifndef SQLITE_OMIT_GLOBALRECOVER
23306b456a2bSdanielk1977   int rc;
23316b456a2bSdanielk1977   if( objc!=1 ){
23326b456a2bSdanielk1977     Tcl_WrongNumArgs(interp, 1, objv, "");
23336b456a2bSdanielk1977     return TCL_ERROR;
23346b456a2bSdanielk1977   }
23356b456a2bSdanielk1977   rc = sqlite3_global_recover();
23366b456a2bSdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
23376b456a2bSdanielk1977 #endif
23386b456a2bSdanielk1977   return TCL_OK;
23396b456a2bSdanielk1977 }
23406b456a2bSdanielk1977 
234104f2e68dSdanielk1977 /*
234204f2e68dSdanielk1977 ** Usage: sqlite3_column_text STMT column
234304f2e68dSdanielk1977 **
234404f2e68dSdanielk1977 ** Usage: sqlite3_column_decltype STMT column
234504f2e68dSdanielk1977 **
234604f2e68dSdanielk1977 ** Usage: sqlite3_column_name STMT column
234704f2e68dSdanielk1977 */
234804f2e68dSdanielk1977 static int test_stmt_utf16(
2349241db313Sdrh   void * clientData,     /* Pointer to SQLite API function to be invoked */
235004f2e68dSdanielk1977   Tcl_Interp *interp,
235104f2e68dSdanielk1977   int objc,
235204f2e68dSdanielk1977   Tcl_Obj *CONST objv[]
235304f2e68dSdanielk1977 ){
23545436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
235504f2e68dSdanielk1977   sqlite3_stmt *pStmt;
235604f2e68dSdanielk1977   int col;
235704f2e68dSdanielk1977   Tcl_Obj *pRet;
235804f2e68dSdanielk1977   const void *zName16;
2359c572ef7fSdanielk1977   const void *(*xFunc)(sqlite3_stmt*, int) = clientData;
236004f2e68dSdanielk1977 
236104f2e68dSdanielk1977   if( objc!=3 ){
236204f2e68dSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
236304f2e68dSdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
236404f2e68dSdanielk1977     return TCL_ERROR;
236504f2e68dSdanielk1977   }
236604f2e68dSdanielk1977 
236704f2e68dSdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
236804f2e68dSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
236904f2e68dSdanielk1977 
237004f2e68dSdanielk1977   zName16 = xFunc(pStmt, col);
2371f93bbbeaSdanielk1977   if( zName16 ){
237204f2e68dSdanielk1977     pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2);
237304f2e68dSdanielk1977     Tcl_SetObjResult(interp, pRet);
2374f93bbbeaSdanielk1977   }
23755436dc2dSdrh #endif /* SQLITE_OMIT_UTF16 */
237604f2e68dSdanielk1977 
237704f2e68dSdanielk1977   return TCL_OK;
237804f2e68dSdanielk1977 }
237904f2e68dSdanielk1977 
238004f2e68dSdanielk1977 /*
238104f2e68dSdanielk1977 ** Usage: sqlite3_column_int STMT column
238204f2e68dSdanielk1977 **
238304f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes STMT column
238404f2e68dSdanielk1977 **
238504f2e68dSdanielk1977 ** Usage: sqlite3_column_bytes16 STMT column
238604f2e68dSdanielk1977 **
238704f2e68dSdanielk1977 */
238804f2e68dSdanielk1977 static int test_stmt_int(
2389241db313Sdrh   void * clientData,    /* Pointer to SQLite API function to be invoked */
239004f2e68dSdanielk1977   Tcl_Interp *interp,
239104f2e68dSdanielk1977   int objc,
239204f2e68dSdanielk1977   Tcl_Obj *CONST objv[]
239304f2e68dSdanielk1977 ){
239404f2e68dSdanielk1977   sqlite3_stmt *pStmt;
239504f2e68dSdanielk1977   int col;
2396c572ef7fSdanielk1977   int (*xFunc)(sqlite3_stmt*, int) = clientData;
239704f2e68dSdanielk1977 
239804f2e68dSdanielk1977   if( objc!=3 ){
239904f2e68dSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
240004f2e68dSdanielk1977        Tcl_GetString(objv[0]), " STMT column", 0);
240104f2e68dSdanielk1977     return TCL_ERROR;
240204f2e68dSdanielk1977   }
240304f2e68dSdanielk1977 
240404f2e68dSdanielk1977   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
240504f2e68dSdanielk1977   if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
240604f2e68dSdanielk1977 
240704f2e68dSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
240804f2e68dSdanielk1977   return TCL_OK;
240904f2e68dSdanielk1977 }
241004f2e68dSdanielk1977 
241144ee5bf7Sdanielk1977 #ifndef SQLITE_OMIT_DISKIO
24129a1d0abeSdanielk1977 /*
24139a1d0abeSdanielk1977 ** Usage:  sqlite3OsOpenReadWrite <filename>
24149a1d0abeSdanielk1977 */
24159a1d0abeSdanielk1977 static int test_sqlite3OsOpenReadWrite(
24169a1d0abeSdanielk1977   void * clientData,
24179a1d0abeSdanielk1977   Tcl_Interp *interp,
24189a1d0abeSdanielk1977   int objc,
24199a1d0abeSdanielk1977   Tcl_Obj *CONST objv[]
24209a1d0abeSdanielk1977 ){
24219a1d0abeSdanielk1977   OsFile * pFile;
24229a1d0abeSdanielk1977   int rc;
24239a1d0abeSdanielk1977   int dummy;
24249a1d0abeSdanielk1977   char zBuf[100];
242504f2e68dSdanielk1977 
24269a1d0abeSdanielk1977   if( objc!=2 ){
24279a1d0abeSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
24289a1d0abeSdanielk1977        Tcl_GetString(objv[0]), " filename", 0);
24299a1d0abeSdanielk1977     return TCL_ERROR;
24309a1d0abeSdanielk1977   }
24319a1d0abeSdanielk1977 
24329a1d0abeSdanielk1977   pFile = sqliteMalloc(sizeof(OsFile));
24339a1d0abeSdanielk1977   rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), pFile, &dummy);
24349a1d0abeSdanielk1977   if( rc!=SQLITE_OK ){
24359a1d0abeSdanielk1977     sqliteFree(pFile);
24369a1d0abeSdanielk1977     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
24379a1d0abeSdanielk1977     return TCL_ERROR;
24389a1d0abeSdanielk1977   }
24399a1d0abeSdanielk1977   makePointerStr(interp, zBuf, pFile);
24409a1d0abeSdanielk1977   Tcl_SetResult(interp, zBuf, 0);
24419a1d0abeSdanielk1977   return TCL_ERROR;
24429a1d0abeSdanielk1977 }
24439a1d0abeSdanielk1977 
24449a1d0abeSdanielk1977 /*
24459a1d0abeSdanielk1977 ** Usage:  sqlite3OsClose <file handle>
24469a1d0abeSdanielk1977 */
24479a1d0abeSdanielk1977 static int test_sqlite3OsClose(
24489a1d0abeSdanielk1977   void * clientData,
24499a1d0abeSdanielk1977   Tcl_Interp *interp,
24509a1d0abeSdanielk1977   int objc,
24519a1d0abeSdanielk1977   Tcl_Obj *CONST objv[]
24529a1d0abeSdanielk1977 ){
24539a1d0abeSdanielk1977   OsFile * pFile;
24549a1d0abeSdanielk1977   int rc;
24559a1d0abeSdanielk1977 
24569a1d0abeSdanielk1977   if( objc!=2 ){
24579a1d0abeSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
24589a1d0abeSdanielk1977        Tcl_GetString(objv[0]), " filehandle", 0);
24599a1d0abeSdanielk1977     return TCL_ERROR;
24609a1d0abeSdanielk1977   }
24619a1d0abeSdanielk1977 
24629a1d0abeSdanielk1977   if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
24639a1d0abeSdanielk1977     return TCL_ERROR;
24649a1d0abeSdanielk1977   }
24659a1d0abeSdanielk1977   rc = sqlite3OsClose(pFile);
24669a1d0abeSdanielk1977   if( rc!=SQLITE_OK ){
24679a1d0abeSdanielk1977     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
24689a1d0abeSdanielk1977     return TCL_ERROR;
24699a1d0abeSdanielk1977   }
24709a1d0abeSdanielk1977   sqliteFree(pFile);
24719a1d0abeSdanielk1977   return TCL_OK;
24729a1d0abeSdanielk1977 }
24739a1d0abeSdanielk1977 
24749a1d0abeSdanielk1977 /*
24759a1d0abeSdanielk1977 ** Usage:  sqlite3OsLock <file handle> <locktype>
24769a1d0abeSdanielk1977 */
24779a1d0abeSdanielk1977 static int test_sqlite3OsLock(
24789a1d0abeSdanielk1977   void * clientData,
24799a1d0abeSdanielk1977   Tcl_Interp *interp,
24809a1d0abeSdanielk1977   int objc,
24819a1d0abeSdanielk1977   Tcl_Obj *CONST objv[]
24829a1d0abeSdanielk1977 ){
24839a1d0abeSdanielk1977   OsFile * pFile;
24849a1d0abeSdanielk1977   int rc;
24859a1d0abeSdanielk1977 
24869a1d0abeSdanielk1977   if( objc!=3 ){
24879a1d0abeSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
24889a1d0abeSdanielk1977         Tcl_GetString(objv[0]),
24899a1d0abeSdanielk1977         " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
24909a1d0abeSdanielk1977     return TCL_ERROR;
24919a1d0abeSdanielk1977   }
24929a1d0abeSdanielk1977 
24939a1d0abeSdanielk1977   if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
24949a1d0abeSdanielk1977     return TCL_ERROR;
24959a1d0abeSdanielk1977   }
24969a1d0abeSdanielk1977 
24979a1d0abeSdanielk1977   if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){
24989a1d0abeSdanielk1977     rc = sqlite3OsLock(pFile, SHARED_LOCK);
24999a1d0abeSdanielk1977   }
25009a1d0abeSdanielk1977   else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){
25019a1d0abeSdanielk1977     rc = sqlite3OsLock(pFile, RESERVED_LOCK);
25029a1d0abeSdanielk1977   }
25039a1d0abeSdanielk1977   else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){
25049a1d0abeSdanielk1977     rc = sqlite3OsLock(pFile, PENDING_LOCK);
25059a1d0abeSdanielk1977   }
25069a1d0abeSdanielk1977   else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){
25079a1d0abeSdanielk1977     rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK);
25089a1d0abeSdanielk1977   }else{
25099a1d0abeSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
25109a1d0abeSdanielk1977         Tcl_GetString(objv[0]),
25119a1d0abeSdanielk1977         " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
25129a1d0abeSdanielk1977     return TCL_ERROR;
25139a1d0abeSdanielk1977   }
25149a1d0abeSdanielk1977 
25159a1d0abeSdanielk1977   if( rc!=SQLITE_OK ){
25169a1d0abeSdanielk1977     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
25179a1d0abeSdanielk1977     return TCL_ERROR;
25189a1d0abeSdanielk1977   }
25199a1d0abeSdanielk1977   return TCL_OK;
25209a1d0abeSdanielk1977 }
25219a1d0abeSdanielk1977 
25229a1d0abeSdanielk1977 /*
25239a1d0abeSdanielk1977 ** Usage:  sqlite3OsUnlock <file handle>
25249a1d0abeSdanielk1977 */
25259a1d0abeSdanielk1977 static int test_sqlite3OsUnlock(
25269a1d0abeSdanielk1977   void * clientData,
25279a1d0abeSdanielk1977   Tcl_Interp *interp,
25289a1d0abeSdanielk1977   int objc,
25299a1d0abeSdanielk1977   Tcl_Obj *CONST objv[]
25309a1d0abeSdanielk1977 ){
25319a1d0abeSdanielk1977   OsFile * pFile;
25329a1d0abeSdanielk1977   int rc;
25339a1d0abeSdanielk1977 
25349a1d0abeSdanielk1977   if( objc!=2 ){
25359a1d0abeSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"",
25369a1d0abeSdanielk1977        Tcl_GetString(objv[0]), " filehandle", 0);
25379a1d0abeSdanielk1977     return TCL_ERROR;
25389a1d0abeSdanielk1977   }
25399a1d0abeSdanielk1977 
25409a1d0abeSdanielk1977   if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
25419a1d0abeSdanielk1977     return TCL_ERROR;
25429a1d0abeSdanielk1977   }
2543a6abd041Sdrh   rc = sqlite3OsUnlock(pFile, NO_LOCK);
25449a1d0abeSdanielk1977   if( rc!=SQLITE_OK ){
25459a1d0abeSdanielk1977     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
25469a1d0abeSdanielk1977     return TCL_ERROR;
25479a1d0abeSdanielk1977   }
25489a1d0abeSdanielk1977   return TCL_OK;
25499a1d0abeSdanielk1977 }
2550d3d39e93Sdrh 
2551ab3f9feaSdrh /*
2552ab3f9feaSdrh ** Usage:  sqlite3OsTempFileName
2553ab3f9feaSdrh */
2554ab3f9feaSdrh static int test_sqlite3OsTempFileName(
2555ab3f9feaSdrh   void * clientData,
2556ab3f9feaSdrh   Tcl_Interp *interp,
2557ab3f9feaSdrh   int objc,
2558ab3f9feaSdrh   Tcl_Obj *CONST objv[]
2559ab3f9feaSdrh ){
2560ab3f9feaSdrh   char zFile[SQLITE_TEMPNAME_SIZE];
2561ab3f9feaSdrh   int rc;
2562ab3f9feaSdrh 
2563ab3f9feaSdrh   rc = sqlite3OsTempFileName(zFile);
2564ab3f9feaSdrh   if( rc!=SQLITE_OK ){
2565ab3f9feaSdrh     Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2566ab3f9feaSdrh     return TCL_ERROR;
2567ab3f9feaSdrh   }
2568ab3f9feaSdrh   Tcl_AppendResult(interp, zFile, 0);
2569ab3f9feaSdrh   return TCL_OK;
2570ab3f9feaSdrh }
257144ee5bf7Sdanielk1977 #endif
2572d8123366Sdanielk1977 
25736622cce3Sdanielk1977 /*
2574cacb208eSdrh ** Usage:  sqlite_set_magic  DB  MAGIC-NUMBER
2575cacb208eSdrh **
2576cacb208eSdrh ** Set the db->magic value.  This is used to test error recovery logic.
2577cacb208eSdrh */
2578cacb208eSdrh static int sqlite_set_magic(
2579cacb208eSdrh   void * clientData,
2580cacb208eSdrh   Tcl_Interp *interp,
2581cacb208eSdrh   int argc,
2582cacb208eSdrh   char **argv
2583cacb208eSdrh ){
2584cacb208eSdrh   sqlite3 *db;
2585cacb208eSdrh   if( argc!=3 ){
2586cacb208eSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2587cacb208eSdrh          " DB MAGIC", 0);
2588cacb208eSdrh     return TCL_ERROR;
2589cacb208eSdrh   }
2590cacb208eSdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2591cacb208eSdrh   if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
2592cacb208eSdrh     db->magic = SQLITE_MAGIC_OPEN;
2593cacb208eSdrh   }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
2594cacb208eSdrh     db->magic = SQLITE_MAGIC_CLOSED;
2595cacb208eSdrh   }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
2596cacb208eSdrh     db->magic = SQLITE_MAGIC_BUSY;
2597cacb208eSdrh   }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
2598cacb208eSdrh     db->magic = SQLITE_MAGIC_ERROR;
2599cacb208eSdrh   }else if( Tcl_GetInt(interp, argv[2], &db->magic) ){
2600cacb208eSdrh     return TCL_ERROR;
2601cacb208eSdrh   }
2602cacb208eSdrh   return TCL_OK;
2603cacb208eSdrh }
2604cacb208eSdrh 
2605cacb208eSdrh /*
2606c5cdca61Sdrh ** Usage:  sqlite3_interrupt  DB
2607c5cdca61Sdrh **
2608c5cdca61Sdrh ** Trigger an interrupt on DB
2609c5cdca61Sdrh */
2610c5cdca61Sdrh static int test_interrupt(
2611c5cdca61Sdrh   void * clientData,
2612c5cdca61Sdrh   Tcl_Interp *interp,
2613c5cdca61Sdrh   int argc,
2614c5cdca61Sdrh   char **argv
2615c5cdca61Sdrh ){
2616c5cdca61Sdrh   sqlite3 *db;
2617c5cdca61Sdrh   if( argc!=2 ){
2618c5cdca61Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
2619c5cdca61Sdrh     return TCL_ERROR;
2620c5cdca61Sdrh   }
2621c5cdca61Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2622c5cdca61Sdrh   sqlite3_interrupt(db);
2623c5cdca61Sdrh   return TCL_OK;
2624c5cdca61Sdrh }
2625c5cdca61Sdrh 
2626c5cdca61Sdrh /*
2627600dd0baSdanielk1977 ** Usage:  sqlite3_sleep ms
2628600dd0baSdanielk1977 **
2629600dd0baSdanielk1977 ** Sleep for the specified number of ms.
2630600dd0baSdanielk1977 */
2631600dd0baSdanielk1977 #if 0
2632600dd0baSdanielk1977 static int test_sleep(
2633600dd0baSdanielk1977   void * clientData,
2634600dd0baSdanielk1977   Tcl_Interp *interp,
2635600dd0baSdanielk1977   int argc,
2636600dd0baSdanielk1977   char **argv
2637600dd0baSdanielk1977 ){
2638600dd0baSdanielk1977   sqlite3 *db;
2639600dd0baSdanielk1977   if( argc!=2 ){
2640600dd0baSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ms", 0);
2641600dd0baSdanielk1977     return TCL_ERROR;
2642600dd0baSdanielk1977   }
2643600dd0baSdanielk1977   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(atoi(argv[1]))));
2644600dd0baSdanielk1977   return TCL_OK;
2645600dd0baSdanielk1977 }
2646600dd0baSdanielk1977 #endif
2647600dd0baSdanielk1977 
2648600dd0baSdanielk1977 /*
26499636c4e1Sdanielk1977 ** Usage: sqlite_delete_function DB function-name
26509636c4e1Sdanielk1977 **
26519636c4e1Sdanielk1977 ** Delete the user function 'function-name' from database handle DB. It
26529636c4e1Sdanielk1977 ** is assumed that the user function was created as UTF8, any number of
26539636c4e1Sdanielk1977 ** arguments (the way the TCL interface does it).
26549636c4e1Sdanielk1977 */
26559636c4e1Sdanielk1977 static int delete_function(
26569636c4e1Sdanielk1977   void * clientData,
26579636c4e1Sdanielk1977   Tcl_Interp *interp,
26589636c4e1Sdanielk1977   int argc,
26599636c4e1Sdanielk1977   char **argv
26609636c4e1Sdanielk1977 ){
26619636c4e1Sdanielk1977   int rc;
26629636c4e1Sdanielk1977   sqlite3 *db;
26639636c4e1Sdanielk1977   if( argc!=3 ){
26649636c4e1Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
26659636c4e1Sdanielk1977         " DB function-name", 0);
26669636c4e1Sdanielk1977     return TCL_ERROR;
26679636c4e1Sdanielk1977   }
26689636c4e1Sdanielk1977   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
26699636c4e1Sdanielk1977   rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
26709636c4e1Sdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
26719636c4e1Sdanielk1977   return TCL_OK;
26729636c4e1Sdanielk1977 }
26739636c4e1Sdanielk1977 
26749636c4e1Sdanielk1977 /*
26759636c4e1Sdanielk1977 ** Usage: sqlite_delete_collation DB collation-name
26769636c4e1Sdanielk1977 **
26779636c4e1Sdanielk1977 ** Delete the collation sequence 'collation-name' from database handle
26789636c4e1Sdanielk1977 ** DB. It is assumed that the collation sequence was created as UTF8 (the
26799636c4e1Sdanielk1977 ** way the TCL interface does it).
26809636c4e1Sdanielk1977 */
26819636c4e1Sdanielk1977 static int delete_collation(
26829636c4e1Sdanielk1977   void * clientData,
26839636c4e1Sdanielk1977   Tcl_Interp *interp,
26849636c4e1Sdanielk1977   int argc,
26859636c4e1Sdanielk1977   char **argv
26869636c4e1Sdanielk1977 ){
26879636c4e1Sdanielk1977   int rc;
26889636c4e1Sdanielk1977   sqlite3 *db;
26899636c4e1Sdanielk1977   if( argc!=3 ){
26909636c4e1Sdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
26919636c4e1Sdanielk1977         " DB function-name", 0);
26929636c4e1Sdanielk1977     return TCL_ERROR;
26939636c4e1Sdanielk1977   }
26949636c4e1Sdanielk1977   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
26959636c4e1Sdanielk1977   rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
26969636c4e1Sdanielk1977   Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
26979636c4e1Sdanielk1977   return TCL_OK;
26989636c4e1Sdanielk1977 }
26999636c4e1Sdanielk1977 
27009636c4e1Sdanielk1977 /*
27013e1d8e63Sdrh ** Usage: sqlite3_get_autocommit DB
27023e1d8e63Sdrh **
27033e1d8e63Sdrh ** Return true if the database DB is currently in auto-commit mode.
27043e1d8e63Sdrh ** Return false if not.
27053e1d8e63Sdrh */
27063e1d8e63Sdrh static int get_autocommit(
27073e1d8e63Sdrh   void * clientData,
27083e1d8e63Sdrh   Tcl_Interp *interp,
27093e1d8e63Sdrh   int argc,
27103e1d8e63Sdrh   char **argv
27113e1d8e63Sdrh ){
27123e1d8e63Sdrh   char zBuf[30];
27133e1d8e63Sdrh   sqlite3 *db;
27143e1d8e63Sdrh   if( argc!=2 ){
27153e1d8e63Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
27163e1d8e63Sdrh         " DB", 0);
27173e1d8e63Sdrh     return TCL_ERROR;
27183e1d8e63Sdrh   }
27193e1d8e63Sdrh   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
27203e1d8e63Sdrh   sprintf(zBuf, "%d", sqlite3_get_autocommit(db));
27213e1d8e63Sdrh   Tcl_AppendResult(interp, zBuf, 0);
27223e1d8e63Sdrh   return TCL_OK;
27233e1d8e63Sdrh }
27243e1d8e63Sdrh 
27253e1d8e63Sdrh /*
272692febd92Sdrh ** Usage:  tcl_variable_type VARIABLENAME
272792febd92Sdrh **
272892febd92Sdrh ** Return the name of the internal representation for the
272992febd92Sdrh ** value of the given variable.
273092febd92Sdrh */
273192febd92Sdrh static int tcl_variable_type(
273292febd92Sdrh   void * clientData,
273392febd92Sdrh   Tcl_Interp *interp,
273492febd92Sdrh   int objc,
273592febd92Sdrh   Tcl_Obj *CONST objv[]
273692febd92Sdrh ){
273792febd92Sdrh   Tcl_Obj *pVar;
273892febd92Sdrh   if( objc!=2 ){
273992febd92Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
274092febd92Sdrh     return TCL_ERROR;
274192febd92Sdrh   }
274292febd92Sdrh   pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
274392febd92Sdrh   if( pVar==0 ) return TCL_ERROR;
274492febd92Sdrh   if( pVar->typePtr ){
274592febd92Sdrh     Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
274692febd92Sdrh   }
274792febd92Sdrh   return TCL_OK;
274892febd92Sdrh }
274992febd92Sdrh 
275092febd92Sdrh /*
275127d258a3Sdrh ** This routine sets entries in the global ::sqlite_options() array variable
275227d258a3Sdrh ** according to the compile-time configuration of the database.  Test
275327d258a3Sdrh ** procedures use this to determine when tests should be omitted.
275427d258a3Sdrh */
275527d258a3Sdrh static void set_options(Tcl_Interp *interp){
275675f86a4bSdrh #ifdef SQLITE_32BIT_ROWID
275775f86a4bSdrh   Tcl_SetVar2(interp, "sqlite_options", "rowid32", "1", TCL_GLOBAL_ONLY);
275875f86a4bSdrh #else
275975f86a4bSdrh   Tcl_SetVar2(interp, "sqlite_options", "rowid32", "0", TCL_GLOBAL_ONLY);
276075f86a4bSdrh #endif
276175f86a4bSdrh 
2762*9f18e8a0Sdrh #ifdef SQLITE_CASE_SENSITIVE_LIKE
2763*9f18e8a0Sdrh   Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","1",TCL_GLOBAL_ONLY);
2764*9f18e8a0Sdrh #else
2765*9f18e8a0Sdrh   Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY);
2766*9f18e8a0Sdrh #endif
2767*9f18e8a0Sdrh 
27681c8c23ccSdanielk1977 #ifdef SQLITE_OMIT_ALTERTABLE
27691c8c23ccSdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "altertable", "0", TCL_GLOBAL_ONLY);
27701c8c23ccSdanielk1977 #else
27711c8c23ccSdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "altertable", "1", TCL_GLOBAL_ONLY);
27721c8c23ccSdanielk1977 #endif
277313d7042aSdrh 
2774*9f18e8a0Sdrh #ifdef SQLITE_OMIT_ANALYZE
2775*9f18e8a0Sdrh   Tcl_SetVar2(interp, "sqlite_options", "analyze", "0", TCL_GLOBAL_ONLY);
2776*9f18e8a0Sdrh #else
2777*9f18e8a0Sdrh   Tcl_SetVar2(interp, "sqlite_options", "analyze", "1", TCL_GLOBAL_ONLY);
2778*9f18e8a0Sdrh #endif
2779*9f18e8a0Sdrh 
278013d7042aSdrh #ifdef SQLITE_OMIT_AUTHORIZATION
278113d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "auth", "0", TCL_GLOBAL_ONLY);
278213d7042aSdrh #else
278313d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "auth", "1", TCL_GLOBAL_ONLY);
278413d7042aSdrh #endif
278513d7042aSdrh 
2786f3388144Sdrh #ifdef SQLITE_OMIT_AUTOINCREMENT
2787f3388144Sdrh   Tcl_SetVar2(interp, "sqlite_options", "autoinc", "0", TCL_GLOBAL_ONLY);
2788f3388144Sdrh #else
2789f3388144Sdrh   Tcl_SetVar2(interp, "sqlite_options", "autoinc", "1", TCL_GLOBAL_ONLY);
2790f3388144Sdrh #endif
2791f3388144Sdrh 
279245901d62Sdanielk1977 #ifdef SQLITE_OMIT_AUTOVACUUM
279345901d62Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "0", TCL_GLOBAL_ONLY);
279445901d62Sdanielk1977 #else
279545901d62Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "1", TCL_GLOBAL_ONLY);
2796f3388144Sdrh #endif /* SQLITE_OMIT_AUTOVACUUM */
27974d36b81eSdanielk1977 #if !defined(SQLITE_DEFAULT_AUTOVACUUM) || SQLITE_DEFAULT_AUTOVACUUM==0
279845901d62Sdanielk1977   Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","0",TCL_GLOBAL_ONLY);
279945901d62Sdanielk1977 #else
280045901d62Sdanielk1977   Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","1",TCL_GLOBAL_ONLY);
280145901d62Sdanielk1977 #endif
280213d7042aSdrh 
280313d7042aSdrh #ifdef SQLITE_OMIT_BLOB_LITERAL
280413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "bloblit", "0", TCL_GLOBAL_ONLY);
280513d7042aSdrh #else
280613d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY);
280713d7042aSdrh #endif
280813d7042aSdrh 
2809487e262fSdrh #ifdef SQLITE_OMIT_CAST
2810487e262fSdrh   Tcl_SetVar2(interp, "sqlite_options", "cast", "0", TCL_GLOBAL_ONLY);
2811487e262fSdrh #else
2812487e262fSdrh   Tcl_SetVar2(interp, "sqlite_options", "cast", "1", TCL_GLOBAL_ONLY);
2813487e262fSdrh #endif
2814487e262fSdrh 
2815ccae6026Sdrh #ifdef SQLITE_OMIT_COMPLETE
2816ccae6026Sdrh   Tcl_SetVar2(interp, "sqlite_options", "complete", "0", TCL_GLOBAL_ONLY);
2817ccae6026Sdrh #else
2818ccae6026Sdrh   Tcl_SetVar2(interp, "sqlite_options", "complete", "1", TCL_GLOBAL_ONLY);
2819ccae6026Sdrh #endif
2820ccae6026Sdrh 
282113d7042aSdrh #ifdef SQLITE_OMIT_COMPOUND_SELECT
282213d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "compound", "0", TCL_GLOBAL_ONLY);
282313d7042aSdrh #else
282413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "compound", "1", TCL_GLOBAL_ONLY);
282513d7042aSdrh #endif
282613d7042aSdrh 
282713d7042aSdrh #ifdef SQLITE_OMIT_CONFLICT_CLAUSE
282813d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "conflict", "0", TCL_GLOBAL_ONLY);
282913d7042aSdrh #else
283013d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY);
283113d7042aSdrh #endif
283213d7042aSdrh 
283313d7042aSdrh #ifdef SQLITE_OMIT_DATETIME_FUNCS
283413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY);
283513d7042aSdrh #else
283613d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY);
283713d7042aSdrh #endif
283813d7042aSdrh 
28392e66f0b9Sdrh #ifdef SQLITE_OMIT_DISKIO
28402e66f0b9Sdrh   Tcl_SetVar2(interp, "sqlite_options", "diskio", "0", TCL_GLOBAL_ONLY);
28412e66f0b9Sdrh #else
28422e66f0b9Sdrh   Tcl_SetVar2(interp, "sqlite_options", "diskio", "1", TCL_GLOBAL_ONLY);
28432e66f0b9Sdrh #endif
28442e66f0b9Sdrh 
284513d7042aSdrh #ifdef SQLITE_OMIT_EXPLAIN
284613d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "explain", "0", TCL_GLOBAL_ONLY);
284713d7042aSdrh #else
284813d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "explain", "1", TCL_GLOBAL_ONLY);
284913d7042aSdrh #endif
285013d7042aSdrh 
285113d7042aSdrh #ifdef SQLITE_OMIT_FLOATING_POINT
285213d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "0", TCL_GLOBAL_ONLY);
285313d7042aSdrh #else
285413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "1", TCL_GLOBAL_ONLY);
285513d7042aSdrh #endif
285613d7042aSdrh 
285713d7042aSdrh #ifdef SQLITE_OMIT_FOREIGN_KEY
285813d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "0", TCL_GLOBAL_ONLY);
285913d7042aSdrh #else
286013d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "1", TCL_GLOBAL_ONLY);
286113d7042aSdrh #endif
286213d7042aSdrh 
28636b456a2bSdanielk1977 #ifdef SQLITE_OMIT_GLOBALRECOVER
28646b456a2bSdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "globalrecover", "0", TCL_GLOBAL_ONLY);
28656b456a2bSdanielk1977 #else
28666b456a2bSdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "globalrecover", "1", TCL_GLOBAL_ONLY);
28676b456a2bSdanielk1977 #endif
28686b456a2bSdanielk1977 
286913d7042aSdrh #ifdef SQLITE_OMIT_INTEGRITY_CHECK
287013d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
287113d7042aSdrh #else
287213d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "integrityck", "1", TCL_GLOBAL_ONLY);
287313d7042aSdrh #endif
287413d7042aSdrh 
287513d7042aSdrh #ifdef SQLITE_OMIT_MEMORYDB
287613d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY);
287713d7042aSdrh #else
287813d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "memorydb", "1", TCL_GLOBAL_ONLY);
287913d7042aSdrh #endif
288013d7042aSdrh 
288113d7042aSdrh #ifdef SQLITE_OMIT_PAGER_PRAGMAS
288213d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY);
288313d7042aSdrh #else
288413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "1", TCL_GLOBAL_ONLY);
288513d7042aSdrh #endif
288613d7042aSdrh 
28872e66f0b9Sdrh #ifdef SQLITE_OMIT_PARSER
28882e66f0b9Sdrh   Tcl_SetVar2(interp, "sqlite_options", "parser", "0", TCL_GLOBAL_ONLY);
28892e66f0b9Sdrh #else
28902e66f0b9Sdrh   Tcl_SetVar2(interp, "sqlite_options", "parser", "1", TCL_GLOBAL_ONLY);
28912e66f0b9Sdrh #endif
28922e66f0b9Sdrh 
2893bf21627bSdrh #if defined(SQLITE_OMIT_PRAGMA) || defined(SQLITE_OMIT_FLAG_PRAGMAS)
289413d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "pragma", "0", TCL_GLOBAL_ONLY);
289513d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
289613d7042aSdrh #else
289713d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "pragma", "1", TCL_GLOBAL_ONLY);
289813d7042aSdrh #endif
289913d7042aSdrh 
290013d7042aSdrh #ifdef SQLITE_OMIT_PROGRESS_CALLBACK
290113d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "progress", "0", TCL_GLOBAL_ONLY);
290213d7042aSdrh #else
290313d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY);
290413d7042aSdrh #endif
290513d7042aSdrh 
290613d7042aSdrh #ifdef SQLITE_OMIT_REINDEX
290713d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "reindex", "0", TCL_GLOBAL_ONLY);
290813d7042aSdrh #else
290913d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "reindex", "1", TCL_GLOBAL_ONLY);
291013d7042aSdrh #endif
291113d7042aSdrh 
291213d7042aSdrh #ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
291313d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "0", TCL_GLOBAL_ONLY);
291413d7042aSdrh #else
291513d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "1", TCL_GLOBAL_ONLY);
291613d7042aSdrh #endif
291713d7042aSdrh 
291813d7042aSdrh #ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
291913d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "schema_version", "0", TCL_GLOBAL_ONLY);
292013d7042aSdrh #else
292113d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY);
292213d7042aSdrh #endif
292313d7042aSdrh 
29243e8c37e7Sdanielk1977 #ifdef SQLITE_OMIT_SUBQUERY
29253e8c37e7Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "subquery", "0", TCL_GLOBAL_ONLY);
29263e8c37e7Sdanielk1977 #else
29273e8c37e7Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "subquery", "1", TCL_GLOBAL_ONLY);
29283e8c37e7Sdanielk1977 #endif
29293e8c37e7Sdanielk1977 
293013d7042aSdrh #ifdef SQLITE_OMIT_TCL_VARIABLE
293113d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY);
293213d7042aSdrh #else
293313d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY);
293413d7042aSdrh #endif
293513d7042aSdrh 
293613d7042aSdrh #if defined(THREADSAFE) && THREADSAFE
293713d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY);
293813d7042aSdrh #else
293913d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "0", TCL_GLOBAL_ONLY);
294013d7042aSdrh #endif
294113d7042aSdrh 
294213d7042aSdrh #ifdef SQLITE_OMIT_TRIGGER
294313d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "trigger", "0", TCL_GLOBAL_ONLY);
294413d7042aSdrh #else
294513d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "trigger", "1", TCL_GLOBAL_ONLY);
294613d7042aSdrh #endif
294713d7042aSdrh 
294853c0f748Sdanielk1977 #ifdef SQLITE_OMIT_TEMPDB
294953c0f748Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "tempdb", "0", TCL_GLOBAL_ONLY);
295053c0f748Sdanielk1977 #else
295153c0f748Sdanielk1977   Tcl_SetVar2(interp, "sqlite_options", "tempdb", "1", TCL_GLOBAL_ONLY);
295253c0f748Sdanielk1977 #endif
295353c0f748Sdanielk1977 
295413d7042aSdrh #ifdef SQLITE_OMIT_UTF16
295513d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY);
295613d7042aSdrh #else
295713d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "utf16", "1", TCL_GLOBAL_ONLY);
295813d7042aSdrh #endif
295913d7042aSdrh 
296013d7042aSdrh #ifdef SQLITE_OMIT_VACUUM
296113d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "vacuum", "0", TCL_GLOBAL_ONLY);
296213d7042aSdrh #else
296313d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "vacuum", "1", TCL_GLOBAL_ONLY);
296413d7042aSdrh #endif
296513d7042aSdrh 
296613d7042aSdrh #ifdef SQLITE_OMIT_VIEW
296713d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "view", "0", TCL_GLOBAL_ONLY);
296813d7042aSdrh #else
296913d7042aSdrh   Tcl_SetVar2(interp, "sqlite_options", "view", "1", TCL_GLOBAL_ONLY);
297013d7042aSdrh #endif
297127d258a3Sdrh }
297227d258a3Sdrh 
297327d258a3Sdrh /*
2974d1bf3512Sdrh ** Register commands with the TCL interpreter.
2975d1bf3512Sdrh */
2976d1bf3512Sdrh int Sqlitetest1_Init(Tcl_Interp *interp){
29776f8a503dSdanielk1977   extern int sqlite3_search_count;
29786f8a503dSdanielk1977   extern int sqlite3_interrupt_count;
29796f8a503dSdanielk1977   extern int sqlite3_open_file_count;
29806bf89570Sdrh   extern int sqlite3_sort_count;
29816f8a503dSdanielk1977   extern int sqlite3_current_time;
2982c2eef3b3Sdrh   static struct {
2983c2eef3b3Sdrh      char *zName;
2984c2eef3b3Sdrh      Tcl_CmdProc *xProc;
2985c2eef3b3Sdrh   } aCmd[] = {
29866f8a503dSdanielk1977      { "sqlite3_mprintf_int",           (Tcl_CmdProc*)sqlite3_mprintf_int    },
2987e9707671Sdrh      { "sqlite3_mprintf_int64",         (Tcl_CmdProc*)sqlite3_mprintf_int64  },
29886f8a503dSdanielk1977      { "sqlite3_mprintf_str",           (Tcl_CmdProc*)sqlite3_mprintf_str    },
2989e29b1a05Sdrh      { "sqlite3_mprintf_stronly",       (Tcl_CmdProc*)sqlite3_mprintf_stronly},
29906f8a503dSdanielk1977      { "sqlite3_mprintf_double",        (Tcl_CmdProc*)sqlite3_mprintf_double },
29916f8a503dSdanielk1977      { "sqlite3_mprintf_scaled",        (Tcl_CmdProc*)sqlite3_mprintf_scaled },
29926f8a503dSdanielk1977      { "sqlite3_mprintf_z_test",        (Tcl_CmdProc*)test_mprintf_z        },
29936f8a503dSdanielk1977      { "sqlite3_last_insert_rowid",     (Tcl_CmdProc*)test_last_rowid       },
29946f8a503dSdanielk1977      { "sqlite3_exec_printf",           (Tcl_CmdProc*)test_exec_printf      },
29956f8a503dSdanielk1977      { "sqlite3_get_table_printf",      (Tcl_CmdProc*)test_get_table_printf },
29966f8a503dSdanielk1977      { "sqlite3_close",                 (Tcl_CmdProc*)sqlite_test_close     },
29976f8a503dSdanielk1977      { "sqlite3_create_function",       (Tcl_CmdProc*)test_create_function  },
29986f8a503dSdanielk1977      { "sqlite3_create_aggregate",      (Tcl_CmdProc*)test_create_aggregate },
2999c2eef3b3Sdrh      { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func    },
3000c2eef3b3Sdrh      { "sqlite_abort",                  (Tcl_CmdProc*)sqlite_abort          },
30012c336549Sdanielk1977 #ifdef SQLITE_MEMDEBUG
3002c2eef3b3Sdrh      { "sqlite_malloc_fail",            (Tcl_CmdProc*)sqlite_malloc_fail    },
3003c2eef3b3Sdrh      { "sqlite_malloc_stat",            (Tcl_CmdProc*)sqlite_malloc_stat    },
3004c2eef3b3Sdrh #endif
300596fc5fe6Sdanielk1977      { "sqlite_bind",                   (Tcl_CmdProc*)test_bind             },
300699ee3600Sdrh      { "breakpoint",                    (Tcl_CmdProc*)test_breakpoint       },
300725d6543dSdrh      { "sqlite3_key",                   (Tcl_CmdProc*)test_key              },
300825d6543dSdrh      { "sqlite3_rekey",                 (Tcl_CmdProc*)test_rekey            },
3009cacb208eSdrh      { "sqlite_set_magic",              (Tcl_CmdProc*)sqlite_set_magic      },
3010c5cdca61Sdrh      { "sqlite3_interrupt",             (Tcl_CmdProc*)test_interrupt        },
3011600dd0baSdanielk1977 #if 0
3012600dd0baSdanielk1977      { "sqlite3_sleep",                 (Tcl_CmdProc*)test_sleep            },
3013600dd0baSdanielk1977 #endif
30149636c4e1Sdanielk1977      { "sqlite_delete_function",        (Tcl_CmdProc*)delete_function       },
30153e1d8e63Sdrh      { "sqlite_delete_collation",       (Tcl_CmdProc*)delete_collation      },
30163e1d8e63Sdrh      { "sqlite3_get_autocommit",        (Tcl_CmdProc*)get_autocommit        },
3017c2eef3b3Sdrh   };
301851e3d8e2Sdanielk1977   static struct {
301951e3d8e2Sdanielk1977      char *zName;
302051e3d8e2Sdanielk1977      Tcl_ObjCmdProc *xProc;
302104f2e68dSdanielk1977      void *clientData;
302251e3d8e2Sdanielk1977   } aObjCmd[] = {
3023241db313Sdrh      { "sqlite3_bind_int",              test_bind_int,      0 },
302404f2e68dSdanielk1977      { "sqlite3_bind_int64",            test_bind_int64,    0 },
302504f2e68dSdanielk1977      { "sqlite3_bind_double",           test_bind_double,   0 },
302604f2e68dSdanielk1977      { "sqlite3_bind_null",             test_bind_null     ,0 },
302704f2e68dSdanielk1977      { "sqlite3_bind_text",             test_bind_text     ,0 },
302804f2e68dSdanielk1977      { "sqlite3_bind_text16",           test_bind_text16   ,0 },
302904f2e68dSdanielk1977      { "sqlite3_bind_blob",             test_bind_blob     ,0 },
303075f6a032Sdrh      { "sqlite3_bind_parameter_count",  test_bind_parameter_count, 0},
3031895d7472Sdrh      { "sqlite3_bind_parameter_name",   test_bind_parameter_name,  0},
3032fa6bc000Sdrh      { "sqlite3_bind_parameter_index",  test_bind_parameter_index, 0},
3033600dd0baSdanielk1977 #if 0
3034600dd0baSdanielk1977      { "sqlite3_clear_bindings",        test_clear_bindings, 0},
3035600dd0baSdanielk1977 #endif
303604f2e68dSdanielk1977      { "sqlite3_errcode",               test_errcode       ,0 },
303704f2e68dSdanielk1977      { "sqlite3_errmsg",                test_errmsg        ,0 },
303804f2e68dSdanielk1977      { "sqlite3_errmsg16",              test_errmsg16      ,0 },
303904f2e68dSdanielk1977      { "sqlite3_open",                  test_open          ,0 },
304004f2e68dSdanielk1977      { "sqlite3_open16",                test_open16        ,0 },
3041bc6ada41Sdanielk1977      { "sqlite3_complete16",            test_complete16    ,0 },
304204f2e68dSdanielk1977 
304304f2e68dSdanielk1977      { "sqlite3_prepare",               test_prepare       ,0 },
304404f2e68dSdanielk1977      { "sqlite3_prepare16",             test_prepare16     ,0 },
304504f2e68dSdanielk1977      { "sqlite3_finalize",              test_finalize      ,0 },
304604f2e68dSdanielk1977      { "sqlite3_reset",                 test_reset         ,0 },
3047d89bd007Sdrh      { "sqlite3_expired",               test_expired       ,0 },
3048f8db1bc0Sdrh      { "sqlite3_transfer_bindings",     test_transfer_bind ,0 },
3049fbcd585fSdanielk1977      { "sqlite3_changes",               test_changes       ,0 },
305004f2e68dSdanielk1977      { "sqlite3_step",                  test_step          ,0 },
305104f2e68dSdanielk1977 
305204f2e68dSdanielk1977      /* sqlite3_column_*() API */
305304f2e68dSdanielk1977      { "sqlite3_column_count",          test_column_count  ,0 },
305404f2e68dSdanielk1977      { "sqlite3_data_count",            test_data_count    ,0 },
305504f2e68dSdanielk1977      { "sqlite3_column_type",           test_column_type   ,0 },
3056ea61b2c4Sdanielk1977      { "sqlite3_column_blob",           test_column_blob   ,0 },
305704f2e68dSdanielk1977      { "sqlite3_column_double",         test_column_double ,0 },
305804f2e68dSdanielk1977      { "sqlite3_column_int64",          test_column_int64  ,0 },
305904f2e68dSdanielk1977      { "sqlite3_column_text",       test_stmt_utf8,  sqlite3_column_text      },
306004f2e68dSdanielk1977      { "sqlite3_column_decltype",   test_stmt_utf8,  sqlite3_column_decltype  },
306104f2e68dSdanielk1977      { "sqlite3_column_name",       test_stmt_utf8,  sqlite3_column_name      },
30626c62608fSdrh      { "sqlite3_column_int",        test_stmt_int,   sqlite3_column_int       },
30636c62608fSdrh      { "sqlite3_column_bytes",      test_stmt_int,   sqlite3_column_bytes     },
30646c62608fSdrh #ifndef SQLITE_OMIT_UTF16
30656c62608fSdrh      { "sqlite3_column_bytes16",    test_stmt_int,   sqlite3_column_bytes16   },
306604f2e68dSdanielk1977      { "sqlite3_column_text16",     test_stmt_utf16, sqlite3_column_text16    },
306704f2e68dSdanielk1977      { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16},
306804f2e68dSdanielk1977      { "sqlite3_column_name16",     test_stmt_utf16, sqlite3_column_name16    },
30696c62608fSdrh #endif
30706b456a2bSdanielk1977      { "sqlite3_global_recover",    test_global_recover, 0   },
307104f2e68dSdanielk1977 
30729a1d0abeSdanielk1977      /* Functions from os.h */
307344ee5bf7Sdanielk1977 #ifndef SQLITE_OMIT_DISKIO
30749a1d0abeSdanielk1977      { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
30759a1d0abeSdanielk1977      { "sqlite3OsClose",        test_sqlite3OsClose, 0 },
30769a1d0abeSdanielk1977      { "sqlite3OsLock",         test_sqlite3OsLock, 0 },
3077ab3f9feaSdrh      { "sqlite3OsTempFileName", test_sqlite3OsTempFileName, 0 },
3078312d6b36Sdanielk1977 
3079312d6b36Sdanielk1977      /* Custom test interfaces */
30809a1d0abeSdanielk1977      { "sqlite3OsUnlock",         test_sqlite3OsUnlock, 0    },
308144ee5bf7Sdanielk1977 #endif
30825436dc2dSdrh #ifndef SQLITE_OMIT_UTF16
30834e6af134Sdanielk1977      { "add_test_collate",        test_collate, 0            },
3084312d6b36Sdanielk1977      { "add_test_collate_needed", test_collate_needed, 0     },
3085c8e9a2dfSdanielk1977      { "add_test_function",       test_function, 0           },
30865436dc2dSdrh #endif
3087c8e9a2dfSdanielk1977      { "sqlite3_crashparams",     sqlite3_crashparams, 0     },
3088312d6b36Sdanielk1977      { "sqlite3_test_errstr",     test_errstr, 0             },
308992febd92Sdrh      { "tcl_variable_type",       tcl_variable_type, 0       },
309051e3d8e2Sdanielk1977   };
30911398ad36Sdrh   static int bitmask_size = sizeof(Bitmask)*8;
3092c2eef3b3Sdrh   int i;
30932ac3ee97Sdrh   extern int sqlite3_os_trace;
3094b851b2c9Sdrh   extern int sqlite3_sync_count, sqlite3_fullsync_count;
3095af6df11fSdrh   extern int sqlite3_opentemp_count;
3096c2eef3b3Sdrh 
3097c2eef3b3Sdrh   for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
3098c2eef3b3Sdrh     Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
3099c2eef3b3Sdrh   }
310051e3d8e2Sdanielk1977   for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
3101c572ef7fSdanielk1977     Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
3102c572ef7fSdanielk1977         aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
310351e3d8e2Sdanielk1977   }
31046490bebdSdanielk1977   Tcl_LinkVar(interp, "sqlite_search_count",
31056f8a503dSdanielk1977       (char*)&sqlite3_search_count, TCL_LINK_INT);
31066bf89570Sdrh   Tcl_LinkVar(interp, "sqlite_sort_count",
31076bf89570Sdrh       (char*)&sqlite3_sort_count, TCL_LINK_INT);
31086490bebdSdanielk1977   Tcl_LinkVar(interp, "sqlite_interrupt_count",
31096f8a503dSdanielk1977       (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
31106490bebdSdanielk1977   Tcl_LinkVar(interp, "sqlite_open_file_count",
31116f8a503dSdanielk1977       (char*)&sqlite3_open_file_count, TCL_LINK_INT);
31126490bebdSdanielk1977   Tcl_LinkVar(interp, "sqlite_current_time",
31136f8a503dSdanielk1977       (char*)&sqlite3_current_time, TCL_LINK_INT);
31142ac3ee97Sdrh   Tcl_LinkVar(interp, "sqlite_os_trace",
31152ac3ee97Sdrh       (char*)&sqlite3_os_trace, TCL_LINK_INT);
3116cbe21be3Sdanielk1977 #ifndef SQLITE_OMIT_DISKIO
3117af6df11fSdrh   Tcl_LinkVar(interp, "sqlite_opentemp_count",
3118af6df11fSdrh       (char*)&sqlite3_opentemp_count, TCL_LINK_INT);
3119cbe21be3Sdanielk1977 #endif
31207c972decSdrh   Tcl_LinkVar(interp, "sqlite_static_bind_value",
31217c972decSdrh       (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
3122ab3f9feaSdrh   Tcl_LinkVar(interp, "sqlite_temp_directory",
3123effd02bcSdrh       (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
31241398ad36Sdrh   Tcl_LinkVar(interp, "bitmask_size",
31251398ad36Sdrh       (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
3126748f763fSdrh #if OS_UNIX
3127b851b2c9Sdrh   Tcl_LinkVar(interp, "sqlite_sync_count",
3128b851b2c9Sdrh       (char*)&sqlite3_sync_count, TCL_LINK_INT);
3129b851b2c9Sdrh   Tcl_LinkVar(interp, "sqlite_fullsync_count",
3130b851b2c9Sdrh       (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
3131748f763fSdrh #endif /* OS_UNIX */
313227d258a3Sdrh   set_options(interp);
3133d1bf3512Sdrh   return TCL_OK;
3134d1bf3512Sdrh }
3135