blob: 09f1b8a7918e98fe360125342af6dda6fa0e495f [file] [log] [blame]
drhd1bf3512001-04-07 15:24:33 +00001/*
drhb19a2bc2001-09-16 00:13:26 +00002** 2001 September 15
drhd1bf3512001-04-07 15:24:33 +00003**
drhb19a2bc2001-09-16 00:13:26 +00004** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
drhd1bf3512001-04-07 15:24:33 +00006**
drhb19a2bc2001-09-16 00:13:26 +00007** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
drhd1bf3512001-04-07 15:24:33 +000010**
11*************************************************************************
12** Code for testing the printf() interface to SQLite. This code
13** is not included in the SQLite library. It is used for automated
14** testing of the SQLite library.
15**
drhb19a2bc2001-09-16 00:13:26 +000016** $Id: test1.c,v 1.3 2001/09/16 00:13:27 drh Exp $
drhd1bf3512001-04-07 15:24:33 +000017*/
18#include "sqliteInt.h"
19#include "tcl.h"
20#include <stdlib.h>
21#include <string.h>
22
23/*
24** Usage: sqlite_open filename
25**
26** Returns: The name of an open database.
27*/
28static int sqlite_test_open(
29 void *NotUsed,
30 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
31 int argc, /* Number of arguments */
32 char **argv /* Text of each argument */
33){
34 sqlite *db;
35 char *zErr = 0;
36 char zBuf[100];
37 if( argc!=2 ){
38 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
39 " FILENAME\"", 0);
40 return TCL_ERROR;
41 }
42 db = sqlite_open(argv[1], 0666, &zErr);
43 if( db==0 ){
44 Tcl_AppendResult(interp, zErr, 0);
45 free(zErr);
46 return TCL_ERROR;
47 }
48 sprintf(zBuf,"%d",(int)db);
49 Tcl_AppendResult(interp, zBuf, 0);
50 return TCL_OK;
51}
52
53/*
54** The callback routine for sqlite_exec_printf().
55*/
56static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
57 Tcl_DString *str = (Tcl_DString*)pArg;
58 int i;
59
60 if( Tcl_DStringLength(str)==0 ){
61 for(i=0; i<argc; i++){
62 Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
63 }
64 }
65 for(i=0; i<argc; i++){
66 Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
67 }
68 return 0;
69}
70
71/*
72** Usage: sqlite_exec_printf DB FORMAT STRING
73**
74** Invoke the sqlite_exec_printf() interface using the open database
75** DB. The SQL is the string FORMAT. The format string should contain
76** one %s or %q. STRING is the value inserted into %s or %q.
77*/
78static int test_exec_printf(
79 void *NotUsed,
80 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
81 int argc, /* Number of arguments */
82 char **argv /* Text of each argument */
83){
84 sqlite *db;
85 Tcl_DString str;
86 int rc;
87 char *zErr = 0;
88 char zBuf[30];
89 if( argc!=4 ){
90 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
91 " DB FORMAT STRING", 0);
92 return TCL_ERROR;
93 }
94 db = (sqlite*)atoi(argv[1]);
95 Tcl_DStringInit(&str);
96 rc = sqlite_exec_printf(db, argv[2], exec_printf_cb, &str, &zErr, argv[3]);
97 sprintf(zBuf, "%d", rc);
98 Tcl_AppendElement(interp, zBuf);
99 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
100 Tcl_DStringFree(&str);
101 if( zErr ) free(zErr);
102 return TCL_OK;
103}
104
105/*
106** Usage: sqlite_get_table_printf DB FORMAT STRING
107**
108** Invoke the sqlite_get_table_printf() interface using the open database
109** DB. The SQL is the string FORMAT. The format string should contain
110** one %s or %q. STRING is the value inserted into %s or %q.
111*/
112static int test_get_table_printf(
113 void *NotUsed,
114 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
115 int argc, /* Number of arguments */
116 char **argv /* Text of each argument */
117){
118 sqlite *db;
119 Tcl_DString str;
120 int rc;
121 char *zErr = 0;
122 int nRow, nCol;
123 char **aResult;
124 int i;
125 char zBuf[30];
126 if( argc!=4 ){
127 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
128 " DB FORMAT STRING", 0);
129 return TCL_ERROR;
130 }
131 db = (sqlite*)atoi(argv[1]);
132 Tcl_DStringInit(&str);
133 rc = sqlite_get_table_printf(db, argv[2], &aResult, &nRow, &nCol,
134 &zErr, argv[3]);
135 sprintf(zBuf, "%d", rc);
136 Tcl_AppendElement(interp, zBuf);
137 if( rc==SQLITE_OK ){
138 sprintf(zBuf, "%d", nRow);
139 Tcl_AppendElement(interp, zBuf);
140 sprintf(zBuf, "%d", nCol);
141 Tcl_AppendElement(interp, zBuf);
142 for(i=0; i<(nRow+1)*nCol; i++){
143 Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
144 }
145 }else{
146 Tcl_AppendElement(interp, zErr);
147 }
148 sqlite_free_table(aResult);
149 if( zErr ) free(zErr);
150 return TCL_OK;
151}
152
153/*
154** Usage: sqlite_close DB
155**
156** Closes the database opened by sqlite_open.
157*/
158static int sqlite_test_close(
159 void *NotUsed,
160 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
161 int argc, /* Number of arguments */
162 char **argv /* Text of each argument */
163){
164 sqlite *db;
165 if( argc!=2 ){
166 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
167 " FILENAME\"", 0);
168 return TCL_ERROR;
169 }
170 db = (sqlite*)atoi(argv[1]);
171 sqlite_close(db);
172 return TCL_OK;
173}
174
175/*
176** Usage: sqlite_mprintf_int FORMAT INTEGER INTEGER INTEGER
177**
178** Call mprintf with three integer arguments
179*/
180static int sqlite_mprintf_int(
181 void *NotUsed,
182 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
183 int argc, /* Number of arguments */
184 char **argv /* Text of each argument */
185){
186 int a[3], i;
187 char *z;
188 if( argc!=5 ){
189 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
190 " FORMAT INT INT INT\"", 0);
191 return TCL_ERROR;
192 }
193 for(i=2; i<5; i++){
194 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
195 }
196 z = sqlite_mprintf(argv[1], a[0], a[1], a[2]);
197 Tcl_AppendResult(interp, z, 0);
198 sqliteFree(z);
199 return TCL_OK;
200}
201
202/*
203** Usage: sqlite_mprintf_str FORMAT INTEGER INTEGER STRING
204**
205** Call mprintf with two integer arguments and one string argument
206*/
207static int sqlite_mprintf_str(
208 void *NotUsed,
209 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
210 int argc, /* Number of arguments */
211 char **argv /* Text of each argument */
212){
213 int a[3], i;
214 char *z;
215 if( argc!=5 ){
216 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
217 " FORMAT INT INT STRING\"", 0);
218 return TCL_ERROR;
219 }
220 for(i=2; i<4; i++){
221 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
222 }
223 z = sqlite_mprintf(argv[1], a[0], a[1], argv[4]);
224 Tcl_AppendResult(interp, z, 0);
225 sqliteFree(z);
226 return TCL_OK;
227}
228
229/*
230** Usage: sqlite_mprintf_str FORMAT INTEGER INTEGER DOUBLE
231**
232** Call mprintf with two integer arguments and one double argument
233*/
234static int sqlite_mprintf_double(
235 void *NotUsed,
236 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
237 int argc, /* Number of arguments */
238 char **argv /* Text of each argument */
239){
240 int a[3], i;
241 double r;
242 char *z;
243 if( argc!=5 ){
244 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
245 " FORMAT INT INT STRING\"", 0);
246 return TCL_ERROR;
247 }
248 for(i=2; i<4; i++){
249 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
250 }
251 if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
252 z = sqlite_mprintf(argv[1], a[0], a[1], r);
253 Tcl_AppendResult(interp, z, 0);
254 sqliteFree(z);
255 return TCL_OK;
256}
257
258/*
drhdaffd0e2001-04-11 14:28:42 +0000259** Usage: sqlite_malloc_fail N
260**
261** Rig sqliteMalloc() to fail on the N-th call. Turn of this mechanism
262** and reset the sqlite_malloc_failed variable is N==0.
263*/
264#ifdef MEMORY_DEBUG
265static int sqlite_malloc_fail(
266 void *NotUsed,
267 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
268 int argc, /* Number of arguments */
269 char **argv /* Text of each argument */
270){
271 int n;
272 if( argc!=2 ){
273 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0);
274 return TCL_ERROR;
275 }
276 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
277 sqlite_iMallocFail = n;
278 sqlite_malloc_failed = 0;
279 return TCL_OK;
280}
281#endif
282
283/*
284** Usage: sqlite_malloc_stat
285**
286** Return the number of prior calls to sqliteMalloc() and sqliteFree().
287*/
288#ifdef MEMORY_DEBUG
289static int sqlite_malloc_stat(
290 void *NotUsed,
291 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
292 int argc, /* Number of arguments */
293 char **argv /* Text of each argument */
294){
295 char zBuf[200];
296 sprintf(zBuf, "%d %d %d", sqlite_nMalloc, sqlite_nFree, sqlite_iMallocFail);
297 Tcl_AppendResult(interp, zBuf, 0);
298 return TCL_OK;
299}
300#endif
301
302/*
drhd1bf3512001-04-07 15:24:33 +0000303** Register commands with the TCL interpreter.
304*/
305int Sqlitetest1_Init(Tcl_Interp *interp){
306 Tcl_CreateCommand(interp, "sqlite_mprintf_int", sqlite_mprintf_int, 0, 0);
307 Tcl_CreateCommand(interp, "sqlite_mprintf_str", sqlite_mprintf_str, 0, 0);
308 Tcl_CreateCommand(interp, "sqlite_mprintf_double", sqlite_mprintf_double,0,0);
309 Tcl_CreateCommand(interp, "sqlite_open", sqlite_test_open, 0, 0);
310 Tcl_CreateCommand(interp, "sqlite_exec_printf", test_exec_printf, 0, 0);
311 Tcl_CreateCommand(interp, "sqlite_get_table_printf", test_get_table_printf,
312 0, 0);
313 Tcl_CreateCommand(interp, "sqlite_close", sqlite_test_close, 0, 0);
drhdaffd0e2001-04-11 14:28:42 +0000314#ifdef MEMORY_DEBUG
315 Tcl_CreateCommand(interp, "sqlite_malloc_fail", sqlite_malloc_fail, 0, 0);
316 Tcl_CreateCommand(interp, "sqlite_malloc_stat", sqlite_malloc_stat, 0, 0);
317#endif
drhd1bf3512001-04-07 15:24:33 +0000318 return TCL_OK;
319}