1 2 #pragma ident "%Z%%M% %I% %E% SMI" 3 4 /* 5 ** 2001 September 15 6 ** 7 ** The author disclaims copyright to this source code. In place of 8 ** a legal notice, here is a blessing: 9 ** 10 ** May you do good and not evil. 11 ** May you find forgiveness for yourself and forgive others. 12 ** May you share freely, never taking more than you give. 13 ** 14 ************************************************************************* 15 ** Code for testing the printf() interface to SQLite. This code 16 ** is not included in the SQLite library. It is used for automated 17 ** testing of the SQLite library. 18 ** 19 ** $Id: test1.c,v 1.36.2.1 2004/05/07 00:57:06 drh Exp $ 20 */ 21 #include "sqliteInt.h" 22 #include "tcl.h" 23 #include "os.h" 24 #include <stdlib.h> 25 #include <string.h> 26 27 #if OS_WIN 28 # define PTR_FMT "%x" 29 #else 30 # define PTR_FMT "%p" 31 #endif 32 33 /* 34 ** Decode a pointer to an sqlite object. 35 */ 36 static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite **ppDb){ 37 if( sscanf(zA, PTR_FMT, (void**)ppDb)!=1 && 38 (zA[0]!='0' || zA[1]!='x' || sscanf(&zA[2], PTR_FMT, (void**)ppDb)!=1) 39 ){ 40 Tcl_AppendResult(interp, "\"", zA, "\" is not a valid pointer value", 0); 41 return TCL_ERROR; 42 } 43 return TCL_OK; 44 } 45 46 /* 47 ** Decode a pointer to an sqlite_vm object. 48 */ 49 static int getVmPointer(Tcl_Interp *interp, const char *zArg, sqlite_vm **ppVm){ 50 if( sscanf(zArg, PTR_FMT, (void**)ppVm)!=1 ){ 51 Tcl_AppendResult(interp, "\"", zArg, "\" is not a valid pointer value", 0); 52 return TCL_ERROR; 53 } 54 return TCL_OK; 55 } 56 57 /* 58 ** Generate a text representation of a pointer that can be understood 59 ** by the getDbPointer and getVmPointer routines above. 60 ** 61 ** The problem is, on some machines (Solaris) if you do a printf with 62 ** "%p" you cannot turn around and do a scanf with the same "%p" and 63 ** get your pointer back. You have to prepend a "0x" before it will 64 ** work. Or at least that is what is reported to me (drh). But this 65 ** behavior varies from machine to machine. The solution used her is 66 ** to test the string right after it is generated to see if it can be 67 ** understood by scanf, and if not, try prepending an "0x" to see if 68 ** that helps. If nothing works, a fatal error is generated. 69 */ 70 static int makePointerStr(Tcl_Interp *interp, char *zPtr, void *p){ 71 void *p2; 72 sprintf(zPtr, PTR_FMT, p); 73 if( sscanf(zPtr, PTR_FMT, &p2)!=1 || p2!=p ){ 74 sprintf(zPtr, "0x" PTR_FMT, p); 75 if( sscanf(zPtr, PTR_FMT, &p2)!=1 || p2!=p ){ 76 Tcl_AppendResult(interp, "unable to convert a pointer to a string " 77 "in the file " __FILE__ " in function makePointerStr(). Please " 78 "report this problem to the SQLite mailing list or as a new but " 79 "report. Please provide detailed information about how you compiled " 80 "SQLite and what computer you are running on.", 0); 81 return TCL_ERROR; 82 } 83 } 84 return TCL_OK; 85 } 86 87 /* 88 ** Usage: sqlite_open filename 89 ** 90 ** Returns: The name of an open database. 91 */ 92 static int sqlite_test_open( 93 void *NotUsed, 94 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 95 int argc, /* Number of arguments */ 96 char **argv /* Text of each argument */ 97 ){ 98 sqlite *db; 99 char *zErr = 0; 100 char zBuf[100]; 101 if( argc!=2 ){ 102 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 103 " FILENAME\"", 0); 104 return TCL_ERROR; 105 } 106 db = sqlite_open(argv[1], 0666, &zErr); 107 if( db==0 ){ 108 Tcl_AppendResult(interp, zErr, 0); 109 free(zErr); 110 return TCL_ERROR; 111 } 112 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; 113 Tcl_AppendResult(interp, zBuf, 0); 114 return TCL_OK; 115 } 116 117 /* 118 ** The callback routine for sqlite_exec_printf(). 119 */ 120 static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){ 121 Tcl_DString *str = (Tcl_DString*)pArg; 122 int i; 123 124 if( Tcl_DStringLength(str)==0 ){ 125 for(i=0; i<argc; i++){ 126 Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL"); 127 } 128 } 129 for(i=0; i<argc; i++){ 130 Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL"); 131 } 132 return 0; 133 } 134 135 /* 136 ** Usage: sqlite_exec_printf DB FORMAT STRING 137 ** 138 ** Invoke the sqlite_exec_printf() interface using the open database 139 ** DB. The SQL is the string FORMAT. The format string should contain 140 ** one %s or %q. STRING is the value inserted into %s or %q. 141 */ 142 static int test_exec_printf( 143 void *NotUsed, 144 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 145 int argc, /* Number of arguments */ 146 char **argv /* Text of each argument */ 147 ){ 148 sqlite *db; 149 Tcl_DString str; 150 int rc; 151 char *zErr = 0; 152 char zBuf[30]; 153 if( argc!=4 ){ 154 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 155 " DB FORMAT STRING", 0); 156 return TCL_ERROR; 157 } 158 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 159 Tcl_DStringInit(&str); 160 rc = sqlite_exec_printf(db, argv[2], exec_printf_cb, &str, &zErr, argv[3]); 161 sprintf(zBuf, "%d", rc); 162 Tcl_AppendElement(interp, zBuf); 163 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); 164 Tcl_DStringFree(&str); 165 if( zErr ) free(zErr); 166 return TCL_OK; 167 } 168 169 /* 170 ** Usage: sqlite_mprintf_z_test SEPARATOR ARG0 ARG1 ... 171 ** 172 ** Test the %z format of mprintf(). Use multiple mprintf() calls to 173 ** concatenate arg0 through argn using separator as the separator. 174 ** Return the result. 175 */ 176 static int test_mprintf_z( 177 void *NotUsed, 178 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 179 int argc, /* Number of arguments */ 180 char **argv /* Text of each argument */ 181 ){ 182 char *zResult = 0; 183 int i; 184 185 for(i=2; i<argc; i++){ 186 zResult = sqliteMPrintf("%z%s%s", zResult, argv[1], argv[i]); 187 } 188 Tcl_AppendResult(interp, zResult, 0); 189 sqliteFree(zResult); 190 return TCL_OK; 191 } 192 193 /* 194 ** Usage: sqlite_get_table_printf DB FORMAT STRING 195 ** 196 ** Invoke the sqlite_get_table_printf() interface using the open database 197 ** DB. The SQL is the string FORMAT. The format string should contain 198 ** one %s or %q. STRING is the value inserted into %s or %q. 199 */ 200 static int test_get_table_printf( 201 void *NotUsed, 202 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 203 int argc, /* Number of arguments */ 204 char **argv /* Text of each argument */ 205 ){ 206 sqlite *db; 207 Tcl_DString str; 208 int rc; 209 char *zErr = 0; 210 int nRow, nCol; 211 char **aResult; 212 int i; 213 char zBuf[30]; 214 if( argc!=4 ){ 215 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 216 " DB FORMAT STRING", 0); 217 return TCL_ERROR; 218 } 219 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 220 Tcl_DStringInit(&str); 221 rc = sqlite_get_table_printf(db, argv[2], &aResult, &nRow, &nCol, 222 &zErr, argv[3]); 223 sprintf(zBuf, "%d", rc); 224 Tcl_AppendElement(interp, zBuf); 225 if( rc==SQLITE_OK ){ 226 sprintf(zBuf, "%d", nRow); 227 Tcl_AppendElement(interp, zBuf); 228 sprintf(zBuf, "%d", nCol); 229 Tcl_AppendElement(interp, zBuf); 230 for(i=0; i<(nRow+1)*nCol; i++){ 231 Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL"); 232 } 233 }else{ 234 Tcl_AppendElement(interp, zErr); 235 } 236 sqlite_free_table(aResult); 237 if( zErr ) free(zErr); 238 return TCL_OK; 239 } 240 241 242 /* 243 ** Usage: sqlite_last_insert_rowid DB 244 ** 245 ** Returns the integer ROWID of the most recent insert. 246 */ 247 static int test_last_rowid( 248 void *NotUsed, 249 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 250 int argc, /* Number of arguments */ 251 char **argv /* Text of each argument */ 252 ){ 253 sqlite *db; 254 char zBuf[30]; 255 256 if( argc!=2 ){ 257 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0); 258 return TCL_ERROR; 259 } 260 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 261 sprintf(zBuf, "%d", sqlite_last_insert_rowid(db)); 262 Tcl_AppendResult(interp, zBuf, 0); 263 return SQLITE_OK; 264 } 265 266 /* 267 ** Usage: sqlite_close DB 268 ** 269 ** Closes the database opened by sqlite_open. 270 */ 271 static int sqlite_test_close( 272 void *NotUsed, 273 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 274 int argc, /* Number of arguments */ 275 char **argv /* Text of each argument */ 276 ){ 277 sqlite *db; 278 if( argc!=2 ){ 279 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 280 " FILENAME\"", 0); 281 return TCL_ERROR; 282 } 283 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 284 sqlite_close(db); 285 return TCL_OK; 286 } 287 288 /* 289 ** Implementation of the x_coalesce() function. 290 ** Return the first argument non-NULL argument. 291 */ 292 static void ifnullFunc(sqlite_func *context, int argc, const char **argv){ 293 int i; 294 for(i=0; i<argc; i++){ 295 if( argv[i] ){ 296 sqlite_set_result_string(context, argv[i], -1); 297 break; 298 } 299 } 300 } 301 302 /* 303 ** A structure into which to accumulate text. 304 */ 305 struct dstr { 306 int nAlloc; /* Space allocated */ 307 int nUsed; /* Space used */ 308 char *z; /* The space */ 309 }; 310 311 /* 312 ** Append text to a dstr 313 */ 314 static void dstrAppend(struct dstr *p, const char *z, int divider){ 315 int n = strlen(z); 316 if( p->nUsed + n + 2 > p->nAlloc ){ 317 char *zNew; 318 p->nAlloc = p->nAlloc*2 + n + 200; 319 zNew = sqliteRealloc(p->z, p->nAlloc); 320 if( zNew==0 ){ 321 sqliteFree(p->z); 322 memset(p, 0, sizeof(*p)); 323 return; 324 } 325 p->z = zNew; 326 } 327 if( divider && p->nUsed>0 ){ 328 p->z[p->nUsed++] = divider; 329 } 330 memcpy(&p->z[p->nUsed], z, n+1); 331 p->nUsed += n; 332 } 333 334 /* 335 ** Invoked for each callback from sqliteExecFunc 336 */ 337 static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){ 338 struct dstr *p = (struct dstr*)pData; 339 int i; 340 for(i=0; i<argc; i++){ 341 if( argv[i]==0 ){ 342 dstrAppend(p, "NULL", ' '); 343 }else{ 344 dstrAppend(p, argv[i], ' '); 345 } 346 } 347 return 0; 348 } 349 350 /* 351 ** Implementation of the x_sqlite_exec() function. This function takes 352 ** a single argument and attempts to execute that argument as SQL code. 353 ** This is illegal and should set the SQLITE_MISUSE flag on the database. 354 ** 355 ** 2004-Jan-07: We have changed this to make it legal to call sqlite_exec() 356 ** from within a function call. 357 ** 358 ** This routine simulates the effect of having two threads attempt to 359 ** use the same database at the same time. 360 */ 361 static void sqliteExecFunc(sqlite_func *context, int argc, const char **argv){ 362 struct dstr x; 363 memset(&x, 0, sizeof(x)); 364 sqlite_exec((sqlite*)sqlite_user_data(context), argv[0], 365 execFuncCallback, &x, 0); 366 sqlite_set_result_string(context, x.z, x.nUsed); 367 sqliteFree(x.z); 368 } 369 370 /* 371 ** Usage: sqlite_test_create_function DB 372 ** 373 ** Call the sqlite_create_function API on the given database in order 374 ** to create a function named "x_coalesce". This function does the same thing 375 ** as the "coalesce" function. This function also registers an SQL function 376 ** named "x_sqlite_exec" that invokes sqlite_exec(). Invoking sqlite_exec() 377 ** in this way is illegal recursion and should raise an SQLITE_MISUSE error. 378 ** The effect is similar to trying to use the same database connection from 379 ** two threads at the same time. 380 ** 381 ** The original motivation for this routine was to be able to call the 382 ** sqlite_create_function function while a query is in progress in order 383 ** to test the SQLITE_MISUSE detection logic. 384 */ 385 static int test_create_function( 386 void *NotUsed, 387 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 388 int argc, /* Number of arguments */ 389 char **argv /* Text of each argument */ 390 ){ 391 sqlite *db; 392 extern void Md5_Register(sqlite*); 393 if( argc!=2 ){ 394 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 395 " FILENAME\"", 0); 396 return TCL_ERROR; 397 } 398 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 399 sqlite_create_function(db, "x_coalesce", -1, ifnullFunc, 0); 400 sqlite_create_function(db, "x_sqlite_exec", 1, sqliteExecFunc, db); 401 return TCL_OK; 402 } 403 404 /* 405 ** Routines to implement the x_count() aggregate function. 406 */ 407 typedef struct CountCtx CountCtx; 408 struct CountCtx { 409 int n; 410 }; 411 static void countStep(sqlite_func *context, int argc, const char **argv){ 412 CountCtx *p; 413 p = sqlite_aggregate_context(context, sizeof(*p)); 414 if( (argc==0 || argv[0]) && p ){ 415 p->n++; 416 } 417 } 418 static void countFinalize(sqlite_func *context){ 419 CountCtx *p; 420 p = sqlite_aggregate_context(context, sizeof(*p)); 421 sqlite_set_result_int(context, p ? p->n : 0); 422 } 423 424 /* 425 ** Usage: sqlite_test_create_aggregate DB 426 ** 427 ** Call the sqlite_create_function API on the given database in order 428 ** to create a function named "x_count". This function does the same thing 429 ** as the "md5sum" function. 430 ** 431 ** The original motivation for this routine was to be able to call the 432 ** sqlite_create_aggregate function while a query is in progress in order 433 ** to test the SQLITE_MISUSE detection logic. 434 */ 435 static int test_create_aggregate( 436 void *NotUsed, 437 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 438 int argc, /* Number of arguments */ 439 char **argv /* Text of each argument */ 440 ){ 441 sqlite *db; 442 if( argc!=2 ){ 443 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 444 " FILENAME\"", 0); 445 return TCL_ERROR; 446 } 447 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 448 sqlite_create_aggregate(db, "x_count", 0, countStep, countFinalize, 0); 449 sqlite_create_aggregate(db, "x_count", 1, countStep, countFinalize, 0); 450 return TCL_OK; 451 } 452 453 454 455 /* 456 ** Usage: sqlite_mprintf_int FORMAT INTEGER INTEGER INTEGER 457 ** 458 ** Call mprintf with three integer arguments 459 */ 460 static int sqlite_mprintf_int( 461 void *NotUsed, 462 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 463 int argc, /* Number of arguments */ 464 char **argv /* Text of each argument */ 465 ){ 466 int a[3], i; 467 char *z; 468 if( argc!=5 ){ 469 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 470 " FORMAT INT INT INT\"", 0); 471 return TCL_ERROR; 472 } 473 for(i=2; i<5; i++){ 474 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 475 } 476 z = sqlite_mprintf(argv[1], a[0], a[1], a[2]); 477 Tcl_AppendResult(interp, z, 0); 478 sqlite_freemem(z); 479 return TCL_OK; 480 } 481 482 /* 483 ** Usage: sqlite_mprintf_str FORMAT INTEGER INTEGER STRING 484 ** 485 ** Call mprintf with two integer arguments and one string argument 486 */ 487 static int sqlite_mprintf_str( 488 void *NotUsed, 489 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 490 int argc, /* Number of arguments */ 491 char **argv /* Text of each argument */ 492 ){ 493 int a[3], i; 494 char *z; 495 if( argc<4 || argc>5 ){ 496 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 497 " FORMAT INT INT ?STRING?\"", 0); 498 return TCL_ERROR; 499 } 500 for(i=2; i<4; i++){ 501 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 502 } 503 z = sqlite_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL); 504 Tcl_AppendResult(interp, z, 0); 505 sqlite_freemem(z); 506 return TCL_OK; 507 } 508 509 /* 510 ** Usage: sqlite_mprintf_str FORMAT INTEGER INTEGER DOUBLE 511 ** 512 ** Call mprintf with two integer arguments and one double argument 513 */ 514 static int sqlite_mprintf_double( 515 void *NotUsed, 516 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 517 int argc, /* Number of arguments */ 518 char **argv /* Text of each argument */ 519 ){ 520 int a[3], i; 521 double r; 522 char *z; 523 if( argc!=5 ){ 524 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 525 " FORMAT INT INT STRING\"", 0); 526 return TCL_ERROR; 527 } 528 for(i=2; i<4; i++){ 529 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 530 } 531 if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR; 532 z = sqlite_mprintf(argv[1], a[0], a[1], r); 533 Tcl_AppendResult(interp, z, 0); 534 sqlite_freemem(z); 535 return TCL_OK; 536 } 537 538 /* 539 ** Usage: sqlite_mprintf_str FORMAT DOUBLE DOUBLE 540 ** 541 ** Call mprintf with a single double argument which is the product of the 542 ** two arguments given above. This is used to generate overflow and underflow 543 ** doubles to test that they are converted properly. 544 */ 545 static int sqlite_mprintf_scaled( 546 void *NotUsed, 547 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 548 int argc, /* Number of arguments */ 549 char **argv /* Text of each argument */ 550 ){ 551 int i; 552 double r[2]; 553 char *z; 554 if( argc!=4 ){ 555 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 556 " FORMAT DOUBLE DOUBLE\"", 0); 557 return TCL_ERROR; 558 } 559 for(i=2; i<4; i++){ 560 if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR; 561 } 562 z = sqlite_mprintf(argv[1], r[0]*r[1]); 563 Tcl_AppendResult(interp, z, 0); 564 sqlite_freemem(z); 565 return TCL_OK; 566 } 567 568 /* 569 ** Usage: sqlite_malloc_fail N 570 ** 571 ** Rig sqliteMalloc() to fail on the N-th call. Turn off this mechanism 572 ** and reset the sqlite_malloc_failed variable is N==0. 573 */ 574 #ifdef MEMORY_DEBUG 575 static int sqlite_malloc_fail( 576 void *NotUsed, 577 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 578 int argc, /* Number of arguments */ 579 char **argv /* Text of each argument */ 580 ){ 581 int n; 582 if( argc!=2 ){ 583 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0); 584 return TCL_ERROR; 585 } 586 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; 587 sqlite_iMallocFail = n; 588 sqlite_malloc_failed = 0; 589 return TCL_OK; 590 } 591 #endif 592 593 /* 594 ** Usage: sqlite_malloc_stat 595 ** 596 ** Return the number of prior calls to sqliteMalloc() and sqliteFree(). 597 */ 598 #ifdef MEMORY_DEBUG 599 static int sqlite_malloc_stat( 600 void *NotUsed, 601 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 602 int argc, /* Number of arguments */ 603 char **argv /* Text of each argument */ 604 ){ 605 char zBuf[200]; 606 sprintf(zBuf, "%d %d %d", sqlite_nMalloc, sqlite_nFree, sqlite_iMallocFail); 607 Tcl_AppendResult(interp, zBuf, 0); 608 return TCL_OK; 609 } 610 #endif 611 612 /* 613 ** Usage: sqlite_abort 614 ** 615 ** Shutdown the process immediately. This is not a clean shutdown. 616 ** This command is used to test the recoverability of a database in 617 ** the event of a program crash. 618 */ 619 static int sqlite_abort( 620 void *NotUsed, 621 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 622 int argc, /* Number of arguments */ 623 char **argv /* Text of each argument */ 624 ){ 625 assert( interp==0 ); /* This will always fail */ 626 return TCL_OK; 627 } 628 629 /* 630 ** The following routine is a user-defined SQL function whose purpose 631 ** is to test the sqlite_set_result() API. 632 */ 633 static void testFunc(sqlite_func *context, int argc, const char **argv){ 634 while( argc>=2 ){ 635 if( argv[0]==0 ){ 636 sqlite_set_result_error(context, "first argument to test function " 637 "may not be NULL", -1); 638 }else if( sqliteStrICmp(argv[0],"string")==0 ){ 639 sqlite_set_result_string(context, argv[1], -1); 640 }else if( argv[1]==0 ){ 641 sqlite_set_result_error(context, "2nd argument may not be NULL if the " 642 "first argument is not \"string\"", -1); 643 }else if( sqliteStrICmp(argv[0],"int")==0 ){ 644 sqlite_set_result_int(context, atoi(argv[1])); 645 }else if( sqliteStrICmp(argv[0],"double")==0 ){ 646 sqlite_set_result_double(context, sqliteAtoF(argv[1], 0)); 647 }else{ 648 sqlite_set_result_error(context,"first argument should be one of: " 649 "string int double", -1); 650 } 651 argc -= 2; 652 argv += 2; 653 } 654 } 655 656 /* 657 ** Usage: sqlite_register_test_function DB NAME 658 ** 659 ** Register the test SQL function on the database DB under the name NAME. 660 */ 661 static int test_register_func( 662 void *NotUsed, 663 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 664 int argc, /* Number of arguments */ 665 char **argv /* Text of each argument */ 666 ){ 667 sqlite *db; 668 int rc; 669 if( argc!=3 ){ 670 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 671 " DB FUNCTION-NAME", 0); 672 return TCL_ERROR; 673 } 674 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 675 rc = sqlite_create_function(db, argv[2], -1, testFunc, 0); 676 if( rc!=0 ){ 677 Tcl_AppendResult(interp, sqlite_error_string(rc), 0); 678 return TCL_ERROR; 679 } 680 return TCL_OK; 681 } 682 683 /* 684 ** This SQLite callback records the datatype of all columns. 685 ** 686 ** The pArg argument is really a pointer to a TCL interpreter. The 687 ** column names are inserted as the result of this interpreter. 688 ** 689 ** This routine returns non-zero which causes the query to abort. 690 */ 691 static int rememberDataTypes(void *pArg, int nCol, char **argv, char **colv){ 692 int i; 693 Tcl_Interp *interp = (Tcl_Interp*)pArg; 694 Tcl_Obj *pList, *pElem; 695 if( colv[nCol+1]==0 ){ 696 return 1; 697 } 698 pList = Tcl_NewObj(); 699 for(i=0; i<nCol; i++){ 700 pElem = Tcl_NewStringObj(colv[i+nCol] ? colv[i+nCol] : "NULL", -1); 701 Tcl_ListObjAppendElement(interp, pList, pElem); 702 } 703 Tcl_SetObjResult(interp, pList); 704 return 1; 705 } 706 707 /* 708 ** Invoke an SQL statement but ignore all the data in the result. Instead, 709 ** return a list that consists of the datatypes of the various columns. 710 ** 711 ** This only works if "PRAGMA show_datatypes=on" has been executed against 712 ** the database connection. 713 */ 714 static int sqlite_datatypes( 715 void *NotUsed, 716 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 717 int argc, /* Number of arguments */ 718 char **argv /* Text of each argument */ 719 ){ 720 sqlite *db; 721 int rc; 722 if( argc!=3 ){ 723 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 724 " DB SQL", 0); 725 return TCL_ERROR; 726 } 727 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 728 rc = sqlite_exec(db, argv[2], rememberDataTypes, interp, 0); 729 if( rc!=0 && rc!=SQLITE_ABORT ){ 730 Tcl_AppendResult(interp, sqlite_error_string(rc), 0); 731 return TCL_ERROR; 732 } 733 return TCL_OK; 734 } 735 736 /* 737 ** Usage: sqlite_compile DB SQL ?TAILVAR? 738 ** 739 ** Attempt to compile an SQL statement. Return a pointer to the virtual 740 ** machine used to execute that statement. Unprocessed SQL is written 741 ** into TAILVAR. 742 */ 743 static int test_compile( 744 void *NotUsed, 745 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 746 int argc, /* Number of arguments */ 747 char **argv /* Text of each argument */ 748 ){ 749 sqlite *db; 750 sqlite_vm *vm; 751 int rc; 752 char *zErr = 0; 753 const char *zTail; 754 char zBuf[50]; 755 if( argc!=3 && argc!=4 ){ 756 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 757 " DB SQL TAILVAR", 0); 758 return TCL_ERROR; 759 } 760 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 761 rc = sqlite_compile(db, argv[2], argc==4 ? &zTail : 0, &vm, &zErr); 762 if( argc==4 ) Tcl_SetVar(interp, argv[3], zTail, 0); 763 if( rc ){ 764 assert( vm==0 ); 765 sprintf(zBuf, "(%d) ", rc); 766 Tcl_AppendResult(interp, zBuf, zErr, 0); 767 sqlite_freemem(zErr); 768 return TCL_ERROR; 769 } 770 if( vm ){ 771 if( makePointerStr(interp, zBuf, vm) ) return TCL_ERROR; 772 Tcl_AppendResult(interp, zBuf, 0); 773 } 774 return TCL_OK; 775 } 776 777 /* 778 ** Usage: sqlite_step VM ?NVAR? ?VALUEVAR? ?COLNAMEVAR? 779 ** 780 ** Step a virtual machine. Return a the result code as a string. 781 ** Column results are written into three variables. 782 */ 783 static int test_step( 784 void *NotUsed, 785 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 786 int argc, /* Number of arguments */ 787 char **argv /* Text of each argument */ 788 ){ 789 sqlite_vm *vm; 790 int rc, i; 791 const char **azValue = 0; 792 const char **azColName = 0; 793 int N = 0; 794 char *zRc; 795 char zBuf[50]; 796 if( argc<2 || argc>5 ){ 797 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 798 " VM NVAR VALUEVAR COLNAMEVAR", 0); 799 return TCL_ERROR; 800 } 801 if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR; 802 rc = sqlite_step(vm, argc>=3?&N:0, argc>=4?&azValue:0, argc==5?&azColName:0); 803 if( argc>=3 ){ 804 sprintf(zBuf, "%d", N); 805 Tcl_SetVar(interp, argv[2], zBuf, 0); 806 } 807 if( argc>=4 ){ 808 Tcl_SetVar(interp, argv[3], "", 0); 809 if( azValue ){ 810 for(i=0; i<N; i++){ 811 Tcl_SetVar(interp, argv[3], azValue[i] ? azValue[i] : "", 812 TCL_APPEND_VALUE | TCL_LIST_ELEMENT); 813 } 814 } 815 } 816 if( argc==5 ){ 817 Tcl_SetVar(interp, argv[4], "", 0); 818 if( azColName ){ 819 for(i=0; i<N*2; i++){ 820 Tcl_SetVar(interp, argv[4], azColName[i] ? azColName[i] : "", 821 TCL_APPEND_VALUE | TCL_LIST_ELEMENT); 822 } 823 } 824 } 825 switch( rc ){ 826 case SQLITE_DONE: zRc = "SQLITE_DONE"; break; 827 case SQLITE_BUSY: zRc = "SQLITE_BUSY"; break; 828 case SQLITE_ROW: zRc = "SQLITE_ROW"; break; 829 case SQLITE_ERROR: zRc = "SQLITE_ERROR"; break; 830 case SQLITE_MISUSE: zRc = "SQLITE_MISUSE"; break; 831 default: zRc = "unknown"; break; 832 } 833 Tcl_AppendResult(interp, zRc, 0); 834 return TCL_OK; 835 } 836 837 /* 838 ** Usage: sqlite_finalize VM 839 ** 840 ** Shutdown a virtual machine. 841 */ 842 static int test_finalize( 843 void *NotUsed, 844 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 845 int argc, /* Number of arguments */ 846 char **argv /* Text of each argument */ 847 ){ 848 sqlite_vm *vm; 849 int rc; 850 char *zErrMsg = 0; 851 if( argc!=2 ){ 852 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 853 " VM\"", 0); 854 return TCL_ERROR; 855 } 856 if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR; 857 rc = sqlite_finalize(vm, &zErrMsg); 858 if( rc ){ 859 char zBuf[50]; 860 sprintf(zBuf, "(%d) ", rc); 861 Tcl_AppendResult(interp, zBuf, zErrMsg, 0); 862 sqlite_freemem(zErrMsg); 863 return TCL_ERROR; 864 } 865 return TCL_OK; 866 } 867 868 /* 869 ** Usage: sqlite_reset VM 870 ** 871 ** Reset a virtual machine and prepare it to be run again. 872 */ 873 static int test_reset( 874 void *NotUsed, 875 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 876 int argc, /* Number of arguments */ 877 char **argv /* Text of each argument */ 878 ){ 879 sqlite_vm *vm; 880 int rc; 881 char *zErrMsg = 0; 882 if( argc!=2 ){ 883 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 884 " VM\"", 0); 885 return TCL_ERROR; 886 } 887 if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR; 888 rc = sqlite_reset(vm, &zErrMsg); 889 if( rc ){ 890 char zBuf[50]; 891 sprintf(zBuf, "(%d) ", rc); 892 Tcl_AppendResult(interp, zBuf, zErrMsg, 0); 893 sqlite_freemem(zErrMsg); 894 return TCL_ERROR; 895 } 896 return TCL_OK; 897 } 898 899 /* 900 ** This is the "static_bind_value" that variables are bound to when 901 ** the FLAG option of sqlite_bind is "static" 902 */ 903 static char *sqlite_static_bind_value = 0; 904 905 /* 906 ** Usage: sqlite_bind VM IDX VALUE FLAGS 907 ** 908 ** Sets the value of the IDX-th occurance of "?" in the original SQL 909 ** string. VALUE is the new value. If FLAGS=="null" then VALUE is 910 ** ignored and the value is set to NULL. If FLAGS=="static" then 911 ** the value is set to the value of a static variable named 912 ** "sqlite_static_bind_value". If FLAGS=="normal" then a copy 913 ** of the VALUE is made. 914 */ 915 static int test_bind( 916 void *NotUsed, 917 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 918 int argc, /* Number of arguments */ 919 char **argv /* Text of each argument */ 920 ){ 921 sqlite_vm *vm; 922 int rc; 923 int idx; 924 if( argc!=5 ){ 925 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 926 " VM IDX VALUE (null|static|normal)\"", 0); 927 return TCL_ERROR; 928 } 929 if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR; 930 if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR; 931 if( strcmp(argv[4],"null")==0 ){ 932 rc = sqlite_bind(vm, idx, 0, 0, 0); 933 }else if( strcmp(argv[4],"static")==0 ){ 934 rc = sqlite_bind(vm, idx, sqlite_static_bind_value, -1, 0); 935 }else if( strcmp(argv[4],"normal")==0 ){ 936 rc = sqlite_bind(vm, idx, argv[3], -1, 1); 937 }else{ 938 Tcl_AppendResult(interp, "4th argument should be " 939 "\"null\" or \"static\" or \"normal\"", 0); 940 return TCL_ERROR; 941 } 942 if( rc ){ 943 char zBuf[50]; 944 sprintf(zBuf, "(%d) ", rc); 945 Tcl_AppendResult(interp, zBuf, sqlite_error_string(rc), 0); 946 return TCL_ERROR; 947 } 948 return TCL_OK; 949 } 950 951 /* 952 ** Usage: breakpoint 953 ** 954 ** This routine exists for one purpose - to provide a place to put a 955 ** breakpoint with GDB that can be triggered using TCL code. The use 956 ** for this is when a particular test fails on (say) the 1485th iteration. 957 ** In the TCL test script, we can add code like this: 958 ** 959 ** if {$i==1485} breakpoint 960 ** 961 ** Then run testfixture in the debugger and wait for the breakpoint to 962 ** fire. Then additional breakpoints can be set to trace down the bug. 963 */ 964 static int test_breakpoint( 965 void *NotUsed, 966 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 967 int argc, /* Number of arguments */ 968 char **argv /* Text of each argument */ 969 ){ 970 return TCL_OK; /* Do nothing */ 971 } 972 973 /* 974 ** Register commands with the TCL interpreter. 975 */ 976 int Sqlitetest1_Init(Tcl_Interp *interp){ 977 extern int sqlite_search_count; 978 extern int sqlite_interrupt_count; 979 extern int sqlite_open_file_count; 980 extern int sqlite_current_time; 981 extern int sqlite_temp_directory; 982 static struct { 983 char *zName; 984 Tcl_CmdProc *xProc; 985 } aCmd[] = { 986 { "sqlite_mprintf_int", (Tcl_CmdProc*)sqlite_mprintf_int }, 987 { "sqlite_mprintf_str", (Tcl_CmdProc*)sqlite_mprintf_str }, 988 { "sqlite_mprintf_double", (Tcl_CmdProc*)sqlite_mprintf_double }, 989 { "sqlite_mprintf_scaled", (Tcl_CmdProc*)sqlite_mprintf_scaled }, 990 { "sqlite_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z }, 991 { "sqlite_open", (Tcl_CmdProc*)sqlite_test_open }, 992 { "sqlite_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid }, 993 { "sqlite_exec_printf", (Tcl_CmdProc*)test_exec_printf }, 994 { "sqlite_get_table_printf", (Tcl_CmdProc*)test_get_table_printf }, 995 { "sqlite_close", (Tcl_CmdProc*)sqlite_test_close }, 996 { "sqlite_create_function", (Tcl_CmdProc*)test_create_function }, 997 { "sqlite_create_aggregate", (Tcl_CmdProc*)test_create_aggregate }, 998 { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, 999 { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, 1000 { "sqlite_datatypes", (Tcl_CmdProc*)sqlite_datatypes }, 1001 #ifdef MEMORY_DEBUG 1002 { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail }, 1003 { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat }, 1004 #endif 1005 { "sqlite_compile", (Tcl_CmdProc*)test_compile }, 1006 { "sqlite_step", (Tcl_CmdProc*)test_step }, 1007 { "sqlite_finalize", (Tcl_CmdProc*)test_finalize }, 1008 { "sqlite_bind", (Tcl_CmdProc*)test_bind }, 1009 { "sqlite_reset", (Tcl_CmdProc*)test_reset }, 1010 { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, 1011 }; 1012 int i; 1013 1014 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ 1015 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); 1016 } 1017 Tcl_LinkVar(interp, "sqlite_search_count", 1018 (char*)&sqlite_search_count, TCL_LINK_INT); 1019 Tcl_LinkVar(interp, "sqlite_interrupt_count", 1020 (char*)&sqlite_interrupt_count, TCL_LINK_INT); 1021 Tcl_LinkVar(interp, "sqlite_open_file_count", 1022 (char*)&sqlite_open_file_count, TCL_LINK_INT); 1023 Tcl_LinkVar(interp, "sqlite_current_time", 1024 (char*)&sqlite_current_time, TCL_LINK_INT); 1025 Tcl_LinkVar(interp, "sqlite_static_bind_value", 1026 (char*)&sqlite_static_bind_value, TCL_LINK_STRING); 1027 Tcl_LinkVar(interp, "sqlite_temp_directory", 1028 (char*)&sqlite_temp_directory, TCL_LINK_STRING); 1029 return TCL_OK; 1030 } 1031