1d1bf3512Sdrh /* 2d1bf3512Sdrh ** Copyright (c) 2001 D. Richard Hipp 3d1bf3512Sdrh ** 4d1bf3512Sdrh ** This program is free software; you can redistribute it and/or 5d1bf3512Sdrh ** modify it under the terms of the GNU General Public 6d1bf3512Sdrh ** License as published by the Free Software Foundation; either 7d1bf3512Sdrh ** version 2 of the License, or (at your option) any later version. 8d1bf3512Sdrh ** 9d1bf3512Sdrh ** This program is distributed in the hope that it will be useful, 10d1bf3512Sdrh ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11d1bf3512Sdrh ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12d1bf3512Sdrh ** General Public License for more details. 13d1bf3512Sdrh ** 14d1bf3512Sdrh ** You should have received a copy of the GNU General Public 15d1bf3512Sdrh ** License along with this library; if not, write to the 16d1bf3512Sdrh ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17d1bf3512Sdrh ** Boston, MA 02111-1307, USA. 18d1bf3512Sdrh ** 19d1bf3512Sdrh ** Author contact information: 20d1bf3512Sdrh ** [email protected] 21d1bf3512Sdrh ** http://www.hwaci.com/drh/ 22d1bf3512Sdrh ** 23d1bf3512Sdrh ************************************************************************* 24d1bf3512Sdrh ** Code for testing the printf() interface to SQLite. This code 25d1bf3512Sdrh ** is not included in the SQLite library. It is used for automated 26d1bf3512Sdrh ** testing of the SQLite library. 27d1bf3512Sdrh ** 28*daffd0e5Sdrh ** $Id: test1.c,v 1.2 2001/04/11 14:28:43 drh Exp $ 29d1bf3512Sdrh */ 30d1bf3512Sdrh #include "sqliteInt.h" 31d1bf3512Sdrh #include "tcl.h" 32d1bf3512Sdrh #include <stdlib.h> 33d1bf3512Sdrh #include <string.h> 34d1bf3512Sdrh 35d1bf3512Sdrh /* 36d1bf3512Sdrh ** Usage: sqlite_open filename 37d1bf3512Sdrh ** 38d1bf3512Sdrh ** Returns: The name of an open database. 39d1bf3512Sdrh */ 40d1bf3512Sdrh static int sqlite_test_open( 41d1bf3512Sdrh void *NotUsed, 42d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 43d1bf3512Sdrh int argc, /* Number of arguments */ 44d1bf3512Sdrh char **argv /* Text of each argument */ 45d1bf3512Sdrh ){ 46d1bf3512Sdrh sqlite *db; 47d1bf3512Sdrh char *zErr = 0; 48d1bf3512Sdrh char zBuf[100]; 49d1bf3512Sdrh if( argc!=2 ){ 50d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 51d1bf3512Sdrh " FILENAME\"", 0); 52d1bf3512Sdrh return TCL_ERROR; 53d1bf3512Sdrh } 54d1bf3512Sdrh db = sqlite_open(argv[1], 0666, &zErr); 55d1bf3512Sdrh if( db==0 ){ 56d1bf3512Sdrh Tcl_AppendResult(interp, zErr, 0); 57d1bf3512Sdrh free(zErr); 58d1bf3512Sdrh return TCL_ERROR; 59d1bf3512Sdrh } 60d1bf3512Sdrh sprintf(zBuf,"%d",(int)db); 61d1bf3512Sdrh Tcl_AppendResult(interp, zBuf, 0); 62d1bf3512Sdrh return TCL_OK; 63d1bf3512Sdrh } 64d1bf3512Sdrh 65d1bf3512Sdrh /* 66d1bf3512Sdrh ** The callback routine for sqlite_exec_printf(). 67d1bf3512Sdrh */ 68d1bf3512Sdrh static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){ 69d1bf3512Sdrh Tcl_DString *str = (Tcl_DString*)pArg; 70d1bf3512Sdrh int i; 71d1bf3512Sdrh 72d1bf3512Sdrh if( Tcl_DStringLength(str)==0 ){ 73d1bf3512Sdrh for(i=0; i<argc; i++){ 74d1bf3512Sdrh Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL"); 75d1bf3512Sdrh } 76d1bf3512Sdrh } 77d1bf3512Sdrh for(i=0; i<argc; i++){ 78d1bf3512Sdrh Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL"); 79d1bf3512Sdrh } 80d1bf3512Sdrh return 0; 81d1bf3512Sdrh } 82d1bf3512Sdrh 83d1bf3512Sdrh /* 84d1bf3512Sdrh ** Usage: sqlite_exec_printf DB FORMAT STRING 85d1bf3512Sdrh ** 86d1bf3512Sdrh ** Invoke the sqlite_exec_printf() interface using the open database 87d1bf3512Sdrh ** DB. The SQL is the string FORMAT. The format string should contain 88d1bf3512Sdrh ** one %s or %q. STRING is the value inserted into %s or %q. 89d1bf3512Sdrh */ 90d1bf3512Sdrh static int test_exec_printf( 91d1bf3512Sdrh void *NotUsed, 92d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 93d1bf3512Sdrh int argc, /* Number of arguments */ 94d1bf3512Sdrh char **argv /* Text of each argument */ 95d1bf3512Sdrh ){ 96d1bf3512Sdrh sqlite *db; 97d1bf3512Sdrh Tcl_DString str; 98d1bf3512Sdrh int rc; 99d1bf3512Sdrh char *zErr = 0; 100d1bf3512Sdrh char zBuf[30]; 101d1bf3512Sdrh if( argc!=4 ){ 102d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 103d1bf3512Sdrh " DB FORMAT STRING", 0); 104d1bf3512Sdrh return TCL_ERROR; 105d1bf3512Sdrh } 106d1bf3512Sdrh db = (sqlite*)atoi(argv[1]); 107d1bf3512Sdrh Tcl_DStringInit(&str); 108d1bf3512Sdrh rc = sqlite_exec_printf(db, argv[2], exec_printf_cb, &str, &zErr, argv[3]); 109d1bf3512Sdrh sprintf(zBuf, "%d", rc); 110d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 111d1bf3512Sdrh Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); 112d1bf3512Sdrh Tcl_DStringFree(&str); 113d1bf3512Sdrh if( zErr ) free(zErr); 114d1bf3512Sdrh return TCL_OK; 115d1bf3512Sdrh } 116d1bf3512Sdrh 117d1bf3512Sdrh /* 118d1bf3512Sdrh ** Usage: sqlite_get_table_printf DB FORMAT STRING 119d1bf3512Sdrh ** 120d1bf3512Sdrh ** Invoke the sqlite_get_table_printf() interface using the open database 121d1bf3512Sdrh ** DB. The SQL is the string FORMAT. The format string should contain 122d1bf3512Sdrh ** one %s or %q. STRING is the value inserted into %s or %q. 123d1bf3512Sdrh */ 124d1bf3512Sdrh static int test_get_table_printf( 125d1bf3512Sdrh void *NotUsed, 126d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 127d1bf3512Sdrh int argc, /* Number of arguments */ 128d1bf3512Sdrh char **argv /* Text of each argument */ 129d1bf3512Sdrh ){ 130d1bf3512Sdrh sqlite *db; 131d1bf3512Sdrh Tcl_DString str; 132d1bf3512Sdrh int rc; 133d1bf3512Sdrh char *zErr = 0; 134d1bf3512Sdrh int nRow, nCol; 135d1bf3512Sdrh char **aResult; 136d1bf3512Sdrh int i; 137d1bf3512Sdrh char zBuf[30]; 138d1bf3512Sdrh if( argc!=4 ){ 139d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 140d1bf3512Sdrh " DB FORMAT STRING", 0); 141d1bf3512Sdrh return TCL_ERROR; 142d1bf3512Sdrh } 143d1bf3512Sdrh db = (sqlite*)atoi(argv[1]); 144d1bf3512Sdrh Tcl_DStringInit(&str); 145d1bf3512Sdrh rc = sqlite_get_table_printf(db, argv[2], &aResult, &nRow, &nCol, 146d1bf3512Sdrh &zErr, argv[3]); 147d1bf3512Sdrh sprintf(zBuf, "%d", rc); 148d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 149d1bf3512Sdrh if( rc==SQLITE_OK ){ 150d1bf3512Sdrh sprintf(zBuf, "%d", nRow); 151d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 152d1bf3512Sdrh sprintf(zBuf, "%d", nCol); 153d1bf3512Sdrh Tcl_AppendElement(interp, zBuf); 154d1bf3512Sdrh for(i=0; i<(nRow+1)*nCol; i++){ 155d1bf3512Sdrh Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL"); 156d1bf3512Sdrh } 157d1bf3512Sdrh }else{ 158d1bf3512Sdrh Tcl_AppendElement(interp, zErr); 159d1bf3512Sdrh } 160d1bf3512Sdrh sqlite_free_table(aResult); 161d1bf3512Sdrh if( zErr ) free(zErr); 162d1bf3512Sdrh return TCL_OK; 163d1bf3512Sdrh } 164d1bf3512Sdrh 165d1bf3512Sdrh /* 166d1bf3512Sdrh ** Usage: sqlite_close DB 167d1bf3512Sdrh ** 168d1bf3512Sdrh ** Closes the database opened by sqlite_open. 169d1bf3512Sdrh */ 170d1bf3512Sdrh static int sqlite_test_close( 171d1bf3512Sdrh void *NotUsed, 172d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 173d1bf3512Sdrh int argc, /* Number of arguments */ 174d1bf3512Sdrh char **argv /* Text of each argument */ 175d1bf3512Sdrh ){ 176d1bf3512Sdrh sqlite *db; 177d1bf3512Sdrh if( argc!=2 ){ 178d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 179d1bf3512Sdrh " FILENAME\"", 0); 180d1bf3512Sdrh return TCL_ERROR; 181d1bf3512Sdrh } 182d1bf3512Sdrh db = (sqlite*)atoi(argv[1]); 183d1bf3512Sdrh sqlite_close(db); 184d1bf3512Sdrh return TCL_OK; 185d1bf3512Sdrh } 186d1bf3512Sdrh 187d1bf3512Sdrh /* 188d1bf3512Sdrh ** Usage: sqlite_mprintf_int FORMAT INTEGER INTEGER INTEGER 189d1bf3512Sdrh ** 190d1bf3512Sdrh ** Call mprintf with three integer arguments 191d1bf3512Sdrh */ 192d1bf3512Sdrh static int sqlite_mprintf_int( 193d1bf3512Sdrh void *NotUsed, 194d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 195d1bf3512Sdrh int argc, /* Number of arguments */ 196d1bf3512Sdrh char **argv /* Text of each argument */ 197d1bf3512Sdrh ){ 198d1bf3512Sdrh int a[3], i; 199d1bf3512Sdrh char *z; 200d1bf3512Sdrh if( argc!=5 ){ 201d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 202d1bf3512Sdrh " FORMAT INT INT INT\"", 0); 203d1bf3512Sdrh return TCL_ERROR; 204d1bf3512Sdrh } 205d1bf3512Sdrh for(i=2; i<5; i++){ 206d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 207d1bf3512Sdrh } 208d1bf3512Sdrh z = sqlite_mprintf(argv[1], a[0], a[1], a[2]); 209d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 210d1bf3512Sdrh sqliteFree(z); 211d1bf3512Sdrh return TCL_OK; 212d1bf3512Sdrh } 213d1bf3512Sdrh 214d1bf3512Sdrh /* 215d1bf3512Sdrh ** Usage: sqlite_mprintf_str FORMAT INTEGER INTEGER STRING 216d1bf3512Sdrh ** 217d1bf3512Sdrh ** Call mprintf with two integer arguments and one string argument 218d1bf3512Sdrh */ 219d1bf3512Sdrh static int sqlite_mprintf_str( 220d1bf3512Sdrh void *NotUsed, 221d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 222d1bf3512Sdrh int argc, /* Number of arguments */ 223d1bf3512Sdrh char **argv /* Text of each argument */ 224d1bf3512Sdrh ){ 225d1bf3512Sdrh int a[3], i; 226d1bf3512Sdrh char *z; 227d1bf3512Sdrh if( argc!=5 ){ 228d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 229d1bf3512Sdrh " FORMAT INT INT STRING\"", 0); 230d1bf3512Sdrh return TCL_ERROR; 231d1bf3512Sdrh } 232d1bf3512Sdrh for(i=2; i<4; i++){ 233d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 234d1bf3512Sdrh } 235d1bf3512Sdrh z = sqlite_mprintf(argv[1], a[0], a[1], argv[4]); 236d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 237d1bf3512Sdrh sqliteFree(z); 238d1bf3512Sdrh return TCL_OK; 239d1bf3512Sdrh } 240d1bf3512Sdrh 241d1bf3512Sdrh /* 242d1bf3512Sdrh ** Usage: sqlite_mprintf_str FORMAT INTEGER INTEGER DOUBLE 243d1bf3512Sdrh ** 244d1bf3512Sdrh ** Call mprintf with two integer arguments and one double argument 245d1bf3512Sdrh */ 246d1bf3512Sdrh static int sqlite_mprintf_double( 247d1bf3512Sdrh void *NotUsed, 248d1bf3512Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 249d1bf3512Sdrh int argc, /* Number of arguments */ 250d1bf3512Sdrh char **argv /* Text of each argument */ 251d1bf3512Sdrh ){ 252d1bf3512Sdrh int a[3], i; 253d1bf3512Sdrh double r; 254d1bf3512Sdrh char *z; 255d1bf3512Sdrh if( argc!=5 ){ 256d1bf3512Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 257d1bf3512Sdrh " FORMAT INT INT STRING\"", 0); 258d1bf3512Sdrh return TCL_ERROR; 259d1bf3512Sdrh } 260d1bf3512Sdrh for(i=2; i<4; i++){ 261d1bf3512Sdrh if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 262d1bf3512Sdrh } 263d1bf3512Sdrh if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR; 264d1bf3512Sdrh z = sqlite_mprintf(argv[1], a[0], a[1], r); 265d1bf3512Sdrh Tcl_AppendResult(interp, z, 0); 266d1bf3512Sdrh sqliteFree(z); 267d1bf3512Sdrh return TCL_OK; 268d1bf3512Sdrh } 269d1bf3512Sdrh 270d1bf3512Sdrh /* 271*daffd0e5Sdrh ** Usage: sqlite_malloc_fail N 272*daffd0e5Sdrh ** 273*daffd0e5Sdrh ** Rig sqliteMalloc() to fail on the N-th call. Turn of this mechanism 274*daffd0e5Sdrh ** and reset the sqlite_malloc_failed variable is N==0. 275*daffd0e5Sdrh */ 276*daffd0e5Sdrh #ifdef MEMORY_DEBUG 277*daffd0e5Sdrh static int sqlite_malloc_fail( 278*daffd0e5Sdrh void *NotUsed, 279*daffd0e5Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 280*daffd0e5Sdrh int argc, /* Number of arguments */ 281*daffd0e5Sdrh char **argv /* Text of each argument */ 282*daffd0e5Sdrh ){ 283*daffd0e5Sdrh int n; 284*daffd0e5Sdrh if( argc!=2 ){ 285*daffd0e5Sdrh Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0); 286*daffd0e5Sdrh return TCL_ERROR; 287*daffd0e5Sdrh } 288*daffd0e5Sdrh if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; 289*daffd0e5Sdrh sqlite_iMallocFail = n; 290*daffd0e5Sdrh sqlite_malloc_failed = 0; 291*daffd0e5Sdrh return TCL_OK; 292*daffd0e5Sdrh } 293*daffd0e5Sdrh #endif 294*daffd0e5Sdrh 295*daffd0e5Sdrh /* 296*daffd0e5Sdrh ** Usage: sqlite_malloc_stat 297*daffd0e5Sdrh ** 298*daffd0e5Sdrh ** Return the number of prior calls to sqliteMalloc() and sqliteFree(). 299*daffd0e5Sdrh */ 300*daffd0e5Sdrh #ifdef MEMORY_DEBUG 301*daffd0e5Sdrh static int sqlite_malloc_stat( 302*daffd0e5Sdrh void *NotUsed, 303*daffd0e5Sdrh Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 304*daffd0e5Sdrh int argc, /* Number of arguments */ 305*daffd0e5Sdrh char **argv /* Text of each argument */ 306*daffd0e5Sdrh ){ 307*daffd0e5Sdrh char zBuf[200]; 308*daffd0e5Sdrh sprintf(zBuf, "%d %d %d", sqlite_nMalloc, sqlite_nFree, sqlite_iMallocFail); 309*daffd0e5Sdrh Tcl_AppendResult(interp, zBuf, 0); 310*daffd0e5Sdrh return TCL_OK; 311*daffd0e5Sdrh } 312*daffd0e5Sdrh #endif 313*daffd0e5Sdrh 314*daffd0e5Sdrh /* 315d1bf3512Sdrh ** Register commands with the TCL interpreter. 316d1bf3512Sdrh */ 317d1bf3512Sdrh int Sqlitetest1_Init(Tcl_Interp *interp){ 318d1bf3512Sdrh Tcl_CreateCommand(interp, "sqlite_mprintf_int", sqlite_mprintf_int, 0, 0); 319d1bf3512Sdrh Tcl_CreateCommand(interp, "sqlite_mprintf_str", sqlite_mprintf_str, 0, 0); 320d1bf3512Sdrh Tcl_CreateCommand(interp, "sqlite_mprintf_double", sqlite_mprintf_double,0,0); 321d1bf3512Sdrh Tcl_CreateCommand(interp, "sqlite_open", sqlite_test_open, 0, 0); 322d1bf3512Sdrh Tcl_CreateCommand(interp, "sqlite_exec_printf", test_exec_printf, 0, 0); 323d1bf3512Sdrh Tcl_CreateCommand(interp, "sqlite_get_table_printf", test_get_table_printf, 324d1bf3512Sdrh 0, 0); 325d1bf3512Sdrh Tcl_CreateCommand(interp, "sqlite_close", sqlite_test_close, 0, 0); 326*daffd0e5Sdrh #ifdef MEMORY_DEBUG 327*daffd0e5Sdrh Tcl_CreateCommand(interp, "sqlite_malloc_fail", sqlite_malloc_fail, 0, 0); 328*daffd0e5Sdrh Tcl_CreateCommand(interp, "sqlite_malloc_stat", sqlite_malloc_stat, 0, 0); 329*daffd0e5Sdrh #endif 330d1bf3512Sdrh return TCL_OK; 331d1bf3512Sdrh } 332