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*487ab3caSdrh ** $Id: test1.c,v 1.5 2001/11/08 00:45:21 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 } 94d1bf3512Sdrh db = (sqlite*)atoi(argv[1]); 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 } 131d1bf3512Sdrh db = (sqlite*)atoi(argv[1]); 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 153d1bf3512Sdrh /* 154d1bf3512Sdrh ** Usage: sqlite_close DB 155d1bf3512Sdrh ** 156d1bf3512Sdrh ** Closes the database opened by sqlite_open. 157d1bf3512Sdrh */ 158d1bf3512Sdrh static int sqlite_test_close( 159d1bf3512Sdrh void *NotUsed, 160d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 161d1bf3512Sdrh int argc, /* Number of arguments */ 162d1bf3512Sdrh char **argv /* Text of each argument */ 163d1bf3512Sdrh ){ 164d1bf3512Sdrh sqlite *db; 165d1bf3512Sdrh if( argc!=2 ){ 166d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 167d1bf3512Sdrh " FILENAME\"", 0); 168d1bf3512Sdrh return TCL_ERROR; 169d1bf3512Sdrh } 170d1bf3512Sdrh db = (sqlite*)atoi(argv[1]); 171d1bf3512Sdrh sqlite_close(db); 172d1bf3512Sdrh return TCL_OK; 173d1bf3512Sdrh } 174d1bf3512Sdrh 175d1bf3512Sdrh /* 176d1bf3512Sdrh ** Usage: sqlite_mprintf_int FORMAT INTEGER INTEGER INTEGER 177d1bf3512Sdrh ** 178d1bf3512Sdrh ** Call mprintf with three integer arguments 179d1bf3512Sdrh */ 180d1bf3512Sdrh static int sqlite_mprintf_int( 181d1bf3512Sdrh void *NotUsed, 182d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 183d1bf3512Sdrh int argc, /* Number of arguments */ 184d1bf3512Sdrh char **argv /* Text of each argument */ 185d1bf3512Sdrh ){ 186d1bf3512Sdrh int a[3], i; 187d1bf3512Sdrh char *z; 188d1bf3512Sdrh if( argc!=5 ){ 189d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 190d1bf3512Sdrh " FORMAT INT INT INT\"", 0); 191d1bf3512Sdrh return TCL_ERROR; 192d1bf3512Sdrh } 193d1bf3512Sdrh for(i=2; i<5; i++){ 194d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 195d1bf3512Sdrh } 196d1bf3512Sdrh z = sqlite_mprintf(argv[1], a[0], a[1], a[2]); 197d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 198d1bf3512Sdrh sqliteFree(z); 199d1bf3512Sdrh return TCL_OK; 200d1bf3512Sdrh } 201d1bf3512Sdrh 202d1bf3512Sdrh /* 203d1bf3512Sdrh ** Usage: sqlite_mprintf_str FORMAT INTEGER INTEGER STRING 204d1bf3512Sdrh ** 205d1bf3512Sdrh ** Call mprintf with two integer arguments and one string argument 206d1bf3512Sdrh */ 207d1bf3512Sdrh static int sqlite_mprintf_str( 208d1bf3512Sdrh void *NotUsed, 209d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 210d1bf3512Sdrh int argc, /* Number of arguments */ 211d1bf3512Sdrh char **argv /* Text of each argument */ 212d1bf3512Sdrh ){ 213d1bf3512Sdrh int a[3], i; 214d1bf3512Sdrh char *z; 215d1bf3512Sdrh if( argc!=5 ){ 216d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 217d1bf3512Sdrh " FORMAT INT INT STRING\"", 0); 218d1bf3512Sdrh return TCL_ERROR; 219d1bf3512Sdrh } 220d1bf3512Sdrh for(i=2; i<4; i++){ 221d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 222d1bf3512Sdrh } 223d1bf3512Sdrh z = sqlite_mprintf(argv[1], a[0], a[1], argv[4]); 224d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 225d1bf3512Sdrh sqliteFree(z); 226d1bf3512Sdrh return TCL_OK; 227d1bf3512Sdrh } 228d1bf3512Sdrh 229d1bf3512Sdrh /* 230d1bf3512Sdrh ** Usage: sqlite_mprintf_str FORMAT INTEGER INTEGER DOUBLE 231d1bf3512Sdrh ** 232d1bf3512Sdrh ** Call mprintf with two integer arguments and one double argument 233d1bf3512Sdrh */ 234d1bf3512Sdrh static int sqlite_mprintf_double( 235d1bf3512Sdrh void *NotUsed, 236d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 237d1bf3512Sdrh int argc, /* Number of arguments */ 238d1bf3512Sdrh char **argv /* Text of each argument */ 239d1bf3512Sdrh ){ 240d1bf3512Sdrh int a[3], i; 241d1bf3512Sdrh double r; 242d1bf3512Sdrh char *z; 243d1bf3512Sdrh if( argc!=5 ){ 244d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 245d1bf3512Sdrh " FORMAT INT INT STRING\"", 0); 246d1bf3512Sdrh return TCL_ERROR; 247d1bf3512Sdrh } 248d1bf3512Sdrh for(i=2; i<4; i++){ 249d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 250d1bf3512Sdrh } 251d1bf3512Sdrh if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR; 252d1bf3512Sdrh z = sqlite_mprintf(argv[1], a[0], a[1], r); 253d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 254d1bf3512Sdrh sqliteFree(z); 255d1bf3512Sdrh return TCL_OK; 256d1bf3512Sdrh } 257d1bf3512Sdrh 258d1bf3512Sdrh /* 259daffd0e5Sdrh ** Usage: sqlite_malloc_fail N 260daffd0e5Sdrh ** 261afa4a020Sdrh ** Rig sqliteMalloc() to fail on the N-th call. Turn off this mechanism 262daffd0e5Sdrh ** and reset the sqlite_malloc_failed variable is N==0. 263daffd0e5Sdrh */ 264daffd0e5Sdrh #ifdef MEMORY_DEBUG 265daffd0e5Sdrh static int sqlite_malloc_fail( 266daffd0e5Sdrh void *NotUsed, 267daffd0e5Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 268daffd0e5Sdrh int argc, /* Number of arguments */ 269daffd0e5Sdrh char **argv /* Text of each argument */ 270daffd0e5Sdrh ){ 271daffd0e5Sdrh int n; 272daffd0e5Sdrh if( argc!=2 ){ 273daffd0e5Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0); 274daffd0e5Sdrh return TCL_ERROR; 275daffd0e5Sdrh } 276daffd0e5Sdrh if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; 277daffd0e5Sdrh sqlite_iMallocFail = n; 278daffd0e5Sdrh sqlite_malloc_failed = 0; 279daffd0e5Sdrh return TCL_OK; 280daffd0e5Sdrh } 281daffd0e5Sdrh #endif 282daffd0e5Sdrh 283daffd0e5Sdrh /* 284daffd0e5Sdrh ** Usage: sqlite_malloc_stat 285daffd0e5Sdrh ** 286daffd0e5Sdrh ** Return the number of prior calls to sqliteMalloc() and sqliteFree(). 287daffd0e5Sdrh */ 288daffd0e5Sdrh #ifdef MEMORY_DEBUG 289daffd0e5Sdrh static int sqlite_malloc_stat( 290daffd0e5Sdrh void *NotUsed, 291daffd0e5Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 292daffd0e5Sdrh int argc, /* Number of arguments */ 293daffd0e5Sdrh char **argv /* Text of each argument */ 294daffd0e5Sdrh ){ 295daffd0e5Sdrh char zBuf[200]; 296daffd0e5Sdrh sprintf(zBuf, "%d %d %d", sqlite_nMalloc, sqlite_nFree, sqlite_iMallocFail); 297daffd0e5Sdrh Tcl_AppendResult(interp, zBuf, 0); 298daffd0e5Sdrh return TCL_OK; 299daffd0e5Sdrh } 300daffd0e5Sdrh #endif 301daffd0e5Sdrh 302daffd0e5Sdrh /* 303d1bf3512Sdrh ** Register commands with the TCL interpreter. 304d1bf3512Sdrh */ 305d1bf3512Sdrh int Sqlitetest1_Init(Tcl_Interp *interp){ 306*487ab3caSdrh extern int sqlite_search_count; 307d1bf3512Sdrh Tcl_CreateCommand(interp, "sqlite_mprintf_int", sqlite_mprintf_int, 0, 0); 308d1bf3512Sdrh Tcl_CreateCommand(interp, "sqlite_mprintf_str", sqlite_mprintf_str, 0, 0); 309d1bf3512Sdrh Tcl_CreateCommand(interp, "sqlite_mprintf_double", sqlite_mprintf_double,0,0); 310d1bf3512Sdrh Tcl_CreateCommand(interp, "sqlite_open", sqlite_test_open, 0, 0); 311d1bf3512Sdrh Tcl_CreateCommand(interp, "sqlite_exec_printf", test_exec_printf, 0, 0); 312d1bf3512Sdrh Tcl_CreateCommand(interp, "sqlite_get_table_printf", test_get_table_printf, 313d1bf3512Sdrh 0, 0); 314d1bf3512Sdrh Tcl_CreateCommand(interp, "sqlite_close", sqlite_test_close, 0, 0); 315*487ab3caSdrh Tcl_LinkVar(interp, "sqlite_search_count", 316*487ab3caSdrh (char*)&sqlite_search_count, TCL_LINK_INT); 317daffd0e5Sdrh #ifdef MEMORY_DEBUG 318daffd0e5Sdrh Tcl_CreateCommand(interp, "sqlite_malloc_fail", sqlite_malloc_fail, 0, 0); 319daffd0e5Sdrh Tcl_CreateCommand(interp, "sqlite_malloc_stat", sqlite_malloc_stat, 0, 0); 320daffd0e5Sdrh #endif 321d1bf3512Sdrh return TCL_OK; 322d1bf3512Sdrh } 323