xref: /sqlite-3.40.0/src/test1.c (revision 06b2718a)
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*06b2718aSdrh ** $Id: test1.c,v 1.10 2002/06/26 20:06:06 drh Exp $
17d1bf3512Sdrh */
18d1bf3512Sdrh #include "sqliteInt.h"
19d1bf3512Sdrh #include "tcl.h"
20d1bf3512Sdrh #include <stdlib.h>
21d1bf3512Sdrh #include <string.h>
22d1bf3512Sdrh 
23d1bf3512Sdrh /*
24d1bf3512Sdrh ** Usage:   sqlite_open filename
25d1bf3512Sdrh **
26d1bf3512Sdrh ** Returns:  The name of an open database.
27d1bf3512Sdrh */
28d1bf3512Sdrh static int sqlite_test_open(
29d1bf3512Sdrh   void *NotUsed,
30d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
31d1bf3512Sdrh   int argc,              /* Number of arguments */
32d1bf3512Sdrh   char **argv            /* Text of each argument */
33d1bf3512Sdrh ){
34d1bf3512Sdrh   sqlite *db;
35d1bf3512Sdrh   char *zErr = 0;
36d1bf3512Sdrh   char zBuf[100];
37d1bf3512Sdrh   if( argc!=2 ){
38d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
39d1bf3512Sdrh        " FILENAME\"", 0);
40d1bf3512Sdrh     return TCL_ERROR;
41d1bf3512Sdrh   }
42d1bf3512Sdrh   db = sqlite_open(argv[1], 0666, &zErr);
43d1bf3512Sdrh   if( db==0 ){
44d1bf3512Sdrh     Tcl_AppendResult(interp, zErr, 0);
45d1bf3512Sdrh     free(zErr);
46d1bf3512Sdrh     return TCL_ERROR;
47d1bf3512Sdrh   }
48d1bf3512Sdrh   sprintf(zBuf,"%d",(int)db);
49d1bf3512Sdrh   Tcl_AppendResult(interp, zBuf, 0);
50d1bf3512Sdrh   return TCL_OK;
51d1bf3512Sdrh }
52d1bf3512Sdrh 
53d1bf3512Sdrh /*
54d1bf3512Sdrh ** The callback routine for sqlite_exec_printf().
55d1bf3512Sdrh */
56d1bf3512Sdrh static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
57d1bf3512Sdrh   Tcl_DString *str = (Tcl_DString*)pArg;
58d1bf3512Sdrh   int i;
59d1bf3512Sdrh 
60d1bf3512Sdrh   if( Tcl_DStringLength(str)==0 ){
61d1bf3512Sdrh     for(i=0; i<argc; i++){
62d1bf3512Sdrh       Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
63d1bf3512Sdrh     }
64d1bf3512Sdrh   }
65d1bf3512Sdrh   for(i=0; i<argc; i++){
66d1bf3512Sdrh     Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
67d1bf3512Sdrh   }
68d1bf3512Sdrh   return 0;
69d1bf3512Sdrh }
70d1bf3512Sdrh 
71d1bf3512Sdrh /*
72d1bf3512Sdrh ** Usage:  sqlite_exec_printf  DB  FORMAT  STRING
73d1bf3512Sdrh **
74d1bf3512Sdrh ** Invoke the sqlite_exec_printf() interface using the open database
75d1bf3512Sdrh ** DB.  The SQL is the string FORMAT.  The format string should contain
76d1bf3512Sdrh ** one %s or %q.  STRING is the value inserted into %s or %q.
77d1bf3512Sdrh */
78d1bf3512Sdrh static int test_exec_printf(
79d1bf3512Sdrh   void *NotUsed,
80d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
81d1bf3512Sdrh   int argc,              /* Number of arguments */
82d1bf3512Sdrh   char **argv            /* Text of each argument */
83d1bf3512Sdrh ){
84d1bf3512Sdrh   sqlite *db;
85d1bf3512Sdrh   Tcl_DString str;
86d1bf3512Sdrh   int rc;
87d1bf3512Sdrh   char *zErr = 0;
88d1bf3512Sdrh   char zBuf[30];
89d1bf3512Sdrh   if( argc!=4 ){
90d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
91d1bf3512Sdrh        " DB FORMAT STRING", 0);
92d1bf3512Sdrh     return TCL_ERROR;
93d1bf3512Sdrh   }
94*06b2718aSdrh   db = (sqlite*)strtol(argv[1], 0, 0);
95d1bf3512Sdrh   Tcl_DStringInit(&str);
96d1bf3512Sdrh   rc = sqlite_exec_printf(db, argv[2], exec_printf_cb, &str, &zErr, argv[3]);
97d1bf3512Sdrh   sprintf(zBuf, "%d", rc);
98d1bf3512Sdrh   Tcl_AppendElement(interp, zBuf);
99d1bf3512Sdrh   Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
100d1bf3512Sdrh   Tcl_DStringFree(&str);
101d1bf3512Sdrh   if( zErr ) free(zErr);
102d1bf3512Sdrh   return TCL_OK;
103d1bf3512Sdrh }
104d1bf3512Sdrh 
105d1bf3512Sdrh /*
106d1bf3512Sdrh ** Usage:  sqlite_get_table_printf  DB  FORMAT  STRING
107d1bf3512Sdrh **
108d1bf3512Sdrh ** Invoke the sqlite_get_table_printf() interface using the open database
109d1bf3512Sdrh ** DB.  The SQL is the string FORMAT.  The format string should contain
110d1bf3512Sdrh ** one %s or %q.  STRING is the value inserted into %s or %q.
111d1bf3512Sdrh */
112d1bf3512Sdrh static int test_get_table_printf(
113d1bf3512Sdrh   void *NotUsed,
114d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
115d1bf3512Sdrh   int argc,              /* Number of arguments */
116d1bf3512Sdrh   char **argv            /* Text of each argument */
117d1bf3512Sdrh ){
118d1bf3512Sdrh   sqlite *db;
119d1bf3512Sdrh   Tcl_DString str;
120d1bf3512Sdrh   int rc;
121d1bf3512Sdrh   char *zErr = 0;
122d1bf3512Sdrh   int nRow, nCol;
123d1bf3512Sdrh   char **aResult;
124d1bf3512Sdrh   int i;
125d1bf3512Sdrh   char zBuf[30];
126d1bf3512Sdrh   if( argc!=4 ){
127d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
128d1bf3512Sdrh        " DB FORMAT STRING", 0);
129d1bf3512Sdrh     return TCL_ERROR;
130d1bf3512Sdrh   }
131*06b2718aSdrh   db = (sqlite*)strtol(argv[1], 0, 0);
132d1bf3512Sdrh   Tcl_DStringInit(&str);
133d1bf3512Sdrh   rc = sqlite_get_table_printf(db, argv[2], &aResult, &nRow, &nCol,
134d1bf3512Sdrh                &zErr, argv[3]);
135d1bf3512Sdrh   sprintf(zBuf, "%d", rc);
136d1bf3512Sdrh   Tcl_AppendElement(interp, zBuf);
137d1bf3512Sdrh   if( rc==SQLITE_OK ){
138d1bf3512Sdrh     sprintf(zBuf, "%d", nRow);
139d1bf3512Sdrh     Tcl_AppendElement(interp, zBuf);
140d1bf3512Sdrh     sprintf(zBuf, "%d", nCol);
141d1bf3512Sdrh     Tcl_AppendElement(interp, zBuf);
142d1bf3512Sdrh     for(i=0; i<(nRow+1)*nCol; i++){
143d1bf3512Sdrh       Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
144d1bf3512Sdrh     }
145d1bf3512Sdrh   }else{
146d1bf3512Sdrh     Tcl_AppendElement(interp, zErr);
147d1bf3512Sdrh   }
148d1bf3512Sdrh   sqlite_free_table(aResult);
149d1bf3512Sdrh   if( zErr ) free(zErr);
150d1bf3512Sdrh   return TCL_OK;
151d1bf3512Sdrh }
152d1bf3512Sdrh 
153af9ff33aSdrh 
154af9ff33aSdrh /*
155af9ff33aSdrh ** Usage:  sqlite_last_insert_rowid DB
156af9ff33aSdrh **
157af9ff33aSdrh ** Returns the integer ROWID of the most recent insert.
158af9ff33aSdrh */
159af9ff33aSdrh static int test_last_rowid(
160af9ff33aSdrh   void *NotUsed,
161af9ff33aSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
162af9ff33aSdrh   int argc,              /* Number of arguments */
163af9ff33aSdrh   char **argv            /* Text of each argument */
164af9ff33aSdrh ){
165af9ff33aSdrh   sqlite *db;
166af9ff33aSdrh   char zBuf[30];
167af9ff33aSdrh 
168af9ff33aSdrh   if( argc!=2 ){
169af9ff33aSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
170af9ff33aSdrh     return TCL_ERROR;
171af9ff33aSdrh   }
172*06b2718aSdrh   db = (sqlite*)strtol(argv[1], 0, 0);
173af9ff33aSdrh   sprintf(zBuf, "%d", sqlite_last_insert_rowid(db));
174af9ff33aSdrh   Tcl_AppendResult(interp, zBuf, 0);
175af9ff33aSdrh   return SQLITE_OK;
176af9ff33aSdrh }
177af9ff33aSdrh 
178d1bf3512Sdrh /*
179d1bf3512Sdrh ** Usage:  sqlite_close DB
180d1bf3512Sdrh **
181d1bf3512Sdrh ** Closes the database opened by sqlite_open.
182d1bf3512Sdrh */
183d1bf3512Sdrh static int sqlite_test_close(
184d1bf3512Sdrh   void *NotUsed,
185d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
186d1bf3512Sdrh   int argc,              /* Number of arguments */
187d1bf3512Sdrh   char **argv            /* Text of each argument */
188d1bf3512Sdrh ){
189d1bf3512Sdrh   sqlite *db;
190d1bf3512Sdrh   if( argc!=2 ){
191d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
192d1bf3512Sdrh        " FILENAME\"", 0);
193d1bf3512Sdrh     return TCL_ERROR;
194d1bf3512Sdrh   }
195*06b2718aSdrh   db = (sqlite*)strtol(argv[1], 0, 0);
196d1bf3512Sdrh   sqlite_close(db);
197d1bf3512Sdrh   return TCL_OK;
198d1bf3512Sdrh }
199d1bf3512Sdrh 
200d1bf3512Sdrh /*
201c22bd47dSdrh ** Implementation of the x_coalesce() function.
202c22bd47dSdrh ** Return the first argument non-NULL argument.
203c22bd47dSdrh */
204c22bd47dSdrh static void ifnullFunc(sqlite_func *context, int argc, const char **argv){
205c22bd47dSdrh   int i;
206c22bd47dSdrh   for(i=0; i<argc; i++){
207c22bd47dSdrh     if( argv[i] ){
208c22bd47dSdrh       sqlite_set_result_string(context, argv[i], -1);
209c22bd47dSdrh       break;
210c22bd47dSdrh     }
211c22bd47dSdrh   }
212c22bd47dSdrh }
213c22bd47dSdrh 
214c22bd47dSdrh /*
215c22bd47dSdrh ** Implementation of the x_sqlite_exec() function.  This function takes
216c22bd47dSdrh ** a single argument and attempts to execute that argument as SQL code.
217c22bd47dSdrh ** This is illegal and shut set the SQLITE_MISUSE flag on the database.
218c22bd47dSdrh **
219c22bd47dSdrh ** This routine simulates the effect of having two threads attempt to
220c22bd47dSdrh ** use the same database at the same time.
221c22bd47dSdrh */
222c22bd47dSdrh static void sqliteExecFunc(sqlite_func *context, int argc, const char **argv){
223c22bd47dSdrh   sqlite_exec((sqlite*)sqlite_user_data(context), argv[0], 0, 0, 0);
224c22bd47dSdrh }
225c22bd47dSdrh 
226c22bd47dSdrh /*
227c22bd47dSdrh ** Usage:  sqlite_test_create_function DB
228c22bd47dSdrh **
229c22bd47dSdrh ** Call the sqlite_create_function API on the given database in order
230c22bd47dSdrh ** to create a function named "x_coalesce".  This function does the same thing
231c22bd47dSdrh ** as the "coalesce" function.  This function also registers an SQL function
232c22bd47dSdrh ** named "x_sqlite_exec" that invokes sqlite_exec().  Invoking sqlite_exec()
233c22bd47dSdrh ** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
234c22bd47dSdrh ** The effect is similar to trying to use the same database connection from
235c22bd47dSdrh ** two threads at the same time.
236c22bd47dSdrh **
237c22bd47dSdrh ** The original motivation for this routine was to be able to call the
238c22bd47dSdrh ** sqlite_create_function function while a query is in progress in order
239c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic.
240c22bd47dSdrh */
241c22bd47dSdrh static int sqlite_test_create_function(
242c22bd47dSdrh   void *NotUsed,
243c22bd47dSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
244c22bd47dSdrh   int argc,              /* Number of arguments */
245c22bd47dSdrh   char **argv            /* Text of each argument */
246c22bd47dSdrh ){
247c22bd47dSdrh   sqlite *db;
248c22bd47dSdrh   extern void Md5_Register(sqlite*);
249c22bd47dSdrh   if( argc!=2 ){
250c22bd47dSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
251c22bd47dSdrh        " FILENAME\"", 0);
252c22bd47dSdrh     return TCL_ERROR;
253c22bd47dSdrh   }
254*06b2718aSdrh   db = (sqlite*)strtol(argv[1], 0, 0);
255c22bd47dSdrh   sqlite_create_function(db, "x_coalesce", -1, ifnullFunc, 0);
256c22bd47dSdrh   sqlite_create_function(db, "x_sqlite_exec", 1, sqliteExecFunc, db);
257c22bd47dSdrh   return TCL_OK;
258c22bd47dSdrh }
259c22bd47dSdrh 
260c22bd47dSdrh /*
261c22bd47dSdrh ** Routines to implement the x_count() aggregate function.
262c22bd47dSdrh */
263c22bd47dSdrh typedef struct CountCtx CountCtx;
264c22bd47dSdrh struct CountCtx {
265c22bd47dSdrh   int n;
266c22bd47dSdrh };
267c22bd47dSdrh static void countStep(sqlite_func *context, int argc, const char **argv){
268c22bd47dSdrh   CountCtx *p;
269c22bd47dSdrh   p = sqlite_aggregate_context(context, sizeof(*p));
270c22bd47dSdrh   if( (argc==0 || argv[0]) && p ){
271c22bd47dSdrh     p->n++;
272c22bd47dSdrh   }
273c22bd47dSdrh }
274c22bd47dSdrh static void countFinalize(sqlite_func *context){
275c22bd47dSdrh   CountCtx *p;
276c22bd47dSdrh   p = sqlite_aggregate_context(context, sizeof(*p));
277c22bd47dSdrh   sqlite_set_result_int(context, p ? p->n : 0);
278c22bd47dSdrh }
279c22bd47dSdrh 
280c22bd47dSdrh /*
281c22bd47dSdrh ** Usage:  sqlite_test_create_aggregate DB
282c22bd47dSdrh **
283c22bd47dSdrh ** Call the sqlite_create_function API on the given database in order
284c22bd47dSdrh ** to create a function named "x_count".  This function does the same thing
285c22bd47dSdrh ** as the "md5sum" function.
286c22bd47dSdrh **
287c22bd47dSdrh ** The original motivation for this routine was to be able to call the
288c22bd47dSdrh ** sqlite_create_aggregate function while a query is in progress in order
289c22bd47dSdrh ** to test the SQLITE_MISUSE detection logic.
290c22bd47dSdrh */
291c22bd47dSdrh static int sqlite_test_create_aggregate(
292c22bd47dSdrh   void *NotUsed,
293c22bd47dSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
294c22bd47dSdrh   int argc,              /* Number of arguments */
295c22bd47dSdrh   char **argv            /* Text of each argument */
296c22bd47dSdrh ){
297c22bd47dSdrh   sqlite *db;
298c22bd47dSdrh   if( argc!=2 ){
299c22bd47dSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
300c22bd47dSdrh        " FILENAME\"", 0);
301c22bd47dSdrh     return TCL_ERROR;
302c22bd47dSdrh   }
303*06b2718aSdrh   db = (sqlite*)strtol(argv[1], 0, 0);
304c22bd47dSdrh   sqlite_create_aggregate(db, "x_count", 0, countStep, countFinalize, 0);
305c22bd47dSdrh   sqlite_create_aggregate(db, "x_count", 1, countStep, countFinalize, 0);
306c22bd47dSdrh   return TCL_OK;
307c22bd47dSdrh }
308c22bd47dSdrh 
309c22bd47dSdrh 
310c22bd47dSdrh 
311c22bd47dSdrh /*
312d1bf3512Sdrh ** Usage:  sqlite_mprintf_int FORMAT INTEGER INTEGER INTEGER
313d1bf3512Sdrh **
314d1bf3512Sdrh ** Call mprintf with three integer arguments
315d1bf3512Sdrh */
316d1bf3512Sdrh static int sqlite_mprintf_int(
317d1bf3512Sdrh   void *NotUsed,
318d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
319d1bf3512Sdrh   int argc,              /* Number of arguments */
320d1bf3512Sdrh   char **argv            /* Text of each argument */
321d1bf3512Sdrh ){
322d1bf3512Sdrh   int a[3], i;
323d1bf3512Sdrh   char *z;
324d1bf3512Sdrh   if( argc!=5 ){
325d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
326d1bf3512Sdrh        " FORMAT INT INT INT\"", 0);
327d1bf3512Sdrh     return TCL_ERROR;
328d1bf3512Sdrh   }
329d1bf3512Sdrh   for(i=2; i<5; i++){
330d1bf3512Sdrh     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
331d1bf3512Sdrh   }
332d1bf3512Sdrh   z = sqlite_mprintf(argv[1], a[0], a[1], a[2]);
333d1bf3512Sdrh   Tcl_AppendResult(interp, z, 0);
334d1bf3512Sdrh   sqliteFree(z);
335d1bf3512Sdrh   return TCL_OK;
336d1bf3512Sdrh }
337d1bf3512Sdrh 
338d1bf3512Sdrh /*
339d1bf3512Sdrh ** Usage:  sqlite_mprintf_str FORMAT INTEGER INTEGER STRING
340d1bf3512Sdrh **
341d1bf3512Sdrh ** Call mprintf with two integer arguments and one string argument
342d1bf3512Sdrh */
343d1bf3512Sdrh static int sqlite_mprintf_str(
344d1bf3512Sdrh   void *NotUsed,
345d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
346d1bf3512Sdrh   int argc,              /* Number of arguments */
347d1bf3512Sdrh   char **argv            /* Text of each argument */
348d1bf3512Sdrh ){
349d1bf3512Sdrh   int a[3], i;
350d1bf3512Sdrh   char *z;
351f220b24fSchw   if( argc<4 || argc>5 ){
352d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
353f220b24fSchw        " FORMAT INT INT ?STRING?\"", 0);
354d1bf3512Sdrh     return TCL_ERROR;
355d1bf3512Sdrh   }
356d1bf3512Sdrh   for(i=2; i<4; i++){
357d1bf3512Sdrh     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
358d1bf3512Sdrh   }
359f220b24fSchw   z = sqlite_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
360d1bf3512Sdrh   Tcl_AppendResult(interp, z, 0);
361d1bf3512Sdrh   sqliteFree(z);
362d1bf3512Sdrh   return TCL_OK;
363d1bf3512Sdrh }
364d1bf3512Sdrh 
365d1bf3512Sdrh /*
366d1bf3512Sdrh ** Usage:  sqlite_mprintf_str FORMAT INTEGER INTEGER DOUBLE
367d1bf3512Sdrh **
368d1bf3512Sdrh ** Call mprintf with two integer arguments and one double argument
369d1bf3512Sdrh */
370d1bf3512Sdrh static int sqlite_mprintf_double(
371d1bf3512Sdrh   void *NotUsed,
372d1bf3512Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
373d1bf3512Sdrh   int argc,              /* Number of arguments */
374d1bf3512Sdrh   char **argv            /* Text of each argument */
375d1bf3512Sdrh ){
376d1bf3512Sdrh   int a[3], i;
377d1bf3512Sdrh   double r;
378d1bf3512Sdrh   char *z;
379d1bf3512Sdrh   if( argc!=5 ){
380d1bf3512Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
381d1bf3512Sdrh        " FORMAT INT INT STRING\"", 0);
382d1bf3512Sdrh     return TCL_ERROR;
383d1bf3512Sdrh   }
384d1bf3512Sdrh   for(i=2; i<4; i++){
385d1bf3512Sdrh     if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
386d1bf3512Sdrh   }
387d1bf3512Sdrh   if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
388d1bf3512Sdrh   z = sqlite_mprintf(argv[1], a[0], a[1], r);
389d1bf3512Sdrh   Tcl_AppendResult(interp, z, 0);
390d1bf3512Sdrh   sqliteFree(z);
391d1bf3512Sdrh   return TCL_OK;
392d1bf3512Sdrh }
393d1bf3512Sdrh 
394d1bf3512Sdrh /*
395daffd0e5Sdrh ** Usage: sqlite_malloc_fail N
396daffd0e5Sdrh **
397afa4a020Sdrh ** Rig sqliteMalloc() to fail on the N-th call.  Turn off this mechanism
398daffd0e5Sdrh ** and reset the sqlite_malloc_failed variable is N==0.
399daffd0e5Sdrh */
400daffd0e5Sdrh #ifdef MEMORY_DEBUG
401daffd0e5Sdrh static int sqlite_malloc_fail(
402daffd0e5Sdrh   void *NotUsed,
403daffd0e5Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
404daffd0e5Sdrh   int argc,              /* Number of arguments */
405daffd0e5Sdrh   char **argv            /* Text of each argument */
406daffd0e5Sdrh ){
407daffd0e5Sdrh   int n;
408daffd0e5Sdrh   if( argc!=2 ){
409daffd0e5Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0);
410daffd0e5Sdrh     return TCL_ERROR;
411daffd0e5Sdrh   }
412daffd0e5Sdrh   if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
413daffd0e5Sdrh   sqlite_iMallocFail = n;
414daffd0e5Sdrh   sqlite_malloc_failed = 0;
415daffd0e5Sdrh   return TCL_OK;
416daffd0e5Sdrh }
417daffd0e5Sdrh #endif
418daffd0e5Sdrh 
419daffd0e5Sdrh /*
420daffd0e5Sdrh ** Usage: sqlite_malloc_stat
421daffd0e5Sdrh **
422daffd0e5Sdrh ** Return the number of prior calls to sqliteMalloc() and sqliteFree().
423daffd0e5Sdrh */
424daffd0e5Sdrh #ifdef MEMORY_DEBUG
425daffd0e5Sdrh static int sqlite_malloc_stat(
426daffd0e5Sdrh   void *NotUsed,
427daffd0e5Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
428daffd0e5Sdrh   int argc,              /* Number of arguments */
429daffd0e5Sdrh   char **argv            /* Text of each argument */
430daffd0e5Sdrh ){
431daffd0e5Sdrh   char zBuf[200];
432daffd0e5Sdrh   sprintf(zBuf, "%d %d %d", sqlite_nMalloc, sqlite_nFree, sqlite_iMallocFail);
433daffd0e5Sdrh   Tcl_AppendResult(interp, zBuf, 0);
434daffd0e5Sdrh   return TCL_OK;
435daffd0e5Sdrh }
436daffd0e5Sdrh #endif
437daffd0e5Sdrh 
438daffd0e5Sdrh /*
43928b4e489Sdrh ** Usage:  sqlite_abort
44028b4e489Sdrh **
44128b4e489Sdrh ** Shutdown the process immediately.  This is not a clean shutdown.
44228b4e489Sdrh ** This command is used to test the recoverability of a database in
44328b4e489Sdrh ** the event of a program crash.
44428b4e489Sdrh */
44528b4e489Sdrh static int sqlite_abort(
44628b4e489Sdrh   void *NotUsed,
44728b4e489Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
44828b4e489Sdrh   int argc,              /* Number of arguments */
44928b4e489Sdrh   char **argv            /* Text of each argument */
45028b4e489Sdrh ){
45128b4e489Sdrh   assert( interp==0 );   /* This will always fail */
45228b4e489Sdrh   return TCL_OK;
45328b4e489Sdrh }
45428b4e489Sdrh 
45528b4e489Sdrh /*
456d1bf3512Sdrh ** Register commands with the TCL interpreter.
457d1bf3512Sdrh */
458d1bf3512Sdrh int Sqlitetest1_Init(Tcl_Interp *interp){
459487ab3caSdrh   extern int sqlite_search_count;
460d1bf3512Sdrh   Tcl_CreateCommand(interp, "sqlite_mprintf_int", sqlite_mprintf_int, 0, 0);
461d1bf3512Sdrh   Tcl_CreateCommand(interp, "sqlite_mprintf_str", sqlite_mprintf_str, 0, 0);
462d1bf3512Sdrh   Tcl_CreateCommand(interp, "sqlite_mprintf_double", sqlite_mprintf_double,0,0);
463d1bf3512Sdrh   Tcl_CreateCommand(interp, "sqlite_open", sqlite_test_open, 0, 0);
464af9ff33aSdrh   Tcl_CreateCommand(interp, "sqlite_last_insert_rowid", test_last_rowid, 0, 0);
465d1bf3512Sdrh   Tcl_CreateCommand(interp, "sqlite_exec_printf", test_exec_printf, 0, 0);
466d1bf3512Sdrh   Tcl_CreateCommand(interp, "sqlite_get_table_printf", test_get_table_printf,
467d1bf3512Sdrh       0, 0);
468d1bf3512Sdrh   Tcl_CreateCommand(interp, "sqlite_close", sqlite_test_close, 0, 0);
469c22bd47dSdrh   Tcl_CreateCommand(interp, "sqlite_create_function",
470c22bd47dSdrh       sqlite_test_create_function, 0, 0);
471c22bd47dSdrh   Tcl_CreateCommand(interp, "sqlite_create_aggregate",
472c22bd47dSdrh       sqlite_test_create_aggregate, 0, 0);
473487ab3caSdrh   Tcl_LinkVar(interp, "sqlite_search_count",
474487ab3caSdrh       (char*)&sqlite_search_count, TCL_LINK_INT);
475daffd0e5Sdrh #ifdef MEMORY_DEBUG
476daffd0e5Sdrh   Tcl_CreateCommand(interp, "sqlite_malloc_fail", sqlite_malloc_fail, 0, 0);
477daffd0e5Sdrh   Tcl_CreateCommand(interp, "sqlite_malloc_stat", sqlite_malloc_stat, 0, 0);
478daffd0e5Sdrh #endif
47928b4e489Sdrh   Tcl_CreateCommand(interp, "sqlite_abort", sqlite_abort, 0, 0);
480d1bf3512Sdrh   return TCL_OK;
481d1bf3512Sdrh }
482