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