drh | d1bf351 | 2001-04-07 15:24:33 +0000 | [diff] [blame] | 1 | /* |
drh | b19a2bc | 2001-09-16 00:13:26 +0000 | [diff] [blame^] | 2 | ** 2001 September 15 |
drh | d1bf351 | 2001-04-07 15:24:33 +0000 | [diff] [blame] | 3 | ** |
drh | b19a2bc | 2001-09-16 00:13:26 +0000 | [diff] [blame^] | 4 | ** The author disclaims copyright to this source code. In place of |
| 5 | ** a legal notice, here is a blessing: |
drh | d1bf351 | 2001-04-07 15:24:33 +0000 | [diff] [blame] | 6 | ** |
drh | b19a2bc | 2001-09-16 00:13:26 +0000 | [diff] [blame^] | 7 | ** 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. |
drh | d1bf351 | 2001-04-07 15:24:33 +0000 | [diff] [blame] | 10 | ** |
| 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 | ** |
drh | b19a2bc | 2001-09-16 00:13:26 +0000 | [diff] [blame^] | 16 | ** $Id: test1.c,v 1.3 2001/09/16 00:13:27 drh Exp $ |
drh | d1bf351 | 2001-04-07 15:24:33 +0000 | [diff] [blame] | 17 | */ |
| 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 | */ |
| 28 | static 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 | */ |
| 56 | static 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 | */ |
| 78 | static 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 | */ |
| 112 | static 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 | */ |
| 158 | static 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 | */ |
| 180 | static 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 | */ |
| 207 | static 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 | */ |
| 234 | static 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 | /* |
drh | daffd0e | 2001-04-11 14:28:42 +0000 | [diff] [blame] | 259 | ** 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 |
| 265 | static 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 |
| 289 | static 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 | /* |
drh | d1bf351 | 2001-04-07 15:24:33 +0000 | [diff] [blame] | 303 | ** Register commands with the TCL interpreter. |
| 304 | */ |
| 305 | int 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); |
drh | daffd0e | 2001-04-11 14:28:42 +0000 | [diff] [blame] | 314 | #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 |
drh | d1bf351 | 2001-04-07 15:24:33 +0000 | [diff] [blame] | 318 | return TCL_OK; |
| 319 | } |