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 all sorts of SQLite interfaces. This code 13 ** is not included in the SQLite library. It is used for automated 14 ** testing of the SQLite library. 15 */ 16 #include "sqliteInt.h" 17 #if SQLITE_OS_WIN 18 # include "os_win.h" 19 #endif 20 21 #include "vdbeInt.h" 22 #include "tcl.h" 23 #include <stdlib.h> 24 #include <string.h> 25 26 /* 27 ** This is a copy of the first part of the SqliteDb structure in 28 ** tclsqlite.c. We need it here so that the get_sqlite_pointer routine 29 ** can extract the sqlite3* pointer from an existing Tcl SQLite 30 ** connection. 31 */ 32 struct SqliteDb { 33 sqlite3 *db; 34 }; 35 36 /* 37 ** Convert text generated by the "%p" conversion format back into 38 ** a pointer. 39 */ 40 static int testHexToInt(int h){ 41 if( h>='0' && h<='9' ){ 42 return h - '0'; 43 }else if( h>='a' && h<='f' ){ 44 return h - 'a' + 10; 45 }else{ 46 assert( h>='A' && h<='F' ); 47 return h - 'A' + 10; 48 } 49 } 50 void *sqlite3TestTextToPtr(const char *z){ 51 void *p; 52 u64 v; 53 u32 v2; 54 if( z[0]=='0' && z[1]=='x' ){ 55 z += 2; 56 } 57 v = 0; 58 while( *z ){ 59 v = (v<<4) + testHexToInt(*z); 60 z++; 61 } 62 if( sizeof(p)==sizeof(v) ){ 63 memcpy(&p, &v, sizeof(p)); 64 }else{ 65 assert( sizeof(p)==sizeof(v2) ); 66 v2 = (u32)v; 67 memcpy(&p, &v2, sizeof(p)); 68 } 69 return p; 70 } 71 72 73 /* 74 ** A TCL command that returns the address of the sqlite* pointer 75 ** for an sqlite connection instance. Bad things happen if the 76 ** input is not an sqlite connection. 77 */ 78 static int get_sqlite_pointer( 79 void * clientData, 80 Tcl_Interp *interp, 81 int objc, 82 Tcl_Obj *CONST objv[] 83 ){ 84 struct SqliteDb *p; 85 Tcl_CmdInfo cmdInfo; 86 char zBuf[100]; 87 if( objc!=2 ){ 88 Tcl_WrongNumArgs(interp, 1, objv, "SQLITE-CONNECTION"); 89 return TCL_ERROR; 90 } 91 if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){ 92 Tcl_AppendResult(interp, "command not found: ", 93 Tcl_GetString(objv[1]), (char*)0); 94 return TCL_ERROR; 95 } 96 p = (struct SqliteDb*)cmdInfo.objClientData; 97 sprintf(zBuf, "%p", p->db); 98 if( strncmp(zBuf,"0x",2) ){ 99 sprintf(zBuf, "0x%p", p->db); 100 } 101 Tcl_AppendResult(interp, zBuf, 0); 102 return TCL_OK; 103 } 104 105 /* 106 ** Decode a pointer to an sqlite3 object. 107 */ 108 int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){ 109 struct SqliteDb *p; 110 Tcl_CmdInfo cmdInfo; 111 if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){ 112 p = (struct SqliteDb*)cmdInfo.objClientData; 113 *ppDb = p->db; 114 }else{ 115 *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA); 116 } 117 return TCL_OK; 118 } 119 120 #if SQLITE_OS_WIN 121 /* 122 ** Decode a Win32 HANDLE object. 123 */ 124 int getWin32Handle(Tcl_Interp *interp, const char *zA, LPHANDLE phFile){ 125 *phFile = (HANDLE)sqlite3TestTextToPtr(zA); 126 return TCL_OK; 127 } 128 #endif 129 130 extern const char *sqlite3ErrName(int); 131 #define t1ErrorName sqlite3ErrName 132 133 /* 134 ** Convert an sqlite3_stmt* into an sqlite3*. This depends on the 135 ** fact that the sqlite3* is the first field in the Vdbe structure. 136 */ 137 #define StmtToDb(X) sqlite3_db_handle(X) 138 139 /* 140 ** Check a return value to make sure it agrees with the results 141 ** from sqlite3_errcode. 142 */ 143 int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){ 144 if( sqlite3_threadsafe()==0 && rc!=SQLITE_MISUSE && rc!=SQLITE_OK 145 && sqlite3_errcode(db)!=rc ){ 146 char zBuf[200]; 147 int r2 = sqlite3_errcode(db); 148 sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)", 149 t1ErrorName(rc), rc, t1ErrorName(r2), r2); 150 Tcl_ResetResult(interp); 151 Tcl_AppendResult(interp, zBuf, 0); 152 return 1; 153 } 154 return 0; 155 } 156 157 /* 158 ** Decode a pointer to an sqlite3_stmt object. 159 */ 160 static int getStmtPointer( 161 Tcl_Interp *interp, 162 const char *zArg, 163 sqlite3_stmt **ppStmt 164 ){ 165 *ppStmt = (sqlite3_stmt*)sqlite3TestTextToPtr(zArg); 166 return TCL_OK; 167 } 168 169 /* 170 ** Generate a text representation of a pointer that can be understood 171 ** by the getDbPointer and getVmPointer routines above. 172 ** 173 ** The problem is, on some machines (Solaris) if you do a printf with 174 ** "%p" you cannot turn around and do a scanf with the same "%p" and 175 ** get your pointer back. You have to prepend a "0x" before it will 176 ** work. Or at least that is what is reported to me (drh). But this 177 ** behavior varies from machine to machine. The solution used her is 178 ** to test the string right after it is generated to see if it can be 179 ** understood by scanf, and if not, try prepending an "0x" to see if 180 ** that helps. If nothing works, a fatal error is generated. 181 */ 182 int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p){ 183 sqlite3_snprintf(100, zPtr, "%p", p); 184 return TCL_OK; 185 } 186 187 /* 188 ** The callback routine for sqlite3_exec_printf(). 189 */ 190 static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){ 191 Tcl_DString *str = (Tcl_DString*)pArg; 192 int i; 193 194 if( Tcl_DStringLength(str)==0 ){ 195 for(i=0; i<argc; i++){ 196 Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL"); 197 } 198 } 199 for(i=0; i<argc; i++){ 200 Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL"); 201 } 202 return 0; 203 } 204 205 /* 206 ** The I/O tracing callback. 207 */ 208 #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) 209 static FILE *iotrace_file = 0; 210 static void io_trace_callback(const char *zFormat, ...){ 211 va_list ap; 212 va_start(ap, zFormat); 213 vfprintf(iotrace_file, zFormat, ap); 214 va_end(ap); 215 fflush(iotrace_file); 216 } 217 #endif 218 219 /* 220 ** Usage: io_trace FILENAME 221 ** 222 ** Turn I/O tracing on or off. If FILENAME is not an empty string, 223 ** I/O tracing begins going into FILENAME. If FILENAME is an empty 224 ** string, I/O tracing is turned off. 225 */ 226 static int test_io_trace( 227 void *NotUsed, 228 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 229 int argc, /* Number of arguments */ 230 char **argv /* Text of each argument */ 231 ){ 232 #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) 233 if( argc!=2 ){ 234 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 235 " FILENAME\"", 0); 236 return TCL_ERROR; 237 } 238 if( iotrace_file ){ 239 if( iotrace_file!=stdout && iotrace_file!=stderr ){ 240 fclose(iotrace_file); 241 } 242 iotrace_file = 0; 243 sqlite3IoTrace = 0; 244 } 245 if( argv[1][0] ){ 246 if( strcmp(argv[1],"stdout")==0 ){ 247 iotrace_file = stdout; 248 }else if( strcmp(argv[1],"stderr")==0 ){ 249 iotrace_file = stderr; 250 }else{ 251 iotrace_file = fopen(argv[1], "w"); 252 } 253 sqlite3IoTrace = io_trace_callback; 254 } 255 #endif 256 return TCL_OK; 257 } 258 259 /* 260 ** Usage: clang_sanitize_address 261 ** 262 ** Returns true if the program was compiled using clang with the 263 ** -fsanitize=address switch on the command line. False otherwise. 264 */ 265 static int clang_sanitize_address( 266 void *NotUsed, 267 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 268 int argc, /* Number of arguments */ 269 char **argv /* Text of each argument */ 270 ){ 271 int res = 0; 272 #if defined(__has_feature) 273 # if __has_feature(address_sanitizer) 274 res = 1; 275 # endif 276 #endif 277 Tcl_SetObjResult(interp, Tcl_NewIntObj(res)); 278 return TCL_OK; 279 } 280 281 /* 282 ** Usage: sqlite3_exec_printf DB FORMAT STRING 283 ** 284 ** Invoke the sqlite3_exec_printf() interface using the open database 285 ** DB. The SQL is the string FORMAT. The format string should contain 286 ** one %s or %q. STRING is the value inserted into %s or %q. 287 */ 288 static int test_exec_printf( 289 void *NotUsed, 290 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 291 int argc, /* Number of arguments */ 292 char **argv /* Text of each argument */ 293 ){ 294 sqlite3 *db; 295 Tcl_DString str; 296 int rc; 297 char *zErr = 0; 298 char *zSql; 299 char zBuf[30]; 300 if( argc!=4 ){ 301 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 302 " DB FORMAT STRING", 0); 303 return TCL_ERROR; 304 } 305 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 306 Tcl_DStringInit(&str); 307 zSql = sqlite3_mprintf(argv[2], argv[3]); 308 rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); 309 sqlite3_free(zSql); 310 sprintf(zBuf, "%d", rc); 311 Tcl_AppendElement(interp, zBuf); 312 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); 313 Tcl_DStringFree(&str); 314 if( zErr ) sqlite3_free(zErr); 315 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 316 return TCL_OK; 317 } 318 319 /* 320 ** Usage: sqlite3_exec_hex DB HEX 321 ** 322 ** Invoke the sqlite3_exec() on a string that is obtained by translating 323 ** HEX into ASCII. Most characters are translated as is. %HH becomes 324 ** a hex character. 325 */ 326 static int test_exec_hex( 327 void *NotUsed, 328 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 329 int argc, /* Number of arguments */ 330 char **argv /* Text of each argument */ 331 ){ 332 sqlite3 *db; 333 Tcl_DString str; 334 int rc, i, j; 335 char *zErr = 0; 336 char *zHex; 337 char zSql[500]; 338 char zBuf[30]; 339 if( argc!=3 ){ 340 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 341 " DB HEX", 0); 342 return TCL_ERROR; 343 } 344 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 345 zHex = argv[2]; 346 for(i=j=0; i<sizeof(zSql) && zHex[j]; i++, j++){ 347 if( zHex[j]=='%' && zHex[j+2] && zHex[j+2] ){ 348 zSql[i] = (testHexToInt(zHex[j+1])<<4) + testHexToInt(zHex[j+2]); 349 j += 2; 350 }else{ 351 zSql[i] = zHex[j]; 352 } 353 } 354 zSql[i] = 0; 355 Tcl_DStringInit(&str); 356 rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); 357 sprintf(zBuf, "%d", rc); 358 Tcl_AppendElement(interp, zBuf); 359 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); 360 Tcl_DStringFree(&str); 361 if( zErr ) sqlite3_free(zErr); 362 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 363 return TCL_OK; 364 } 365 366 /* 367 ** Usage: db_enter DB 368 ** db_leave DB 369 ** 370 ** Enter or leave the mutex on a database connection. 371 */ 372 static int db_enter( 373 void *NotUsed, 374 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 375 int argc, /* Number of arguments */ 376 char **argv /* Text of each argument */ 377 ){ 378 sqlite3 *db; 379 if( argc!=2 ){ 380 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 381 " DB", 0); 382 return TCL_ERROR; 383 } 384 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 385 sqlite3_mutex_enter(db->mutex); 386 return TCL_OK; 387 } 388 static int db_leave( 389 void *NotUsed, 390 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 391 int argc, /* Number of arguments */ 392 char **argv /* Text of each argument */ 393 ){ 394 sqlite3 *db; 395 if( argc!=2 ){ 396 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 397 " DB", 0); 398 return TCL_ERROR; 399 } 400 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 401 sqlite3_mutex_leave(db->mutex); 402 return TCL_OK; 403 } 404 405 /* 406 ** Usage: sqlite3_exec DB SQL 407 ** 408 ** Invoke the sqlite3_exec interface using the open database DB 409 */ 410 static int test_exec( 411 void *NotUsed, 412 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 413 int argc, /* Number of arguments */ 414 char **argv /* Text of each argument */ 415 ){ 416 sqlite3 *db; 417 Tcl_DString str; 418 int rc; 419 char *zErr = 0; 420 char *zSql; 421 int i, j; 422 char zBuf[30]; 423 if( argc!=3 ){ 424 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 425 " DB SQL", 0); 426 return TCL_ERROR; 427 } 428 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 429 Tcl_DStringInit(&str); 430 zSql = sqlite3_mprintf("%s", argv[2]); 431 for(i=j=0; zSql[i];){ 432 if( zSql[i]=='%' ){ 433 zSql[j++] = (testHexToInt(zSql[i+1])<<4) + testHexToInt(zSql[i+2]); 434 i += 3; 435 }else{ 436 zSql[j++] = zSql[i++]; 437 } 438 } 439 zSql[j] = 0; 440 rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); 441 sqlite3_free(zSql); 442 sprintf(zBuf, "%d", rc); 443 Tcl_AppendElement(interp, zBuf); 444 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); 445 Tcl_DStringFree(&str); 446 if( zErr ) sqlite3_free(zErr); 447 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 448 return TCL_OK; 449 } 450 451 /* 452 ** Usage: sqlite3_exec_nr DB SQL 453 ** 454 ** Invoke the sqlite3_exec interface using the open database DB. Discard 455 ** all results 456 */ 457 static int test_exec_nr( 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 sqlite3 *db; 464 int rc; 465 char *zErr = 0; 466 if( argc!=3 ){ 467 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 468 " DB SQL", 0); 469 return TCL_ERROR; 470 } 471 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 472 rc = sqlite3_exec(db, argv[2], 0, 0, &zErr); 473 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 474 return TCL_OK; 475 } 476 477 /* 478 ** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ... 479 ** 480 ** Test the %z format of sqlite_mprintf(). Use multiple mprintf() calls to 481 ** concatenate arg0 through argn using separator as the separator. 482 ** Return the result. 483 */ 484 static int test_mprintf_z( 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 char *zResult = 0; 491 int i; 492 493 for(i=2; i<argc && (i==2 || zResult); i++){ 494 zResult = sqlite3_mprintf("%z%s%s", zResult, argv[1], argv[i]); 495 } 496 Tcl_AppendResult(interp, zResult, 0); 497 sqlite3_free(zResult); 498 return TCL_OK; 499 } 500 501 /* 502 ** Usage: sqlite3_mprintf_n_test STRING 503 ** 504 ** Test the %n format of sqlite_mprintf(). Return the length of the 505 ** input string. 506 */ 507 static int test_mprintf_n( 508 void *NotUsed, 509 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 510 int argc, /* Number of arguments */ 511 char **argv /* Text of each argument */ 512 ){ 513 char *zStr; 514 int n = 0; 515 zStr = sqlite3_mprintf("%s%n", argv[1], &n); 516 sqlite3_free(zStr); 517 Tcl_SetObjResult(interp, Tcl_NewIntObj(n)); 518 return TCL_OK; 519 } 520 521 /* 522 ** Usage: sqlite3_snprintf_int SIZE FORMAT INT 523 ** 524 ** Test the of sqlite3_snprintf() routine. SIZE is the size of the 525 ** output buffer in bytes. The maximum size is 100. FORMAT is the 526 ** format string. INT is a single integer argument. The FORMAT 527 ** string must require no more than this one integer argument. If 528 ** You pass in a format string that requires more than one argument, 529 ** bad things will happen. 530 */ 531 static int test_snprintf_int( 532 void *NotUsed, 533 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 534 int argc, /* Number of arguments */ 535 char **argv /* Text of each argument */ 536 ){ 537 char zStr[100]; 538 int n = atoi(argv[1]); 539 const char *zFormat = argv[2]; 540 int a1 = atoi(argv[3]); 541 if( n>sizeof(zStr) ) n = sizeof(zStr); 542 sqlite3_snprintf(sizeof(zStr), zStr, "abcdefghijklmnopqrstuvwxyz"); 543 sqlite3_snprintf(n, zStr, zFormat, a1); 544 Tcl_AppendResult(interp, zStr, 0); 545 return TCL_OK; 546 } 547 548 #ifndef SQLITE_OMIT_GET_TABLE 549 550 /* 551 ** Usage: sqlite3_get_table_printf DB FORMAT STRING ?--no-counts? 552 ** 553 ** Invoke the sqlite3_get_table_printf() interface using the open database 554 ** DB. The SQL is the string FORMAT. The format string should contain 555 ** one %s or %q. STRING is the value inserted into %s or %q. 556 */ 557 static int test_get_table_printf( 558 void *NotUsed, 559 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 560 int argc, /* Number of arguments */ 561 char **argv /* Text of each argument */ 562 ){ 563 sqlite3 *db; 564 Tcl_DString str; 565 int rc; 566 char *zErr = 0; 567 int nRow, nCol; 568 char **aResult; 569 int i; 570 char zBuf[30]; 571 char *zSql; 572 int resCount = -1; 573 if( argc==5 ){ 574 if( Tcl_GetInt(interp, argv[4], &resCount) ) return TCL_ERROR; 575 } 576 if( argc!=4 && argc!=5 ){ 577 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 578 " DB FORMAT STRING ?COUNT?", 0); 579 return TCL_ERROR; 580 } 581 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 582 Tcl_DStringInit(&str); 583 zSql = sqlite3_mprintf(argv[2],argv[3]); 584 if( argc==5 ){ 585 rc = sqlite3_get_table(db, zSql, &aResult, 0, 0, &zErr); 586 }else{ 587 rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr); 588 resCount = (nRow+1)*nCol; 589 } 590 sqlite3_free(zSql); 591 sprintf(zBuf, "%d", rc); 592 Tcl_AppendElement(interp, zBuf); 593 if( rc==SQLITE_OK ){ 594 if( argc==4 ){ 595 sprintf(zBuf, "%d", nRow); 596 Tcl_AppendElement(interp, zBuf); 597 sprintf(zBuf, "%d", nCol); 598 Tcl_AppendElement(interp, zBuf); 599 } 600 for(i=0; i<resCount; i++){ 601 Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL"); 602 } 603 }else{ 604 Tcl_AppendElement(interp, zErr); 605 } 606 sqlite3_free_table(aResult); 607 if( zErr ) sqlite3_free(zErr); 608 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 609 return TCL_OK; 610 } 611 612 #endif /* SQLITE_OMIT_GET_TABLE */ 613 614 615 /* 616 ** Usage: sqlite3_last_insert_rowid DB 617 ** 618 ** Returns the integer ROWID of the most recent insert. 619 */ 620 static int test_last_rowid( 621 void *NotUsed, 622 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 623 int argc, /* Number of arguments */ 624 char **argv /* Text of each argument */ 625 ){ 626 sqlite3 *db; 627 char zBuf[30]; 628 629 if( argc!=2 ){ 630 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0); 631 return TCL_ERROR; 632 } 633 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 634 sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db)); 635 Tcl_AppendResult(interp, zBuf, 0); 636 return SQLITE_OK; 637 } 638 639 /* 640 ** Usage: sqlite3_key DB KEY 641 ** 642 ** Set the codec key. 643 */ 644 static int test_key( 645 void *NotUsed, 646 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 647 int argc, /* Number of arguments */ 648 char **argv /* Text of each argument */ 649 ){ 650 #ifdef SQLITE_HAS_CODEC 651 sqlite3 *db; 652 const char *zKey; 653 int nKey; 654 if( argc!=3 ){ 655 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 656 " FILENAME\"", 0); 657 return TCL_ERROR; 658 } 659 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 660 zKey = argv[2]; 661 nKey = strlen(zKey); 662 sqlite3_key(db, zKey, nKey); 663 #endif 664 return TCL_OK; 665 } 666 667 /* 668 ** Usage: sqlite3_rekey DB KEY 669 ** 670 ** Change the codec key. 671 */ 672 static int test_rekey( 673 void *NotUsed, 674 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 675 int argc, /* Number of arguments */ 676 char **argv /* Text of each argument */ 677 ){ 678 #ifdef SQLITE_HAS_CODEC 679 sqlite3 *db; 680 const char *zKey; 681 int nKey; 682 if( argc!=3 ){ 683 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 684 " FILENAME\"", 0); 685 return TCL_ERROR; 686 } 687 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 688 zKey = argv[2]; 689 nKey = strlen(zKey); 690 sqlite3_rekey(db, zKey, nKey); 691 #endif 692 return TCL_OK; 693 } 694 695 /* 696 ** Usage: sqlite3_close DB 697 ** 698 ** Closes the database opened by sqlite3_open. 699 */ 700 static int sqlite_test_close( 701 void *NotUsed, 702 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 703 int argc, /* Number of arguments */ 704 char **argv /* Text of each argument */ 705 ){ 706 sqlite3 *db; 707 int rc; 708 if( argc!=2 ){ 709 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 710 " FILENAME\"", 0); 711 return TCL_ERROR; 712 } 713 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 714 rc = sqlite3_close(db); 715 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 716 return TCL_OK; 717 } 718 719 /* 720 ** Usage: sqlite3_close_v2 DB 721 ** 722 ** Closes the database opened by sqlite3_open. 723 */ 724 static int sqlite_test_close_v2( 725 void *NotUsed, 726 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 727 int argc, /* Number of arguments */ 728 char **argv /* Text of each argument */ 729 ){ 730 sqlite3 *db; 731 int rc; 732 if( argc!=2 ){ 733 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 734 " FILENAME\"", 0); 735 return TCL_ERROR; 736 } 737 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 738 rc = sqlite3_close_v2(db); 739 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 740 return TCL_OK; 741 } 742 743 /* 744 ** Implementation of the x_coalesce() function. 745 ** Return the first argument non-NULL argument. 746 */ 747 static void t1_ifnullFunc( 748 sqlite3_context *context, 749 int argc, 750 sqlite3_value **argv 751 ){ 752 int i; 753 for(i=0; i<argc; i++){ 754 if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){ 755 int n = sqlite3_value_bytes(argv[i]); 756 sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]), 757 n, SQLITE_TRANSIENT); 758 break; 759 } 760 } 761 } 762 763 /* 764 ** These are test functions. hex8() interprets its argument as 765 ** UTF8 and returns a hex encoding. hex16le() interprets its argument 766 ** as UTF16le and returns a hex encoding. 767 */ 768 static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){ 769 const unsigned char *z; 770 int i; 771 char zBuf[200]; 772 z = sqlite3_value_text(argv[0]); 773 for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){ 774 sprintf(&zBuf[i*2], "%02x", z[i]&0xff); 775 } 776 zBuf[i*2] = 0; 777 sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT); 778 } 779 #ifndef SQLITE_OMIT_UTF16 780 static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){ 781 const unsigned short int *z; 782 int i; 783 char zBuf[400]; 784 z = sqlite3_value_text16(argv[0]); 785 for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){ 786 sprintf(&zBuf[i*4], "%04x", z[i]&0xff); 787 } 788 zBuf[i*4] = 0; 789 sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT); 790 } 791 #endif 792 793 /* 794 ** A structure into which to accumulate text. 795 */ 796 struct dstr { 797 int nAlloc; /* Space allocated */ 798 int nUsed; /* Space used */ 799 char *z; /* The space */ 800 }; 801 802 /* 803 ** Append text to a dstr 804 */ 805 static void dstrAppend(struct dstr *p, const char *z, int divider){ 806 int n = (int)strlen(z); 807 if( p->nUsed + n + 2 > p->nAlloc ){ 808 char *zNew; 809 p->nAlloc = p->nAlloc*2 + n + 200; 810 zNew = sqlite3_realloc(p->z, p->nAlloc); 811 if( zNew==0 ){ 812 sqlite3_free(p->z); 813 memset(p, 0, sizeof(*p)); 814 return; 815 } 816 p->z = zNew; 817 } 818 if( divider && p->nUsed>0 ){ 819 p->z[p->nUsed++] = divider; 820 } 821 memcpy(&p->z[p->nUsed], z, n+1); 822 p->nUsed += n; 823 } 824 825 /* 826 ** Invoked for each callback from sqlite3ExecFunc 827 */ 828 static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){ 829 struct dstr *p = (struct dstr*)pData; 830 int i; 831 for(i=0; i<argc; i++){ 832 if( argv[i]==0 ){ 833 dstrAppend(p, "NULL", ' '); 834 }else{ 835 dstrAppend(p, argv[i], ' '); 836 } 837 } 838 return 0; 839 } 840 841 /* 842 ** Implementation of the x_sqlite_exec() function. This function takes 843 ** a single argument and attempts to execute that argument as SQL code. 844 ** This is illegal and should set the SQLITE_MISUSE flag on the database. 845 ** 846 ** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec() 847 ** from within a function call. 848 ** 849 ** This routine simulates the effect of having two threads attempt to 850 ** use the same database at the same time. 851 */ 852 static void sqlite3ExecFunc( 853 sqlite3_context *context, 854 int argc, 855 sqlite3_value **argv 856 ){ 857 struct dstr x; 858 memset(&x, 0, sizeof(x)); 859 (void)sqlite3_exec((sqlite3*)sqlite3_user_data(context), 860 (char*)sqlite3_value_text(argv[0]), 861 execFuncCallback, &x, 0); 862 sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT); 863 sqlite3_free(x.z); 864 } 865 866 /* 867 ** Implementation of tkt2213func(), a scalar function that takes exactly 868 ** one argument. It has two interesting features: 869 ** 870 ** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*. 871 ** If the three pointers returned are not the same an SQL error is raised. 872 ** 873 ** * Otherwise it returns a copy of the text representation of its 874 ** argument in such a way as the VDBE representation is a Mem* cell 875 ** with the MEM_Term flag clear. 876 ** 877 ** Ticket #2213 can therefore be tested by evaluating the following 878 ** SQL expression: 879 ** 880 ** tkt2213func(tkt2213func('a string')); 881 */ 882 static void tkt2213Function( 883 sqlite3_context *context, 884 int argc, 885 sqlite3_value **argv 886 ){ 887 int nText; 888 unsigned char const *zText1; 889 unsigned char const *zText2; 890 unsigned char const *zText3; 891 892 nText = sqlite3_value_bytes(argv[0]); 893 zText1 = sqlite3_value_text(argv[0]); 894 zText2 = sqlite3_value_text(argv[0]); 895 zText3 = sqlite3_value_text(argv[0]); 896 897 if( zText1!=zText2 || zText2!=zText3 ){ 898 sqlite3_result_error(context, "tkt2213 is not fixed", -1); 899 }else{ 900 char *zCopy = (char *)sqlite3_malloc(nText); 901 memcpy(zCopy, zText1, nText); 902 sqlite3_result_text(context, zCopy, nText, sqlite3_free); 903 } 904 } 905 906 /* 907 ** The following SQL function takes 4 arguments. The 2nd and 908 ** 4th argument must be one of these strings: 'text', 'text16', 909 ** or 'blob' corresponding to API functions 910 ** 911 ** sqlite3_value_text() 912 ** sqlite3_value_text16() 913 ** sqlite3_value_blob() 914 ** 915 ** The third argument is a string, either 'bytes' or 'bytes16' or 'noop', 916 ** corresponding to APIs: 917 ** 918 ** sqlite3_value_bytes() 919 ** sqlite3_value_bytes16() 920 ** noop 921 ** 922 ** The APIs designated by the 2nd through 4th arguments are applied 923 ** to the first argument in order. If the pointers returned by the 924 ** second and fourth are different, this routine returns 1. Otherwise, 925 ** this routine returns 0. 926 ** 927 ** This function is used to test to see when returned pointers from 928 ** the _text(), _text16() and _blob() APIs become invalidated. 929 */ 930 static void ptrChngFunction( 931 sqlite3_context *context, 932 int argc, 933 sqlite3_value **argv 934 ){ 935 const void *p1, *p2; 936 const char *zCmd; 937 if( argc!=4 ) return; 938 zCmd = (const char*)sqlite3_value_text(argv[1]); 939 if( zCmd==0 ) return; 940 if( strcmp(zCmd,"text")==0 ){ 941 p1 = (const void*)sqlite3_value_text(argv[0]); 942 #ifndef SQLITE_OMIT_UTF16 943 }else if( strcmp(zCmd, "text16")==0 ){ 944 p1 = (const void*)sqlite3_value_text16(argv[0]); 945 #endif 946 }else if( strcmp(zCmd, "blob")==0 ){ 947 p1 = (const void*)sqlite3_value_blob(argv[0]); 948 }else{ 949 return; 950 } 951 zCmd = (const char*)sqlite3_value_text(argv[2]); 952 if( zCmd==0 ) return; 953 if( strcmp(zCmd,"bytes")==0 ){ 954 sqlite3_value_bytes(argv[0]); 955 #ifndef SQLITE_OMIT_UTF16 956 }else if( strcmp(zCmd, "bytes16")==0 ){ 957 sqlite3_value_bytes16(argv[0]); 958 #endif 959 }else if( strcmp(zCmd, "noop")==0 ){ 960 /* do nothing */ 961 }else{ 962 return; 963 } 964 zCmd = (const char*)sqlite3_value_text(argv[3]); 965 if( zCmd==0 ) return; 966 if( strcmp(zCmd,"text")==0 ){ 967 p2 = (const void*)sqlite3_value_text(argv[0]); 968 #ifndef SQLITE_OMIT_UTF16 969 }else if( strcmp(zCmd, "text16")==0 ){ 970 p2 = (const void*)sqlite3_value_text16(argv[0]); 971 #endif 972 }else if( strcmp(zCmd, "blob")==0 ){ 973 p2 = (const void*)sqlite3_value_blob(argv[0]); 974 }else{ 975 return; 976 } 977 sqlite3_result_int(context, p1!=p2); 978 } 979 980 /* 981 ** This SQL function returns a different answer each time it is called, even if 982 ** the arguments are the same. 983 */ 984 static void nondeterministicFunction( 985 sqlite3_context *context, 986 int argc, 987 sqlite3_value **argv 988 ){ 989 static int cnt = 0; 990 sqlite3_result_int(context, cnt++); 991 } 992 993 /* 994 ** Usage: sqlite3_create_function DB 995 ** 996 ** Call the sqlite3_create_function API on the given database in order 997 ** to create a function named "x_coalesce". This function does the same thing 998 ** as the "coalesce" function. This function also registers an SQL function 999 ** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec() 1000 ** in this way is illegal recursion and should raise an SQLITE_MISUSE error. 1001 ** The effect is similar to trying to use the same database connection from 1002 ** two threads at the same time. 1003 ** 1004 ** The original motivation for this routine was to be able to call the 1005 ** sqlite3_create_function function while a query is in progress in order 1006 ** to test the SQLITE_MISUSE detection logic. 1007 */ 1008 static int test_create_function( 1009 void *NotUsed, 1010 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1011 int argc, /* Number of arguments */ 1012 char **argv /* Text of each argument */ 1013 ){ 1014 int rc; 1015 sqlite3 *db; 1016 1017 if( argc!=2 ){ 1018 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1019 " DB\"", 0); 1020 return TCL_ERROR; 1021 } 1022 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 1023 rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_UTF8, 0, 1024 t1_ifnullFunc, 0, 0); 1025 if( rc==SQLITE_OK ){ 1026 rc = sqlite3_create_function(db, "hex8", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, 1027 0, hex8Func, 0, 0); 1028 } 1029 #ifndef SQLITE_OMIT_UTF16 1030 if( rc==SQLITE_OK ){ 1031 rc = sqlite3_create_function(db, "hex16", 1, SQLITE_UTF16 | SQLITE_DETERMINISTIC, 1032 0, hex16Func, 0, 0); 1033 } 1034 #endif 1035 if( rc==SQLITE_OK ){ 1036 rc = sqlite3_create_function(db, "tkt2213func", 1, SQLITE_ANY, 0, 1037 tkt2213Function, 0, 0); 1038 } 1039 if( rc==SQLITE_OK ){ 1040 rc = sqlite3_create_function(db, "pointer_change", 4, SQLITE_ANY, 0, 1041 ptrChngFunction, 0, 0); 1042 } 1043 1044 /* Functions counter1() and counter2() have the same implementation - they 1045 ** both return an ascending integer with each call. But counter1() is marked 1046 ** as non-deterministic and counter2() is marked as deterministic. 1047 */ 1048 if( rc==SQLITE_OK ){ 1049 rc = sqlite3_create_function(db, "counter1", -1, SQLITE_UTF8, 1050 0, nondeterministicFunction, 0, 0); 1051 } 1052 if( rc==SQLITE_OK ){ 1053 rc = sqlite3_create_function(db, "counter2", -1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1054 0, nondeterministicFunction, 0, 0); 1055 } 1056 1057 #ifndef SQLITE_OMIT_UTF16 1058 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also 1059 ** because it is not tested anywhere else. */ 1060 if( rc==SQLITE_OK ){ 1061 const void *zUtf16; 1062 sqlite3_value *pVal; 1063 sqlite3_mutex_enter(db->mutex); 1064 pVal = sqlite3ValueNew(db); 1065 sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC); 1066 zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); 1067 if( db->mallocFailed ){ 1068 rc = SQLITE_NOMEM; 1069 }else{ 1070 rc = sqlite3_create_function16(db, zUtf16, 1071 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0); 1072 } 1073 sqlite3ValueFree(pVal); 1074 sqlite3_mutex_leave(db->mutex); 1075 } 1076 #endif 1077 1078 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 1079 Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); 1080 return TCL_OK; 1081 } 1082 1083 /* 1084 ** Routines to implement the x_count() aggregate function. 1085 ** 1086 ** x_count() counts the number of non-null arguments. But there are 1087 ** some twists for testing purposes. 1088 ** 1089 ** If the argument to x_count() is 40 then a UTF-8 error is reported 1090 ** on the step function. If x_count(41) is seen, then a UTF-16 error 1091 ** is reported on the step function. If the total count is 42, then 1092 ** a UTF-8 error is reported on the finalize function. 1093 */ 1094 typedef struct t1CountCtx t1CountCtx; 1095 struct t1CountCtx { 1096 int n; 1097 }; 1098 static void t1CountStep( 1099 sqlite3_context *context, 1100 int argc, 1101 sqlite3_value **argv 1102 ){ 1103 t1CountCtx *p; 1104 p = sqlite3_aggregate_context(context, sizeof(*p)); 1105 if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){ 1106 p->n++; 1107 } 1108 if( argc>0 ){ 1109 int v = sqlite3_value_int(argv[0]); 1110 if( v==40 ){ 1111 sqlite3_result_error(context, "value of 40 handed to x_count", -1); 1112 #ifndef SQLITE_OMIT_UTF16 1113 }else if( v==41 ){ 1114 const char zUtf16ErrMsg[] = { 0, 0x61, 0, 0x62, 0, 0x63, 0, 0, 0}; 1115 sqlite3_result_error16(context, &zUtf16ErrMsg[1-SQLITE_BIGENDIAN], -1); 1116 #endif 1117 } 1118 } 1119 } 1120 static void t1CountFinalize(sqlite3_context *context){ 1121 t1CountCtx *p; 1122 p = sqlite3_aggregate_context(context, sizeof(*p)); 1123 if( p ){ 1124 if( p->n==42 ){ 1125 sqlite3_result_error(context, "x_count totals to 42", -1); 1126 }else{ 1127 sqlite3_result_int(context, p ? p->n : 0); 1128 } 1129 } 1130 } 1131 1132 #ifndef SQLITE_OMIT_DEPRECATED 1133 static void legacyCountStep( 1134 sqlite3_context *context, 1135 int argc, 1136 sqlite3_value **argv 1137 ){ 1138 /* no-op */ 1139 } 1140 1141 static void legacyCountFinalize(sqlite3_context *context){ 1142 sqlite3_result_int(context, sqlite3_aggregate_count(context)); 1143 } 1144 #endif 1145 1146 /* 1147 ** Usage: sqlite3_create_aggregate DB 1148 ** 1149 ** Call the sqlite3_create_function API on the given database in order 1150 ** to create a function named "x_count". This function is similar 1151 ** to the built-in count() function, with a few special quirks 1152 ** for testing the sqlite3_result_error() APIs. 1153 ** 1154 ** The original motivation for this routine was to be able to call the 1155 ** sqlite3_create_aggregate function while a query is in progress in order 1156 ** to test the SQLITE_MISUSE detection logic. See misuse.test. 1157 ** 1158 ** This routine was later extended to test the use of sqlite3_result_error() 1159 ** within aggregate functions. 1160 ** 1161 ** Later: It is now also extended to register the aggregate function 1162 ** "legacy_count()" with the supplied database handle. This is used 1163 ** to test the deprecated sqlite3_aggregate_count() API. 1164 */ 1165 static int test_create_aggregate( 1166 void *NotUsed, 1167 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1168 int argc, /* Number of arguments */ 1169 char **argv /* Text of each argument */ 1170 ){ 1171 sqlite3 *db; 1172 int rc; 1173 if( argc!=2 ){ 1174 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1175 " FILENAME\"", 0); 1176 return TCL_ERROR; 1177 } 1178 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 1179 rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0, 1180 t1CountStep,t1CountFinalize); 1181 if( rc==SQLITE_OK ){ 1182 rc = sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0, 1183 t1CountStep,t1CountFinalize); 1184 } 1185 #ifndef SQLITE_OMIT_DEPRECATED 1186 if( rc==SQLITE_OK ){ 1187 rc = sqlite3_create_function(db, "legacy_count", 0, SQLITE_ANY, 0, 0, 1188 legacyCountStep, legacyCountFinalize 1189 ); 1190 } 1191 #endif 1192 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 1193 Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); 1194 return TCL_OK; 1195 } 1196 1197 1198 /* 1199 ** Usage: printf TEXT 1200 ** 1201 ** Send output to printf. Use this rather than puts to merge the output 1202 ** in the correct sequence with debugging printfs inserted into C code. 1203 ** Puts uses a separate buffer and debugging statements will be out of 1204 ** sequence if it is used. 1205 */ 1206 static int test_printf( 1207 void *NotUsed, 1208 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1209 int argc, /* Number of arguments */ 1210 char **argv /* Text of each argument */ 1211 ){ 1212 if( argc!=2 ){ 1213 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1214 " TEXT\"", 0); 1215 return TCL_ERROR; 1216 } 1217 printf("%s\n", argv[1]); 1218 return TCL_OK; 1219 } 1220 1221 1222 1223 /* 1224 ** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER 1225 ** 1226 ** Call mprintf with three integer arguments 1227 */ 1228 static int sqlite3_mprintf_int( 1229 void *NotUsed, 1230 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1231 int argc, /* Number of arguments */ 1232 char **argv /* Text of each argument */ 1233 ){ 1234 int a[3], i; 1235 char *z; 1236 if( argc!=5 ){ 1237 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1238 " FORMAT INT INT INT\"", 0); 1239 return TCL_ERROR; 1240 } 1241 for(i=2; i<5; i++){ 1242 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 1243 } 1244 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); 1245 Tcl_AppendResult(interp, z, 0); 1246 sqlite3_free(z); 1247 return TCL_OK; 1248 } 1249 1250 /* 1251 ** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER 1252 ** 1253 ** Call mprintf with three 64-bit integer arguments 1254 */ 1255 static int sqlite3_mprintf_int64( 1256 void *NotUsed, 1257 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1258 int argc, /* Number of arguments */ 1259 char **argv /* Text of each argument */ 1260 ){ 1261 int i; 1262 sqlite_int64 a[3]; 1263 char *z; 1264 if( argc!=5 ){ 1265 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1266 " FORMAT INT INT INT\"", 0); 1267 return TCL_ERROR; 1268 } 1269 for(i=2; i<5; i++){ 1270 if( sqlite3Atoi64(argv[i], &a[i-2], 1000000, SQLITE_UTF8) ){ 1271 Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0); 1272 return TCL_ERROR; 1273 } 1274 } 1275 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); 1276 Tcl_AppendResult(interp, z, 0); 1277 sqlite3_free(z); 1278 return TCL_OK; 1279 } 1280 1281 /* 1282 ** Usage: sqlite3_mprintf_long FORMAT INTEGER INTEGER INTEGER 1283 ** 1284 ** Call mprintf with three long integer arguments. This might be the 1285 ** same as sqlite3_mprintf_int or sqlite3_mprintf_int64, depending on 1286 ** platform. 1287 */ 1288 static int sqlite3_mprintf_long( 1289 void *NotUsed, 1290 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1291 int argc, /* Number of arguments */ 1292 char **argv /* Text of each argument */ 1293 ){ 1294 int i; 1295 long int a[3]; 1296 int b[3]; 1297 char *z; 1298 if( argc!=5 ){ 1299 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1300 " FORMAT INT INT INT\"", 0); 1301 return TCL_ERROR; 1302 } 1303 for(i=2; i<5; i++){ 1304 if( Tcl_GetInt(interp, argv[i], &b[i-2]) ) return TCL_ERROR; 1305 a[i-2] = (long int)b[i-2]; 1306 a[i-2] &= (((u64)1)<<(sizeof(int)*8))-1; 1307 } 1308 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); 1309 Tcl_AppendResult(interp, z, 0); 1310 sqlite3_free(z); 1311 return TCL_OK; 1312 } 1313 1314 /* 1315 ** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING 1316 ** 1317 ** Call mprintf with two integer arguments and one string argument 1318 */ 1319 static int sqlite3_mprintf_str( 1320 void *NotUsed, 1321 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1322 int argc, /* Number of arguments */ 1323 char **argv /* Text of each argument */ 1324 ){ 1325 int a[3], i; 1326 char *z; 1327 if( argc<4 || argc>5 ){ 1328 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1329 " FORMAT INT INT ?STRING?\"", 0); 1330 return TCL_ERROR; 1331 } 1332 for(i=2; i<4; i++){ 1333 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 1334 } 1335 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL); 1336 Tcl_AppendResult(interp, z, 0); 1337 sqlite3_free(z); 1338 return TCL_OK; 1339 } 1340 1341 /* 1342 ** Usage: sqlite3_snprintf_str INTEGER FORMAT INTEGER INTEGER STRING 1343 ** 1344 ** Call mprintf with two integer arguments and one string argument 1345 */ 1346 static int sqlite3_snprintf_str( 1347 void *NotUsed, 1348 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1349 int argc, /* Number of arguments */ 1350 char **argv /* Text of each argument */ 1351 ){ 1352 int a[3], i; 1353 int n; 1354 char *z; 1355 if( argc<5 || argc>6 ){ 1356 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1357 " INT FORMAT INT INT ?STRING?\"", 0); 1358 return TCL_ERROR; 1359 } 1360 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; 1361 if( n<0 ){ 1362 Tcl_AppendResult(interp, "N must be non-negative", 0); 1363 return TCL_ERROR; 1364 } 1365 for(i=3; i<5; i++){ 1366 if( Tcl_GetInt(interp, argv[i], &a[i-3]) ) return TCL_ERROR; 1367 } 1368 z = sqlite3_malloc( n+1 ); 1369 sqlite3_snprintf(n, z, argv[2], a[0], a[1], argc>4 ? argv[5] : NULL); 1370 Tcl_AppendResult(interp, z, 0); 1371 sqlite3_free(z); 1372 return TCL_OK; 1373 } 1374 1375 /* 1376 ** Usage: sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE 1377 ** 1378 ** Call mprintf with two integer arguments and one double argument 1379 */ 1380 static int sqlite3_mprintf_double( 1381 void *NotUsed, 1382 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1383 int argc, /* Number of arguments */ 1384 char **argv /* Text of each argument */ 1385 ){ 1386 int a[3], i; 1387 double r; 1388 char *z; 1389 if( argc!=5 ){ 1390 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1391 " FORMAT INT INT DOUBLE\"", 0); 1392 return TCL_ERROR; 1393 } 1394 for(i=2; i<4; i++){ 1395 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; 1396 } 1397 if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR; 1398 z = sqlite3_mprintf(argv[1], a[0], a[1], r); 1399 Tcl_AppendResult(interp, z, 0); 1400 sqlite3_free(z); 1401 return TCL_OK; 1402 } 1403 1404 /* 1405 ** Usage: sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE 1406 ** 1407 ** Call mprintf with a single double argument which is the product of the 1408 ** two arguments given above. This is used to generate overflow and underflow 1409 ** doubles to test that they are converted properly. 1410 */ 1411 static int sqlite3_mprintf_scaled( 1412 void *NotUsed, 1413 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1414 int argc, /* Number of arguments */ 1415 char **argv /* Text of each argument */ 1416 ){ 1417 int i; 1418 double r[2]; 1419 char *z; 1420 if( argc!=4 ){ 1421 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1422 " FORMAT DOUBLE DOUBLE\"", 0); 1423 return TCL_ERROR; 1424 } 1425 for(i=2; i<4; i++){ 1426 if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR; 1427 } 1428 z = sqlite3_mprintf(argv[1], r[0]*r[1]); 1429 Tcl_AppendResult(interp, z, 0); 1430 sqlite3_free(z); 1431 return TCL_OK; 1432 } 1433 1434 /* 1435 ** Usage: sqlite3_mprintf_stronly FORMAT STRING 1436 ** 1437 ** Call mprintf with a single double argument which is the product of the 1438 ** two arguments given above. This is used to generate overflow and underflow 1439 ** doubles to test that they are converted properly. 1440 */ 1441 static int sqlite3_mprintf_stronly( 1442 void *NotUsed, 1443 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1444 int argc, /* Number of arguments */ 1445 char **argv /* Text of each argument */ 1446 ){ 1447 char *z; 1448 if( argc!=3 ){ 1449 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1450 " FORMAT STRING\"", 0); 1451 return TCL_ERROR; 1452 } 1453 z = sqlite3_mprintf(argv[1], argv[2]); 1454 Tcl_AppendResult(interp, z, 0); 1455 sqlite3_free(z); 1456 return TCL_OK; 1457 } 1458 1459 /* 1460 ** Usage: sqlite3_mprintf_hexdouble FORMAT HEX 1461 ** 1462 ** Call mprintf with a single double argument which is derived from the 1463 ** hexadecimal encoding of an IEEE double. 1464 */ 1465 static int sqlite3_mprintf_hexdouble( 1466 void *NotUsed, 1467 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1468 int argc, /* Number of arguments */ 1469 char **argv /* Text of each argument */ 1470 ){ 1471 char *z; 1472 double r; 1473 unsigned int x1, x2; 1474 sqlite_uint64 d; 1475 if( argc!=3 ){ 1476 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1477 " FORMAT STRING\"", 0); 1478 return TCL_ERROR; 1479 } 1480 if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){ 1481 Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0); 1482 return TCL_ERROR; 1483 } 1484 d = x2; 1485 d = (d<<32) + x1; 1486 memcpy(&r, &d, sizeof(r)); 1487 z = sqlite3_mprintf(argv[1], r); 1488 Tcl_AppendResult(interp, z, 0); 1489 sqlite3_free(z); 1490 return TCL_OK; 1491 } 1492 1493 /* 1494 ** Usage: sqlite3_enable_shared_cache ?BOOLEAN? 1495 ** 1496 */ 1497 #if !defined(SQLITE_OMIT_SHARED_CACHE) 1498 static int test_enable_shared( 1499 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 1500 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1501 int objc, /* Number of arguments */ 1502 Tcl_Obj *CONST objv[] /* Command arguments */ 1503 ){ 1504 int rc; 1505 int enable; 1506 int ret = 0; 1507 1508 if( objc!=2 && objc!=1 ){ 1509 Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?"); 1510 return TCL_ERROR; 1511 } 1512 ret = sqlite3GlobalConfig.sharedCacheEnabled; 1513 1514 if( objc==2 ){ 1515 if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){ 1516 return TCL_ERROR; 1517 } 1518 rc = sqlite3_enable_shared_cache(enable); 1519 if( rc!=SQLITE_OK ){ 1520 Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC); 1521 return TCL_ERROR; 1522 } 1523 } 1524 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret)); 1525 return TCL_OK; 1526 } 1527 #endif 1528 1529 1530 1531 /* 1532 ** Usage: sqlite3_extended_result_codes DB BOOLEAN 1533 ** 1534 */ 1535 static int test_extended_result_codes( 1536 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 1537 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1538 int objc, /* Number of arguments */ 1539 Tcl_Obj *CONST objv[] /* Command arguments */ 1540 ){ 1541 int enable; 1542 sqlite3 *db; 1543 1544 if( objc!=3 ){ 1545 Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN"); 1546 return TCL_ERROR; 1547 } 1548 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 1549 if( Tcl_GetBooleanFromObj(interp, objv[2], &enable) ) return TCL_ERROR; 1550 sqlite3_extended_result_codes(db, enable); 1551 return TCL_OK; 1552 } 1553 1554 /* 1555 ** Usage: sqlite3_libversion_number 1556 ** 1557 */ 1558 static int test_libversion_number( 1559 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 1560 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1561 int objc, /* Number of arguments */ 1562 Tcl_Obj *CONST objv[] /* Command arguments */ 1563 ){ 1564 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_libversion_number())); 1565 return TCL_OK; 1566 } 1567 1568 /* 1569 ** Usage: sqlite3_table_column_metadata DB dbname tblname colname 1570 ** 1571 */ 1572 static int test_table_column_metadata( 1573 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 1574 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1575 int objc, /* Number of arguments */ 1576 Tcl_Obj *CONST objv[] /* Command arguments */ 1577 ){ 1578 sqlite3 *db; 1579 const char *zDb; 1580 const char *zTbl; 1581 const char *zCol; 1582 int rc; 1583 Tcl_Obj *pRet; 1584 1585 const char *zDatatype; 1586 const char *zCollseq; 1587 int notnull; 1588 int primarykey; 1589 int autoincrement; 1590 1591 if( objc!=5 && objc!=4 ){ 1592 Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname"); 1593 return TCL_ERROR; 1594 } 1595 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 1596 zDb = Tcl_GetString(objv[2]); 1597 zTbl = Tcl_GetString(objv[3]); 1598 zCol = objc==5 ? Tcl_GetString(objv[4]) : 0; 1599 1600 if( strlen(zDb)==0 ) zDb = 0; 1601 1602 rc = sqlite3_table_column_metadata(db, zDb, zTbl, zCol, 1603 &zDatatype, &zCollseq, ¬null, &primarykey, &autoincrement); 1604 1605 if( rc!=SQLITE_OK ){ 1606 Tcl_AppendResult(interp, sqlite3_errmsg(db), 0); 1607 return TCL_ERROR; 1608 } 1609 1610 pRet = Tcl_NewObj(); 1611 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zDatatype, -1)); 1612 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zCollseq, -1)); 1613 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(notnull)); 1614 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(primarykey)); 1615 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(autoincrement)); 1616 Tcl_SetObjResult(interp, pRet); 1617 1618 return TCL_OK; 1619 } 1620 1621 #ifndef SQLITE_OMIT_INCRBLOB 1622 1623 static int blobHandleFromObj( 1624 Tcl_Interp *interp, 1625 Tcl_Obj *pObj, 1626 sqlite3_blob **ppBlob 1627 ){ 1628 char *z; 1629 int n; 1630 1631 z = Tcl_GetStringFromObj(pObj, &n); 1632 if( n==0 ){ 1633 *ppBlob = 0; 1634 }else{ 1635 int notUsed; 1636 Tcl_Channel channel; 1637 ClientData instanceData; 1638 1639 channel = Tcl_GetChannel(interp, z, ¬Used); 1640 if( !channel ) return TCL_ERROR; 1641 1642 Tcl_Flush(channel); 1643 Tcl_Seek(channel, 0, SEEK_SET); 1644 1645 instanceData = Tcl_GetChannelInstanceData(channel); 1646 *ppBlob = *((sqlite3_blob **)instanceData); 1647 } 1648 1649 return TCL_OK; 1650 } 1651 1652 static int test_blob_reopen( 1653 ClientData clientData, /* Not used */ 1654 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1655 int objc, /* Number of arguments */ 1656 Tcl_Obj *CONST objv[] /* Command arguments */ 1657 ){ 1658 Tcl_WideInt iRowid; 1659 sqlite3_blob *pBlob; 1660 int rc; 1661 1662 if( objc!=3 ){ 1663 Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL ROWID"); 1664 return TCL_ERROR; 1665 } 1666 1667 if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR; 1668 if( Tcl_GetWideIntFromObj(interp, objv[2], &iRowid) ) return TCL_ERROR; 1669 1670 rc = sqlite3_blob_reopen(pBlob, iRowid); 1671 if( rc!=SQLITE_OK ){ 1672 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE); 1673 } 1674 1675 return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); 1676 } 1677 1678 #endif 1679 1680 /* 1681 ** Usage: sqlite3_create_collation_v2 DB-HANDLE NAME CMP-PROC DEL-PROC 1682 ** 1683 ** This Tcl proc is used for testing the experimental 1684 ** sqlite3_create_collation_v2() interface. 1685 */ 1686 struct TestCollationX { 1687 Tcl_Interp *interp; 1688 Tcl_Obj *pCmp; 1689 Tcl_Obj *pDel; 1690 }; 1691 typedef struct TestCollationX TestCollationX; 1692 static void testCreateCollationDel(void *pCtx){ 1693 TestCollationX *p = (TestCollationX *)pCtx; 1694 1695 int rc = Tcl_EvalObjEx(p->interp, p->pDel, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL); 1696 if( rc!=TCL_OK ){ 1697 Tcl_BackgroundError(p->interp); 1698 } 1699 1700 Tcl_DecrRefCount(p->pCmp); 1701 Tcl_DecrRefCount(p->pDel); 1702 sqlite3_free((void *)p); 1703 } 1704 static int testCreateCollationCmp( 1705 void *pCtx, 1706 int nLeft, 1707 const void *zLeft, 1708 int nRight, 1709 const void *zRight 1710 ){ 1711 TestCollationX *p = (TestCollationX *)pCtx; 1712 Tcl_Obj *pScript = Tcl_DuplicateObj(p->pCmp); 1713 int iRes = 0; 1714 1715 Tcl_IncrRefCount(pScript); 1716 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zLeft, nLeft)); 1717 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zRight,nRight)); 1718 1719 if( TCL_OK!=Tcl_EvalObjEx(p->interp, pScript, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL) 1720 || TCL_OK!=Tcl_GetIntFromObj(p->interp, Tcl_GetObjResult(p->interp), &iRes) 1721 ){ 1722 Tcl_BackgroundError(p->interp); 1723 } 1724 Tcl_DecrRefCount(pScript); 1725 1726 return iRes; 1727 } 1728 static int test_create_collation_v2( 1729 ClientData clientData, /* Not used */ 1730 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1731 int objc, /* Number of arguments */ 1732 Tcl_Obj *CONST objv[] /* Command arguments */ 1733 ){ 1734 TestCollationX *p; 1735 sqlite3 *db; 1736 int rc; 1737 1738 if( objc!=5 ){ 1739 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE NAME CMP-PROC DEL-PROC"); 1740 return TCL_ERROR; 1741 } 1742 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 1743 1744 p = (TestCollationX *)sqlite3_malloc(sizeof(TestCollationX)); 1745 p->pCmp = objv[3]; 1746 p->pDel = objv[4]; 1747 p->interp = interp; 1748 Tcl_IncrRefCount(p->pCmp); 1749 Tcl_IncrRefCount(p->pDel); 1750 1751 rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), 16, 1752 (void *)p, testCreateCollationCmp, testCreateCollationDel 1753 ); 1754 if( rc!=SQLITE_MISUSE ){ 1755 Tcl_AppendResult(interp, "sqlite3_create_collate_v2() failed to detect " 1756 "an invalid encoding", (char*)0); 1757 return TCL_ERROR; 1758 } 1759 rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), SQLITE_UTF8, 1760 (void *)p, testCreateCollationCmp, testCreateCollationDel 1761 ); 1762 return TCL_OK; 1763 } 1764 1765 /* 1766 ** USAGE: sqlite3_create_function_v2 DB NAME NARG ENC ?SWITCHES? 1767 ** 1768 ** Available switches are: 1769 ** 1770 ** -func SCRIPT 1771 ** -step SCRIPT 1772 ** -final SCRIPT 1773 ** -destroy SCRIPT 1774 */ 1775 typedef struct CreateFunctionV2 CreateFunctionV2; 1776 struct CreateFunctionV2 { 1777 Tcl_Interp *interp; 1778 Tcl_Obj *pFunc; /* Script for function invocation */ 1779 Tcl_Obj *pStep; /* Script for agg. step invocation */ 1780 Tcl_Obj *pFinal; /* Script for agg. finalization invocation */ 1781 Tcl_Obj *pDestroy; /* Destructor script */ 1782 }; 1783 static void cf2Func(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ 1784 } 1785 static void cf2Step(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ 1786 } 1787 static void cf2Final(sqlite3_context *ctx){ 1788 } 1789 static void cf2Destroy(void *pUser){ 1790 CreateFunctionV2 *p = (CreateFunctionV2 *)pUser; 1791 1792 if( p->interp && p->pDestroy ){ 1793 int rc = Tcl_EvalObjEx(p->interp, p->pDestroy, 0); 1794 if( rc!=TCL_OK ) Tcl_BackgroundError(p->interp); 1795 } 1796 1797 if( p->pFunc ) Tcl_DecrRefCount(p->pFunc); 1798 if( p->pStep ) Tcl_DecrRefCount(p->pStep); 1799 if( p->pFinal ) Tcl_DecrRefCount(p->pFinal); 1800 if( p->pDestroy ) Tcl_DecrRefCount(p->pDestroy); 1801 sqlite3_free(p); 1802 } 1803 static int test_create_function_v2( 1804 ClientData clientData, /* Not used */ 1805 Tcl_Interp *interp, /* The invoking TCL interpreter */ 1806 int objc, /* Number of arguments */ 1807 Tcl_Obj *CONST objv[] /* Command arguments */ 1808 ){ 1809 sqlite3 *db; 1810 const char *zFunc; 1811 int nArg; 1812 int enc; 1813 CreateFunctionV2 *p; 1814 int i; 1815 int rc; 1816 1817 struct EncTable { 1818 const char *zEnc; 1819 int enc; 1820 } aEnc[] = { 1821 {"utf8", SQLITE_UTF8 }, 1822 {"utf16", SQLITE_UTF16 }, 1823 {"utf16le", SQLITE_UTF16LE }, 1824 {"utf16be", SQLITE_UTF16BE }, 1825 {"any", SQLITE_ANY }, 1826 {"0", 0 } 1827 }; 1828 1829 if( objc<5 || (objc%2)==0 ){ 1830 Tcl_WrongNumArgs(interp, 1, objv, "DB NAME NARG ENC SWITCHES..."); 1831 return TCL_ERROR; 1832 } 1833 1834 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 1835 zFunc = Tcl_GetString(objv[2]); 1836 if( Tcl_GetIntFromObj(interp, objv[3], &nArg) ) return TCL_ERROR; 1837 if( Tcl_GetIndexFromObjStruct(interp, objv[4], aEnc, sizeof(aEnc[0]), 1838 "encoding", 0, &enc) 1839 ){ 1840 return TCL_ERROR; 1841 } 1842 enc = aEnc[enc].enc; 1843 1844 p = sqlite3_malloc(sizeof(CreateFunctionV2)); 1845 assert( p ); 1846 memset(p, 0, sizeof(CreateFunctionV2)); 1847 p->interp = interp; 1848 1849 for(i=5; i<objc; i+=2){ 1850 int iSwitch; 1851 const char *azSwitch[] = {"-func", "-step", "-final", "-destroy", 0}; 1852 if( Tcl_GetIndexFromObj(interp, objv[i], azSwitch, "switch", 0, &iSwitch) ){ 1853 sqlite3_free(p); 1854 return TCL_ERROR; 1855 } 1856 1857 switch( iSwitch ){ 1858 case 0: p->pFunc = objv[i+1]; break; 1859 case 1: p->pStep = objv[i+1]; break; 1860 case 2: p->pFinal = objv[i+1]; break; 1861 case 3: p->pDestroy = objv[i+1]; break; 1862 } 1863 } 1864 if( p->pFunc ) p->pFunc = Tcl_DuplicateObj(p->pFunc); 1865 if( p->pStep ) p->pStep = Tcl_DuplicateObj(p->pStep); 1866 if( p->pFinal ) p->pFinal = Tcl_DuplicateObj(p->pFinal); 1867 if( p->pDestroy ) p->pDestroy = Tcl_DuplicateObj(p->pDestroy); 1868 1869 if( p->pFunc ) Tcl_IncrRefCount(p->pFunc); 1870 if( p->pStep ) Tcl_IncrRefCount(p->pStep); 1871 if( p->pFinal ) Tcl_IncrRefCount(p->pFinal); 1872 if( p->pDestroy ) Tcl_IncrRefCount(p->pDestroy); 1873 1874 rc = sqlite3_create_function_v2(db, zFunc, nArg, enc, (void *)p, 1875 (p->pFunc ? cf2Func : 0), 1876 (p->pStep ? cf2Step : 0), 1877 (p->pFinal ? cf2Final : 0), 1878 cf2Destroy 1879 ); 1880 if( rc!=SQLITE_OK ){ 1881 Tcl_ResetResult(interp); 1882 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); 1883 return TCL_ERROR; 1884 } 1885 return TCL_OK; 1886 } 1887 1888 /* 1889 ** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC? 1890 */ 1891 static int test_load_extension( 1892 ClientData clientData, /* Not used */ 1893 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1894 int objc, /* Number of arguments */ 1895 Tcl_Obj *CONST objv[] /* Command arguments */ 1896 ){ 1897 Tcl_CmdInfo cmdInfo; 1898 sqlite3 *db; 1899 int rc; 1900 char *zDb; 1901 char *zFile; 1902 char *zProc = 0; 1903 char *zErr = 0; 1904 1905 if( objc!=4 && objc!=3 ){ 1906 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?"); 1907 return TCL_ERROR; 1908 } 1909 zDb = Tcl_GetString(objv[1]); 1910 zFile = Tcl_GetString(objv[2]); 1911 if( objc==4 ){ 1912 zProc = Tcl_GetString(objv[3]); 1913 } 1914 1915 /* Extract the C database handle from the Tcl command name */ 1916 if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ 1917 Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0); 1918 return TCL_ERROR; 1919 } 1920 db = ((struct SqliteDb*)cmdInfo.objClientData)->db; 1921 assert(db); 1922 1923 /* Call the underlying C function. If an error occurs, set rc to 1924 ** TCL_ERROR and load any error string into the interpreter. If no 1925 ** error occurs, set rc to TCL_OK. 1926 */ 1927 #ifdef SQLITE_OMIT_LOAD_EXTENSION 1928 rc = SQLITE_ERROR; 1929 zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()"); 1930 #else 1931 rc = sqlite3_load_extension(db, zFile, zProc, &zErr); 1932 #endif 1933 if( rc!=SQLITE_OK ){ 1934 Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE); 1935 rc = TCL_ERROR; 1936 }else{ 1937 rc = TCL_OK; 1938 } 1939 sqlite3_free(zErr); 1940 1941 return rc; 1942 } 1943 1944 /* 1945 ** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF 1946 */ 1947 static int test_enable_load( 1948 ClientData clientData, /* Not used */ 1949 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1950 int objc, /* Number of arguments */ 1951 Tcl_Obj *CONST objv[] /* Command arguments */ 1952 ){ 1953 Tcl_CmdInfo cmdInfo; 1954 sqlite3 *db; 1955 char *zDb; 1956 int onoff; 1957 1958 if( objc!=3 ){ 1959 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF"); 1960 return TCL_ERROR; 1961 } 1962 zDb = Tcl_GetString(objv[1]); 1963 1964 /* Extract the C database handle from the Tcl command name */ 1965 if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ 1966 Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0); 1967 return TCL_ERROR; 1968 } 1969 db = ((struct SqliteDb*)cmdInfo.objClientData)->db; 1970 assert(db); 1971 1972 /* Get the onoff parameter */ 1973 if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){ 1974 return TCL_ERROR; 1975 } 1976 1977 #ifdef SQLITE_OMIT_LOAD_EXTENSION 1978 Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()"); 1979 return TCL_ERROR; 1980 #else 1981 sqlite3_enable_load_extension(db, onoff); 1982 return TCL_OK; 1983 #endif 1984 } 1985 1986 /* 1987 ** Usage: sqlite_abort 1988 ** 1989 ** Shutdown the process immediately. This is not a clean shutdown. 1990 ** This command is used to test the recoverability of a database in 1991 ** the event of a program crash. 1992 */ 1993 static int sqlite_abort( 1994 void *NotUsed, 1995 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1996 int argc, /* Number of arguments */ 1997 char **argv /* Text of each argument */ 1998 ){ 1999 #if defined(_MSC_VER) 2000 /* We do this, otherwise the test will halt with a popup message 2001 * that we have to click away before the test will continue. 2002 */ 2003 _set_abort_behavior( 0, _CALL_REPORTFAULT ); 2004 #endif 2005 exit(255); 2006 assert( interp==0 ); /* This will always fail */ 2007 return TCL_OK; 2008 } 2009 2010 /* 2011 ** The following routine is a user-defined SQL function whose purpose 2012 ** is to test the sqlite_set_result() API. 2013 */ 2014 static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ 2015 while( argc>=2 ){ 2016 const char *zArg0 = (char*)sqlite3_value_text(argv[0]); 2017 if( zArg0 ){ 2018 if( 0==sqlite3StrICmp(zArg0, "int") ){ 2019 sqlite3_result_int(context, sqlite3_value_int(argv[1])); 2020 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){ 2021 sqlite3_result_int64(context, sqlite3_value_int64(argv[1])); 2022 }else if( sqlite3StrICmp(zArg0,"string")==0 ){ 2023 sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1, 2024 SQLITE_TRANSIENT); 2025 }else if( sqlite3StrICmp(zArg0,"double")==0 ){ 2026 sqlite3_result_double(context, sqlite3_value_double(argv[1])); 2027 }else if( sqlite3StrICmp(zArg0,"null")==0 ){ 2028 sqlite3_result_null(context); 2029 }else if( sqlite3StrICmp(zArg0,"value")==0 ){ 2030 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]); 2031 }else{ 2032 goto error_out; 2033 } 2034 }else{ 2035 goto error_out; 2036 } 2037 argc -= 2; 2038 argv += 2; 2039 } 2040 return; 2041 2042 error_out: 2043 sqlite3_result_error(context,"first argument should be one of: " 2044 "int int64 string double null value", -1); 2045 } 2046 2047 /* 2048 ** Usage: sqlite_register_test_function DB NAME 2049 ** 2050 ** Register the test SQL function on the database DB under the name NAME. 2051 */ 2052 static int test_register_func( 2053 void *NotUsed, 2054 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 2055 int argc, /* Number of arguments */ 2056 char **argv /* Text of each argument */ 2057 ){ 2058 sqlite3 *db; 2059 int rc; 2060 if( argc!=3 ){ 2061 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 2062 " DB FUNCTION-NAME", 0); 2063 return TCL_ERROR; 2064 } 2065 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 2066 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 2067 testFunc, 0, 0); 2068 if( rc!=0 ){ 2069 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); 2070 return TCL_ERROR; 2071 } 2072 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 2073 return TCL_OK; 2074 } 2075 2076 /* 2077 ** Usage: sqlite3_finalize STMT 2078 ** 2079 ** Finalize a statement handle. 2080 */ 2081 static int test_finalize( 2082 void * clientData, 2083 Tcl_Interp *interp, 2084 int objc, 2085 Tcl_Obj *CONST objv[] 2086 ){ 2087 sqlite3_stmt *pStmt; 2088 int rc; 2089 sqlite3 *db = 0; 2090 2091 if( objc!=2 ){ 2092 Tcl_AppendResult(interp, "wrong # args: should be \"", 2093 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); 2094 return TCL_ERROR; 2095 } 2096 2097 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2098 2099 if( pStmt ){ 2100 db = StmtToDb(pStmt); 2101 } 2102 rc = sqlite3_finalize(pStmt); 2103 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 2104 if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 2105 return TCL_OK; 2106 } 2107 2108 /* 2109 ** Usage: sqlite3_stmt_status STMT CODE RESETFLAG 2110 ** 2111 ** Get the value of a status counter from a statement. 2112 */ 2113 static int test_stmt_status( 2114 void * clientData, 2115 Tcl_Interp *interp, 2116 int objc, 2117 Tcl_Obj *CONST objv[] 2118 ){ 2119 int iValue; 2120 int i, op, resetFlag; 2121 const char *zOpName; 2122 sqlite3_stmt *pStmt; 2123 2124 static const struct { 2125 const char *zName; 2126 int op; 2127 } aOp[] = { 2128 { "SQLITE_STMTSTATUS_FULLSCAN_STEP", SQLITE_STMTSTATUS_FULLSCAN_STEP }, 2129 { "SQLITE_STMTSTATUS_SORT", SQLITE_STMTSTATUS_SORT }, 2130 { "SQLITE_STMTSTATUS_AUTOINDEX", SQLITE_STMTSTATUS_AUTOINDEX }, 2131 { "SQLITE_STMTSTATUS_VM_STEP", SQLITE_STMTSTATUS_VM_STEP }, 2132 }; 2133 if( objc!=4 ){ 2134 Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG"); 2135 return TCL_ERROR; 2136 } 2137 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2138 zOpName = Tcl_GetString(objv[2]); 2139 for(i=0; i<ArraySize(aOp); i++){ 2140 if( strcmp(aOp[i].zName, zOpName)==0 ){ 2141 op = aOp[i].op; 2142 break; 2143 } 2144 } 2145 if( i>=ArraySize(aOp) ){ 2146 if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR; 2147 } 2148 if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR; 2149 iValue = sqlite3_stmt_status(pStmt, op, resetFlag); 2150 Tcl_SetObjResult(interp, Tcl_NewIntObj(iValue)); 2151 return TCL_OK; 2152 } 2153 2154 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS 2155 /* 2156 ** Usage: sqlite3_stmt_scanstatus STMT IDX 2157 */ 2158 static int test_stmt_scanstatus( 2159 void * clientData, 2160 Tcl_Interp *interp, 2161 int objc, 2162 Tcl_Obj *CONST objv[] 2163 ){ 2164 sqlite3_stmt *pStmt; /* First argument */ 2165 int idx; /* Second argument */ 2166 2167 const char *zName; 2168 const char *zExplain; 2169 sqlite3_int64 nLoop; 2170 sqlite3_int64 nVisit; 2171 double rEst; 2172 int res; 2173 2174 if( objc!=3 ){ 2175 Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX"); 2176 return TCL_ERROR; 2177 } 2178 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2179 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 2180 2181 res = sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop); 2182 if( res==0 ){ 2183 Tcl_Obj *pRet = Tcl_NewObj(); 2184 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nLoop", -1)); 2185 Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nLoop)); 2186 sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit); 2187 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nVisit", -1)); 2188 Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nVisit)); 2189 sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EST, (void*)&rEst); 2190 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nEst", -1)); 2191 Tcl_ListObjAppendElement(0, pRet, Tcl_NewDoubleObj(rEst)); 2192 sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NAME, (void*)&zName); 2193 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zName", -1)); 2194 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zName, -1)); 2195 sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain); 2196 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zExplain", -1)); 2197 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zExplain, -1)); 2198 Tcl_SetObjResult(interp, pRet); 2199 }else{ 2200 Tcl_ResetResult(interp); 2201 } 2202 return TCL_OK; 2203 } 2204 2205 /* 2206 ** Usage: sqlite3_stmt_scanstatus_reset STMT 2207 */ 2208 static int test_stmt_scanstatus_reset( 2209 void * clientData, 2210 Tcl_Interp *interp, 2211 int objc, 2212 Tcl_Obj *CONST objv[] 2213 ){ 2214 sqlite3_stmt *pStmt; /* First argument */ 2215 if( objc!=2 ){ 2216 Tcl_WrongNumArgs(interp, 1, objv, "STMT"); 2217 return TCL_ERROR; 2218 } 2219 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2220 sqlite3_stmt_scanstatus_reset(pStmt); 2221 return TCL_OK; 2222 } 2223 #endif 2224 2225 /* 2226 ** Usage: sqlite3_next_stmt DB STMT 2227 ** 2228 ** Return the next statment in sequence after STMT. 2229 */ 2230 static int test_next_stmt( 2231 void * clientData, 2232 Tcl_Interp *interp, 2233 int objc, 2234 Tcl_Obj *CONST objv[] 2235 ){ 2236 sqlite3_stmt *pStmt; 2237 sqlite3 *db = 0; 2238 char zBuf[50]; 2239 2240 if( objc!=3 ){ 2241 Tcl_AppendResult(interp, "wrong # args: should be \"", 2242 Tcl_GetStringFromObj(objv[0], 0), " DB STMT", 0); 2243 return TCL_ERROR; 2244 } 2245 2246 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 2247 if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt) ) return TCL_ERROR; 2248 pStmt = sqlite3_next_stmt(db, pStmt); 2249 if( pStmt ){ 2250 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 2251 Tcl_AppendResult(interp, zBuf, 0); 2252 } 2253 return TCL_OK; 2254 } 2255 2256 /* 2257 ** Usage: sqlite3_stmt_readonly STMT 2258 ** 2259 ** Return true if STMT is a NULL pointer or a pointer to a statement 2260 ** that is guaranteed to leave the database unmodified. 2261 */ 2262 static int test_stmt_readonly( 2263 void * clientData, 2264 Tcl_Interp *interp, 2265 int objc, 2266 Tcl_Obj *CONST objv[] 2267 ){ 2268 sqlite3_stmt *pStmt; 2269 int rc; 2270 2271 if( objc!=2 ){ 2272 Tcl_AppendResult(interp, "wrong # args: should be \"", 2273 Tcl_GetStringFromObj(objv[0], 0), " STMT", 0); 2274 return TCL_ERROR; 2275 } 2276 2277 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2278 rc = sqlite3_stmt_readonly(pStmt); 2279 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc)); 2280 return TCL_OK; 2281 } 2282 2283 /* 2284 ** Usage: sqlite3_stmt_busy STMT 2285 ** 2286 ** Return true if STMT is a non-NULL pointer to a statement 2287 ** that has been stepped but not to completion. 2288 */ 2289 static int test_stmt_busy( 2290 void * clientData, 2291 Tcl_Interp *interp, 2292 int objc, 2293 Tcl_Obj *CONST objv[] 2294 ){ 2295 sqlite3_stmt *pStmt; 2296 int rc; 2297 2298 if( objc!=2 ){ 2299 Tcl_AppendResult(interp, "wrong # args: should be \"", 2300 Tcl_GetStringFromObj(objv[0], 0), " STMT", 0); 2301 return TCL_ERROR; 2302 } 2303 2304 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2305 rc = sqlite3_stmt_busy(pStmt); 2306 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc)); 2307 return TCL_OK; 2308 } 2309 2310 /* 2311 ** Usage: uses_stmt_journal STMT 2312 ** 2313 ** Return true if STMT uses a statement journal. 2314 */ 2315 static int uses_stmt_journal( 2316 void * clientData, 2317 Tcl_Interp *interp, 2318 int objc, 2319 Tcl_Obj *CONST objv[] 2320 ){ 2321 sqlite3_stmt *pStmt; 2322 2323 if( objc!=2 ){ 2324 Tcl_AppendResult(interp, "wrong # args: should be \"", 2325 Tcl_GetStringFromObj(objv[0], 0), " STMT", 0); 2326 return TCL_ERROR; 2327 } 2328 2329 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2330 sqlite3_stmt_readonly(pStmt); 2331 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(((Vdbe *)pStmt)->usesStmtJournal)); 2332 return TCL_OK; 2333 } 2334 2335 2336 /* 2337 ** Usage: sqlite3_reset STMT 2338 ** 2339 ** Reset a statement handle. 2340 */ 2341 static int test_reset( 2342 void * clientData, 2343 Tcl_Interp *interp, 2344 int objc, 2345 Tcl_Obj *CONST objv[] 2346 ){ 2347 sqlite3_stmt *pStmt; 2348 int rc; 2349 2350 if( objc!=2 ){ 2351 Tcl_AppendResult(interp, "wrong # args: should be \"", 2352 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); 2353 return TCL_ERROR; 2354 } 2355 2356 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2357 2358 rc = sqlite3_reset(pStmt); 2359 if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){ 2360 return TCL_ERROR; 2361 } 2362 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 2363 /* 2364 if( rc ){ 2365 return TCL_ERROR; 2366 } 2367 */ 2368 return TCL_OK; 2369 } 2370 2371 /* 2372 ** Usage: sqlite3_expired STMT 2373 ** 2374 ** Return TRUE if a recompilation of the statement is recommended. 2375 */ 2376 static int test_expired( 2377 void * clientData, 2378 Tcl_Interp *interp, 2379 int objc, 2380 Tcl_Obj *CONST objv[] 2381 ){ 2382 #ifndef SQLITE_OMIT_DEPRECATED 2383 sqlite3_stmt *pStmt; 2384 if( objc!=2 ){ 2385 Tcl_AppendResult(interp, "wrong # args: should be \"", 2386 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); 2387 return TCL_ERROR; 2388 } 2389 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2390 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt))); 2391 #endif 2392 return TCL_OK; 2393 } 2394 2395 /* 2396 ** Usage: sqlite3_transfer_bindings FROMSTMT TOSTMT 2397 ** 2398 ** Transfer all bindings from FROMSTMT over to TOSTMT 2399 */ 2400 static int test_transfer_bind( 2401 void * clientData, 2402 Tcl_Interp *interp, 2403 int objc, 2404 Tcl_Obj *CONST objv[] 2405 ){ 2406 #ifndef SQLITE_OMIT_DEPRECATED 2407 sqlite3_stmt *pStmt1, *pStmt2; 2408 if( objc!=3 ){ 2409 Tcl_AppendResult(interp, "wrong # args: should be \"", 2410 Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0); 2411 return TCL_ERROR; 2412 } 2413 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR; 2414 if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR; 2415 Tcl_SetObjResult(interp, 2416 Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2))); 2417 #endif 2418 return TCL_OK; 2419 } 2420 2421 /* 2422 ** Usage: sqlite3_changes DB 2423 ** 2424 ** Return the number of changes made to the database by the last SQL 2425 ** execution. 2426 */ 2427 static int test_changes( 2428 void * clientData, 2429 Tcl_Interp *interp, 2430 int objc, 2431 Tcl_Obj *CONST objv[] 2432 ){ 2433 sqlite3 *db; 2434 if( objc!=2 ){ 2435 Tcl_AppendResult(interp, "wrong # args: should be \"", 2436 Tcl_GetString(objv[0]), " DB", 0); 2437 return TCL_ERROR; 2438 } 2439 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 2440 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db))); 2441 return TCL_OK; 2442 } 2443 2444 /* 2445 ** This is the "static_bind_value" that variables are bound to when 2446 ** the FLAG option of sqlite3_bind is "static" 2447 */ 2448 static char *sqlite_static_bind_value = 0; 2449 static int sqlite_static_bind_nbyte = 0; 2450 2451 /* 2452 ** Usage: sqlite3_bind VM IDX VALUE FLAGS 2453 ** 2454 ** Sets the value of the IDX-th occurrence of "?" in the original SQL 2455 ** string. VALUE is the new value. If FLAGS=="null" then VALUE is 2456 ** ignored and the value is set to NULL. If FLAGS=="static" then 2457 ** the value is set to the value of a static variable named 2458 ** "sqlite_static_bind_value". If FLAGS=="normal" then a copy 2459 ** of the VALUE is made. If FLAGS=="blob10" then a VALUE is ignored 2460 ** an a 10-byte blob "abc\000xyz\000pq" is inserted. 2461 */ 2462 static int test_bind( 2463 void *NotUsed, 2464 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 2465 int argc, /* Number of arguments */ 2466 char **argv /* Text of each argument */ 2467 ){ 2468 sqlite3_stmt *pStmt; 2469 int rc; 2470 int idx; 2471 if( argc!=5 ){ 2472 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 2473 " VM IDX VALUE (null|static|normal)\"", 0); 2474 return TCL_ERROR; 2475 } 2476 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR; 2477 if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR; 2478 if( strcmp(argv[4],"null")==0 ){ 2479 rc = sqlite3_bind_null(pStmt, idx); 2480 }else if( strcmp(argv[4],"static")==0 ){ 2481 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0); 2482 }else if( strcmp(argv[4],"static-nbytes")==0 ){ 2483 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, 2484 sqlite_static_bind_nbyte, 0); 2485 }else if( strcmp(argv[4],"normal")==0 ){ 2486 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT); 2487 }else if( strcmp(argv[4],"blob10")==0 ){ 2488 rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC); 2489 }else{ 2490 Tcl_AppendResult(interp, "4th argument should be " 2491 "\"null\" or \"static\" or \"normal\"", 0); 2492 return TCL_ERROR; 2493 } 2494 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 2495 if( rc ){ 2496 char zBuf[50]; 2497 sprintf(zBuf, "(%d) ", rc); 2498 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0); 2499 return TCL_ERROR; 2500 } 2501 return TCL_OK; 2502 } 2503 2504 #ifndef SQLITE_OMIT_UTF16 2505 /* 2506 ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be> 2507 ** 2508 ** This function is used to test that SQLite selects the correct collation 2509 ** sequence callback when multiple versions (for different text encodings) 2510 ** are available. 2511 ** 2512 ** Calling this routine registers the collation sequence "test_collate" 2513 ** with database handle <db>. The second argument must be a list of three 2514 ** boolean values. If the first is true, then a version of test_collate is 2515 ** registered for UTF-8, if the second is true, a version is registered for 2516 ** UTF-16le, if the third is true, a UTF-16be version is available. 2517 ** Previous versions of test_collate are deleted. 2518 ** 2519 ** The collation sequence test_collate is implemented by calling the 2520 ** following TCL script: 2521 ** 2522 ** "test_collate <enc> <lhs> <rhs>" 2523 ** 2524 ** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8. 2525 ** The <enc> parameter is the encoding of the collation function that 2526 ** SQLite selected to call. The TCL test script implements the 2527 ** "test_collate" proc. 2528 ** 2529 ** Note that this will only work with one interpreter at a time, as the 2530 ** interp pointer to use when evaluating the TCL script is stored in 2531 ** pTestCollateInterp. 2532 */ 2533 static Tcl_Interp* pTestCollateInterp; 2534 static int test_collate_func( 2535 void *pCtx, 2536 int nA, const void *zA, 2537 int nB, const void *zB 2538 ){ 2539 Tcl_Interp *i = pTestCollateInterp; 2540 int encin = SQLITE_PTR_TO_INT(pCtx); 2541 int res; 2542 int n; 2543 2544 sqlite3_value *pVal; 2545 Tcl_Obj *pX; 2546 2547 pX = Tcl_NewStringObj("test_collate", -1); 2548 Tcl_IncrRefCount(pX); 2549 2550 switch( encin ){ 2551 case SQLITE_UTF8: 2552 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1)); 2553 break; 2554 case SQLITE_UTF16LE: 2555 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1)); 2556 break; 2557 case SQLITE_UTF16BE: 2558 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1)); 2559 break; 2560 default: 2561 assert(0); 2562 } 2563 2564 sqlite3BeginBenignMalloc(); 2565 pVal = sqlite3ValueNew(0); 2566 if( pVal ){ 2567 sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC); 2568 n = sqlite3_value_bytes(pVal); 2569 Tcl_ListObjAppendElement(i,pX, 2570 Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n)); 2571 sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC); 2572 n = sqlite3_value_bytes(pVal); 2573 Tcl_ListObjAppendElement(i,pX, 2574 Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n)); 2575 sqlite3ValueFree(pVal); 2576 } 2577 sqlite3EndBenignMalloc(); 2578 2579 Tcl_EvalObjEx(i, pX, 0); 2580 Tcl_DecrRefCount(pX); 2581 Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res); 2582 return res; 2583 } 2584 static int test_collate( 2585 void * clientData, 2586 Tcl_Interp *interp, 2587 int objc, 2588 Tcl_Obj *CONST objv[] 2589 ){ 2590 sqlite3 *db; 2591 int val; 2592 sqlite3_value *pVal; 2593 int rc; 2594 2595 if( objc!=5 ) goto bad_args; 2596 pTestCollateInterp = interp; 2597 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 2598 2599 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; 2600 rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8, 2601 (void *)SQLITE_UTF8, val?test_collate_func:0); 2602 if( rc==SQLITE_OK ){ 2603 const void *zUtf16; 2604 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; 2605 rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE, 2606 (void *)SQLITE_UTF16LE, val?test_collate_func:0); 2607 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; 2608 2609 #if 0 2610 if( sqlite3_iMallocFail>0 ){ 2611 sqlite3_iMallocFail++; 2612 } 2613 #endif 2614 sqlite3_mutex_enter(db->mutex); 2615 pVal = sqlite3ValueNew(db); 2616 sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC); 2617 zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); 2618 if( db->mallocFailed ){ 2619 rc = SQLITE_NOMEM; 2620 }else{ 2621 rc = sqlite3_create_collation16(db, zUtf16, SQLITE_UTF16BE, 2622 (void *)SQLITE_UTF16BE, val?test_collate_func:0); 2623 } 2624 sqlite3ValueFree(pVal); 2625 sqlite3_mutex_leave(db->mutex); 2626 } 2627 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 2628 2629 if( rc!=SQLITE_OK ){ 2630 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); 2631 return TCL_ERROR; 2632 } 2633 return TCL_OK; 2634 2635 bad_args: 2636 Tcl_AppendResult(interp, "wrong # args: should be \"", 2637 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); 2638 return TCL_ERROR; 2639 } 2640 2641 /* 2642 ** Usage: add_test_utf16bin_collate <db ptr> 2643 ** 2644 ** Add a utf-16 collation sequence named "utf16bin" to the database 2645 ** handle. This collation sequence compares arguments in the same way as the 2646 ** built-in collation "binary". 2647 */ 2648 static int test_utf16bin_collate_func( 2649 void *pCtx, 2650 int nA, const void *zA, 2651 int nB, const void *zB 2652 ){ 2653 int nCmp = (nA>nB ? nB : nA); 2654 int res = memcmp(zA, zB, nCmp); 2655 if( res==0 ) res = nA - nB; 2656 return res; 2657 } 2658 static int test_utf16bin_collate( 2659 void * clientData, 2660 Tcl_Interp *interp, 2661 int objc, 2662 Tcl_Obj *CONST objv[] 2663 ){ 2664 sqlite3 *db; 2665 int rc; 2666 2667 if( objc!=2 ) goto bad_args; 2668 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 2669 2670 rc = sqlite3_create_collation(db, "utf16bin", SQLITE_UTF16, 0, 2671 test_utf16bin_collate_func 2672 ); 2673 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 2674 return TCL_OK; 2675 2676 bad_args: 2677 Tcl_WrongNumArgs(interp, 1, objv, "DB"); 2678 return TCL_ERROR; 2679 } 2680 2681 /* 2682 ** When the collation needed callback is invoked, record the name of 2683 ** the requested collating function here. The recorded name is linked 2684 ** to a TCL variable and used to make sure that the requested collation 2685 ** name is correct. 2686 */ 2687 static char zNeededCollation[200]; 2688 static char *pzNeededCollation = zNeededCollation; 2689 2690 2691 /* 2692 ** Called when a collating sequence is needed. Registered using 2693 ** sqlite3_collation_needed16(). 2694 */ 2695 static void test_collate_needed_cb( 2696 void *pCtx, 2697 sqlite3 *db, 2698 int eTextRep, 2699 const void *pName 2700 ){ 2701 int enc = ENC(db); 2702 int i; 2703 char *z; 2704 for(z = (char*)pName, i=0; *z || z[1]; z++){ 2705 if( *z ) zNeededCollation[i++] = *z; 2706 } 2707 zNeededCollation[i] = 0; 2708 sqlite3_create_collation( 2709 db, "test_collate", ENC(db), SQLITE_INT_TO_PTR(enc), test_collate_func); 2710 } 2711 2712 /* 2713 ** Usage: add_test_collate_needed DB 2714 */ 2715 static int test_collate_needed( 2716 void * clientData, 2717 Tcl_Interp *interp, 2718 int objc, 2719 Tcl_Obj *CONST objv[] 2720 ){ 2721 sqlite3 *db; 2722 int rc; 2723 2724 if( objc!=2 ) goto bad_args; 2725 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 2726 rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb); 2727 zNeededCollation[0] = 0; 2728 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 2729 return TCL_OK; 2730 2731 bad_args: 2732 Tcl_WrongNumArgs(interp, 1, objv, "DB"); 2733 return TCL_ERROR; 2734 } 2735 2736 /* 2737 ** tclcmd: add_alignment_test_collations DB 2738 ** 2739 ** Add two new collating sequences to the database DB 2740 ** 2741 ** utf16_aligned 2742 ** utf16_unaligned 2743 ** 2744 ** Both collating sequences use the same sort order as BINARY. 2745 ** The only difference is that the utf16_aligned collating 2746 ** sequence is declared with the SQLITE_UTF16_ALIGNED flag. 2747 ** Both collating functions increment the unaligned utf16 counter 2748 ** whenever they see a string that begins on an odd byte boundary. 2749 */ 2750 static int unaligned_string_counter = 0; 2751 static int alignmentCollFunc( 2752 void *NotUsed, 2753 int nKey1, const void *pKey1, 2754 int nKey2, const void *pKey2 2755 ){ 2756 int rc, n; 2757 n = nKey1<nKey2 ? nKey1 : nKey2; 2758 if( nKey1>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey1))) ) unaligned_string_counter++; 2759 if( nKey2>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey2))) ) unaligned_string_counter++; 2760 rc = memcmp(pKey1, pKey2, n); 2761 if( rc==0 ){ 2762 rc = nKey1 - nKey2; 2763 } 2764 return rc; 2765 } 2766 static int add_alignment_test_collations( 2767 void * clientData, 2768 Tcl_Interp *interp, 2769 int objc, 2770 Tcl_Obj *CONST objv[] 2771 ){ 2772 sqlite3 *db; 2773 if( objc>=2 ){ 2774 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 2775 sqlite3_create_collation(db, "utf16_unaligned", SQLITE_UTF16, 2776 0, alignmentCollFunc); 2777 sqlite3_create_collation(db, "utf16_aligned", SQLITE_UTF16_ALIGNED, 2778 0, alignmentCollFunc); 2779 } 2780 return SQLITE_OK; 2781 } 2782 #endif /* !defined(SQLITE_OMIT_UTF16) */ 2783 2784 /* 2785 ** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be> 2786 ** 2787 ** This function is used to test that SQLite selects the correct user 2788 ** function callback when multiple versions (for different text encodings) 2789 ** are available. 2790 ** 2791 ** Calling this routine registers up to three versions of the user function 2792 ** "test_function" with database handle <db>. If the second argument is 2793 ** true, then a version of test_function is registered for UTF-8, if the 2794 ** third is true, a version is registered for UTF-16le, if the fourth is 2795 ** true, a UTF-16be version is available. Previous versions of 2796 ** test_function are deleted. 2797 ** 2798 ** The user function is implemented by calling the following TCL script: 2799 ** 2800 ** "test_function <enc> <arg>" 2801 ** 2802 ** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the 2803 ** single argument passed to the SQL function. The value returned by 2804 ** the TCL script is used as the return value of the SQL function. It 2805 ** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8 2806 ** for a UTF-16LE test_function(), and UTF-16LE for an implementation that 2807 ** prefers UTF-16BE. 2808 */ 2809 #ifndef SQLITE_OMIT_UTF16 2810 static void test_function_utf8( 2811 sqlite3_context *pCtx, 2812 int nArg, 2813 sqlite3_value **argv 2814 ){ 2815 Tcl_Interp *interp; 2816 Tcl_Obj *pX; 2817 sqlite3_value *pVal; 2818 interp = (Tcl_Interp *)sqlite3_user_data(pCtx); 2819 pX = Tcl_NewStringObj("test_function", -1); 2820 Tcl_IncrRefCount(pX); 2821 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1)); 2822 Tcl_ListObjAppendElement(interp, pX, 2823 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); 2824 Tcl_EvalObjEx(interp, pX, 0); 2825 Tcl_DecrRefCount(pX); 2826 sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT); 2827 pVal = sqlite3ValueNew(0); 2828 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 2829 SQLITE_UTF8, SQLITE_STATIC); 2830 sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal), 2831 -1, SQLITE_TRANSIENT); 2832 sqlite3ValueFree(pVal); 2833 } 2834 static void test_function_utf16le( 2835 sqlite3_context *pCtx, 2836 int nArg, 2837 sqlite3_value **argv 2838 ){ 2839 Tcl_Interp *interp; 2840 Tcl_Obj *pX; 2841 sqlite3_value *pVal; 2842 interp = (Tcl_Interp *)sqlite3_user_data(pCtx); 2843 pX = Tcl_NewStringObj("test_function", -1); 2844 Tcl_IncrRefCount(pX); 2845 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1)); 2846 Tcl_ListObjAppendElement(interp, pX, 2847 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); 2848 Tcl_EvalObjEx(interp, pX, 0); 2849 Tcl_DecrRefCount(pX); 2850 pVal = sqlite3ValueNew(0); 2851 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 2852 SQLITE_UTF8, SQLITE_STATIC); 2853 sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT); 2854 sqlite3ValueFree(pVal); 2855 } 2856 static void test_function_utf16be( 2857 sqlite3_context *pCtx, 2858 int nArg, 2859 sqlite3_value **argv 2860 ){ 2861 Tcl_Interp *interp; 2862 Tcl_Obj *pX; 2863 sqlite3_value *pVal; 2864 interp = (Tcl_Interp *)sqlite3_user_data(pCtx); 2865 pX = Tcl_NewStringObj("test_function", -1); 2866 Tcl_IncrRefCount(pX); 2867 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1)); 2868 Tcl_ListObjAppendElement(interp, pX, 2869 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); 2870 Tcl_EvalObjEx(interp, pX, 0); 2871 Tcl_DecrRefCount(pX); 2872 pVal = sqlite3ValueNew(0); 2873 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 2874 SQLITE_UTF8, SQLITE_STATIC); 2875 sqlite3_result_text16(pCtx, sqlite3_value_text16le(pVal), 2876 -1, SQLITE_TRANSIENT); 2877 sqlite3_result_text16be(pCtx, sqlite3_value_text16le(pVal), 2878 -1, SQLITE_TRANSIENT); 2879 sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal), 2880 -1, SQLITE_TRANSIENT); 2881 sqlite3ValueFree(pVal); 2882 } 2883 #endif /* SQLITE_OMIT_UTF16 */ 2884 static int test_function( 2885 void * clientData, 2886 Tcl_Interp *interp, 2887 int objc, 2888 Tcl_Obj *CONST objv[] 2889 ){ 2890 #ifndef SQLITE_OMIT_UTF16 2891 sqlite3 *db; 2892 int val; 2893 2894 if( objc!=5 ) goto bad_args; 2895 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 2896 2897 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; 2898 if( val ){ 2899 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8, 2900 interp, test_function_utf8, 0, 0); 2901 } 2902 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; 2903 if( val ){ 2904 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE, 2905 interp, test_function_utf16le, 0, 0); 2906 } 2907 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; 2908 if( val ){ 2909 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE, 2910 interp, test_function_utf16be, 0, 0); 2911 } 2912 2913 return TCL_OK; 2914 bad_args: 2915 Tcl_AppendResult(interp, "wrong # args: should be \"", 2916 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); 2917 #endif /* SQLITE_OMIT_UTF16 */ 2918 return TCL_ERROR; 2919 } 2920 2921 /* 2922 ** Usage: sqlite3_test_errstr <err code> 2923 ** 2924 ** Test that the english language string equivalents for sqlite error codes 2925 ** are sane. The parameter is an integer representing an sqlite error code. 2926 ** The result is a list of two elements, the string representation of the 2927 ** error code and the english language explanation. 2928 */ 2929 static int test_errstr( 2930 void * clientData, 2931 Tcl_Interp *interp, 2932 int objc, 2933 Tcl_Obj *CONST objv[] 2934 ){ 2935 char *zCode; 2936 int i; 2937 if( objc!=1 ){ 2938 Tcl_WrongNumArgs(interp, 1, objv, "<error code>"); 2939 } 2940 2941 zCode = Tcl_GetString(objv[1]); 2942 for(i=0; i<200; i++){ 2943 if( 0==strcmp(t1ErrorName(i), zCode) ) break; 2944 } 2945 Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0); 2946 return TCL_OK; 2947 } 2948 2949 /* 2950 ** Usage: breakpoint 2951 ** 2952 ** This routine exists for one purpose - to provide a place to put a 2953 ** breakpoint with GDB that can be triggered using TCL code. The use 2954 ** for this is when a particular test fails on (say) the 1485th iteration. 2955 ** In the TCL test script, we can add code like this: 2956 ** 2957 ** if {$i==1485} breakpoint 2958 ** 2959 ** Then run testfixture in the debugger and wait for the breakpoint to 2960 ** fire. Then additional breakpoints can be set to trace down the bug. 2961 */ 2962 static int test_breakpoint( 2963 void *NotUsed, 2964 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 2965 int argc, /* Number of arguments */ 2966 char **argv /* Text of each argument */ 2967 ){ 2968 return TCL_OK; /* Do nothing */ 2969 } 2970 2971 /* 2972 ** Usage: sqlite3_bind_zeroblob STMT IDX N 2973 ** 2974 ** Test the sqlite3_bind_zeroblob interface. STMT is a prepared statement. 2975 ** IDX is the index of a wildcard in the prepared statement. This command 2976 ** binds a N-byte zero-filled BLOB to the wildcard. 2977 */ 2978 static int test_bind_zeroblob( 2979 void * clientData, 2980 Tcl_Interp *interp, 2981 int objc, 2982 Tcl_Obj *CONST objv[] 2983 ){ 2984 sqlite3_stmt *pStmt; 2985 int idx; 2986 int n; 2987 int rc; 2988 2989 if( objc!=4 ){ 2990 Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N"); 2991 return TCL_ERROR; 2992 } 2993 2994 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 2995 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 2996 if( Tcl_GetIntFromObj(interp, objv[3], &n) ) return TCL_ERROR; 2997 2998 rc = sqlite3_bind_zeroblob(pStmt, idx, n); 2999 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 3000 if( rc!=SQLITE_OK ){ 3001 return TCL_ERROR; 3002 } 3003 3004 return TCL_OK; 3005 } 3006 3007 /* 3008 ** Usage: sqlite3_bind_int STMT N VALUE 3009 ** 3010 ** Test the sqlite3_bind_int interface. STMT is a prepared statement. 3011 ** N is the index of a wildcard in the prepared statement. This command 3012 ** binds a 32-bit integer VALUE to that wildcard. 3013 */ 3014 static int test_bind_int( 3015 void * clientData, 3016 Tcl_Interp *interp, 3017 int objc, 3018 Tcl_Obj *CONST objv[] 3019 ){ 3020 sqlite3_stmt *pStmt; 3021 int idx; 3022 int value; 3023 int rc; 3024 3025 if( objc!=4 ){ 3026 Tcl_AppendResult(interp, "wrong # args: should be \"", 3027 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); 3028 return TCL_ERROR; 3029 } 3030 3031 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 3032 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 3033 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; 3034 3035 rc = sqlite3_bind_int(pStmt, idx, value); 3036 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 3037 if( rc!=SQLITE_OK ){ 3038 return TCL_ERROR; 3039 } 3040 3041 return TCL_OK; 3042 } 3043 3044 3045 /* 3046 ** Usage: sqlite3_bind_int64 STMT N VALUE 3047 ** 3048 ** Test the sqlite3_bind_int64 interface. STMT is a prepared statement. 3049 ** N is the index of a wildcard in the prepared statement. This command 3050 ** binds a 64-bit integer VALUE to that wildcard. 3051 */ 3052 static int test_bind_int64( 3053 void * clientData, 3054 Tcl_Interp *interp, 3055 int objc, 3056 Tcl_Obj *CONST objv[] 3057 ){ 3058 sqlite3_stmt *pStmt; 3059 int idx; 3060 Tcl_WideInt value; 3061 int rc; 3062 3063 if( objc!=4 ){ 3064 Tcl_AppendResult(interp, "wrong # args: should be \"", 3065 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); 3066 return TCL_ERROR; 3067 } 3068 3069 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 3070 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 3071 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; 3072 3073 rc = sqlite3_bind_int64(pStmt, idx, value); 3074 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 3075 if( rc!=SQLITE_OK ){ 3076 return TCL_ERROR; 3077 } 3078 3079 return TCL_OK; 3080 } 3081 3082 3083 /* 3084 ** Usage: sqlite3_bind_double STMT N VALUE 3085 ** 3086 ** Test the sqlite3_bind_double interface. STMT is a prepared statement. 3087 ** N is the index of a wildcard in the prepared statement. This command 3088 ** binds a 64-bit integer VALUE to that wildcard. 3089 */ 3090 static int test_bind_double( 3091 void * clientData, 3092 Tcl_Interp *interp, 3093 int objc, 3094 Tcl_Obj *CONST objv[] 3095 ){ 3096 sqlite3_stmt *pStmt; 3097 int idx; 3098 double value; 3099 int rc; 3100 const char *zVal; 3101 int i; 3102 static const struct { 3103 const char *zName; /* Name of the special floating point value */ 3104 unsigned int iUpper; /* Upper 32 bits */ 3105 unsigned int iLower; /* Lower 32 bits */ 3106 } aSpecialFp[] = { 3107 { "NaN", 0x7fffffff, 0xffffffff }, 3108 { "SNaN", 0x7ff7ffff, 0xffffffff }, 3109 { "-NaN", 0xffffffff, 0xffffffff }, 3110 { "-SNaN", 0xfff7ffff, 0xffffffff }, 3111 { "+Inf", 0x7ff00000, 0x00000000 }, 3112 { "-Inf", 0xfff00000, 0x00000000 }, 3113 { "Epsilon", 0x00000000, 0x00000001 }, 3114 { "-Epsilon", 0x80000000, 0x00000001 }, 3115 { "NaN0", 0x7ff80000, 0x00000000 }, 3116 { "-NaN0", 0xfff80000, 0x00000000 }, 3117 }; 3118 3119 if( objc!=4 ){ 3120 Tcl_AppendResult(interp, "wrong # args: should be \"", 3121 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); 3122 return TCL_ERROR; 3123 } 3124 3125 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 3126 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 3127 3128 /* Intercept the string "NaN" and generate a NaN value for it. 3129 ** All other strings are passed through to Tcl_GetDoubleFromObj(). 3130 ** Tcl_GetDoubleFromObj() should understand "NaN" but some versions 3131 ** contain a bug. 3132 */ 3133 zVal = Tcl_GetString(objv[3]); 3134 for(i=0; i<sizeof(aSpecialFp)/sizeof(aSpecialFp[0]); i++){ 3135 if( strcmp(aSpecialFp[i].zName, zVal)==0 ){ 3136 sqlite3_uint64 x; 3137 x = aSpecialFp[i].iUpper; 3138 x <<= 32; 3139 x |= aSpecialFp[i].iLower; 3140 assert( sizeof(value)==8 ); 3141 assert( sizeof(x)==8 ); 3142 memcpy(&value, &x, 8); 3143 break; 3144 } 3145 } 3146 if( i>=sizeof(aSpecialFp)/sizeof(aSpecialFp[0]) && 3147 Tcl_GetDoubleFromObj(interp, objv[3], &value) ){ 3148 return TCL_ERROR; 3149 } 3150 rc = sqlite3_bind_double(pStmt, idx, value); 3151 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 3152 if( rc!=SQLITE_OK ){ 3153 return TCL_ERROR; 3154 } 3155 3156 return TCL_OK; 3157 } 3158 3159 /* 3160 ** Usage: sqlite3_bind_null STMT N 3161 ** 3162 ** Test the sqlite3_bind_null interface. STMT is a prepared statement. 3163 ** N is the index of a wildcard in the prepared statement. This command 3164 ** binds a NULL to the wildcard. 3165 */ 3166 static int test_bind_null( 3167 void * clientData, 3168 Tcl_Interp *interp, 3169 int objc, 3170 Tcl_Obj *CONST objv[] 3171 ){ 3172 sqlite3_stmt *pStmt; 3173 int idx; 3174 int rc; 3175 3176 if( objc!=3 ){ 3177 Tcl_AppendResult(interp, "wrong # args: should be \"", 3178 Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0); 3179 return TCL_ERROR; 3180 } 3181 3182 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 3183 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 3184 3185 rc = sqlite3_bind_null(pStmt, idx); 3186 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 3187 if( rc!=SQLITE_OK ){ 3188 return TCL_ERROR; 3189 } 3190 3191 return TCL_OK; 3192 } 3193 3194 /* 3195 ** Usage: sqlite3_bind_text STMT N STRING BYTES 3196 ** 3197 ** Test the sqlite3_bind_text interface. STMT is a prepared statement. 3198 ** N is the index of a wildcard in the prepared statement. This command 3199 ** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes 3200 ** long. 3201 */ 3202 static int test_bind_text( 3203 void * clientData, 3204 Tcl_Interp *interp, 3205 int objc, 3206 Tcl_Obj *CONST objv[] 3207 ){ 3208 sqlite3_stmt *pStmt; 3209 int idx; 3210 int bytes; 3211 char *value; 3212 int rc; 3213 3214 if( objc!=5 ){ 3215 Tcl_AppendResult(interp, "wrong # args: should be \"", 3216 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0); 3217 return TCL_ERROR; 3218 } 3219 3220 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 3221 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 3222 value = (char*)Tcl_GetByteArrayFromObj(objv[3], &bytes); 3223 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 3224 3225 rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT); 3226 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 3227 if( rc!=SQLITE_OK ){ 3228 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); 3229 return TCL_ERROR; 3230 } 3231 3232 return TCL_OK; 3233 } 3234 3235 /* 3236 ** Usage: sqlite3_bind_text16 ?-static? STMT N STRING BYTES 3237 ** 3238 ** Test the sqlite3_bind_text16 interface. STMT is a prepared statement. 3239 ** N is the index of a wildcard in the prepared statement. This command 3240 ** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes 3241 ** long. 3242 */ 3243 static int test_bind_text16( 3244 void * clientData, 3245 Tcl_Interp *interp, 3246 int objc, 3247 Tcl_Obj *CONST objv[] 3248 ){ 3249 #ifndef SQLITE_OMIT_UTF16 3250 sqlite3_stmt *pStmt; 3251 int idx; 3252 int bytes; 3253 char *value; 3254 int rc; 3255 3256 void (*xDel)(void*) = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT); 3257 Tcl_Obj *oStmt = objv[objc-4]; 3258 Tcl_Obj *oN = objv[objc-3]; 3259 Tcl_Obj *oString = objv[objc-2]; 3260 Tcl_Obj *oBytes = objv[objc-1]; 3261 3262 if( objc!=5 && objc!=6){ 3263 Tcl_AppendResult(interp, "wrong # args: should be \"", 3264 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0); 3265 return TCL_ERROR; 3266 } 3267 3268 if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR; 3269 if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR; 3270 value = (char*)Tcl_GetByteArrayFromObj(oString, 0); 3271 if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR; 3272 3273 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel); 3274 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 3275 if( rc!=SQLITE_OK ){ 3276 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); 3277 return TCL_ERROR; 3278 } 3279 3280 #endif /* SQLITE_OMIT_UTF16 */ 3281 return TCL_OK; 3282 } 3283 3284 /* 3285 ** Usage: sqlite3_bind_blob ?-static? STMT N DATA BYTES 3286 ** 3287 ** Test the sqlite3_bind_blob interface. STMT is a prepared statement. 3288 ** N is the index of a wildcard in the prepared statement. This command 3289 ** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size. 3290 */ 3291 static int test_bind_blob( 3292 void * clientData, 3293 Tcl_Interp *interp, 3294 int objc, 3295 Tcl_Obj *CONST objv[] 3296 ){ 3297 sqlite3_stmt *pStmt; 3298 int idx; 3299 int bytes; 3300 char *value; 3301 int rc; 3302 sqlite3_destructor_type xDestructor = SQLITE_TRANSIENT; 3303 3304 if( objc!=5 && objc!=6 ){ 3305 Tcl_AppendResult(interp, "wrong # args: should be \"", 3306 Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0); 3307 return TCL_ERROR; 3308 } 3309 3310 if( objc==6 ){ 3311 xDestructor = SQLITE_STATIC; 3312 objv++; 3313 } 3314 3315 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 3316 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; 3317 value = Tcl_GetString(objv[3]); 3318 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; 3319 3320 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, xDestructor); 3321 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; 3322 if( rc!=SQLITE_OK ){ 3323 return TCL_ERROR; 3324 } 3325 3326 return TCL_OK; 3327 } 3328 3329 /* 3330 ** Usage: sqlite3_bind_parameter_count STMT 3331 ** 3332 ** Return the number of wildcards in the given statement. 3333 */ 3334 static int test_bind_parameter_count( 3335 void * clientData, 3336 Tcl_Interp *interp, 3337 int objc, 3338 Tcl_Obj *CONST objv[] 3339 ){ 3340 sqlite3_stmt *pStmt; 3341 3342 if( objc!=2 ){ 3343 Tcl_WrongNumArgs(interp, 1, objv, "STMT"); 3344 return TCL_ERROR; 3345 } 3346 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 3347 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt))); 3348 return TCL_OK; 3349 } 3350 3351 /* 3352 ** Usage: sqlite3_bind_parameter_name STMT N 3353 ** 3354 ** Return the name of the Nth wildcard. The first wildcard is 1. 3355 ** An empty string is returned if N is out of range or if the wildcard 3356 ** is nameless. 3357 */ 3358 static int test_bind_parameter_name( 3359 void * clientData, 3360 Tcl_Interp *interp, 3361 int objc, 3362 Tcl_Obj *CONST objv[] 3363 ){ 3364 sqlite3_stmt *pStmt; 3365 int i; 3366 3367 if( objc!=3 ){ 3368 Tcl_WrongNumArgs(interp, 1, objv, "STMT N"); 3369 return TCL_ERROR; 3370 } 3371 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 3372 if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR; 3373 Tcl_SetObjResult(interp, 3374 Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1) 3375 ); 3376 return TCL_OK; 3377 } 3378 3379 /* 3380 ** Usage: sqlite3_bind_parameter_index STMT NAME 3381 ** 3382 ** Return the index of the wildcard called NAME. Return 0 if there is 3383 ** no such wildcard. 3384 */ 3385 static int test_bind_parameter_index( 3386 void * clientData, 3387 Tcl_Interp *interp, 3388 int objc, 3389 Tcl_Obj *CONST objv[] 3390 ){ 3391 sqlite3_stmt *pStmt; 3392 3393 if( objc!=3 ){ 3394 Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME"); 3395 return TCL_ERROR; 3396 } 3397 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 3398 Tcl_SetObjResult(interp, 3399 Tcl_NewIntObj( 3400 sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2])) 3401 ) 3402 ); 3403 return TCL_OK; 3404 } 3405 3406 /* 3407 ** Usage: sqlite3_clear_bindings STMT 3408 ** 3409 */ 3410 static int test_clear_bindings( 3411 void * clientData, 3412 Tcl_Interp *interp, 3413 int objc, 3414 Tcl_Obj *CONST objv[] 3415 ){ 3416 sqlite3_stmt *pStmt; 3417 3418 if( objc!=2 ){ 3419 Tcl_WrongNumArgs(interp, 1, objv, "STMT"); 3420 return TCL_ERROR; 3421 } 3422 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 3423 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt))); 3424 return TCL_OK; 3425 } 3426 3427 /* 3428 ** Usage: sqlite3_sleep MILLISECONDS 3429 */ 3430 static int test_sleep( 3431 void * clientData, 3432 Tcl_Interp *interp, 3433 int objc, 3434 Tcl_Obj *CONST objv[] 3435 ){ 3436 int ms; 3437 3438 if( objc!=2 ){ 3439 Tcl_WrongNumArgs(interp, 1, objv, "MILLISECONDS"); 3440 return TCL_ERROR; 3441 } 3442 if( Tcl_GetIntFromObj(interp, objv[1], &ms) ){ 3443 return TCL_ERROR; 3444 } 3445 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(ms))); 3446 return TCL_OK; 3447 } 3448 3449 /* 3450 ** Usage: sqlite3_extended_errcode DB 3451 ** 3452 ** Return the string representation of the most recent sqlite3_* API 3453 ** error code. e.g. "SQLITE_ERROR". 3454 */ 3455 static int test_ex_errcode( 3456 void * clientData, 3457 Tcl_Interp *interp, 3458 int objc, 3459 Tcl_Obj *CONST objv[] 3460 ){ 3461 sqlite3 *db; 3462 int rc; 3463 3464 if( objc!=2 ){ 3465 Tcl_AppendResult(interp, "wrong # args: should be \"", 3466 Tcl_GetString(objv[0]), " DB", 0); 3467 return TCL_ERROR; 3468 } 3469 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 3470 rc = sqlite3_extended_errcode(db); 3471 Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0); 3472 return TCL_OK; 3473 } 3474 3475 3476 /* 3477 ** Usage: sqlite3_errcode DB 3478 ** 3479 ** Return the string representation of the most recent sqlite3_* API 3480 ** error code. e.g. "SQLITE_ERROR". 3481 */ 3482 static int test_errcode( 3483 void * clientData, 3484 Tcl_Interp *interp, 3485 int objc, 3486 Tcl_Obj *CONST objv[] 3487 ){ 3488 sqlite3 *db; 3489 int rc; 3490 3491 if( objc!=2 ){ 3492 Tcl_AppendResult(interp, "wrong # args: should be \"", 3493 Tcl_GetString(objv[0]), " DB", 0); 3494 return TCL_ERROR; 3495 } 3496 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 3497 rc = sqlite3_errcode(db); 3498 Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0); 3499 return TCL_OK; 3500 } 3501 3502 /* 3503 ** Usage: sqlite3_errmsg DB 3504 ** 3505 ** Returns the UTF-8 representation of the error message string for the 3506 ** most recent sqlite3_* API call. 3507 */ 3508 static int test_errmsg( 3509 void * clientData, 3510 Tcl_Interp *interp, 3511 int objc, 3512 Tcl_Obj *CONST objv[] 3513 ){ 3514 sqlite3 *db; 3515 const char *zErr; 3516 3517 if( objc!=2 ){ 3518 Tcl_AppendResult(interp, "wrong # args: should be \"", 3519 Tcl_GetString(objv[0]), " DB", 0); 3520 return TCL_ERROR; 3521 } 3522 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 3523 3524 zErr = sqlite3_errmsg(db); 3525 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1)); 3526 return TCL_OK; 3527 } 3528 3529 /* 3530 ** Usage: test_errmsg16 DB 3531 ** 3532 ** Returns the UTF-16 representation of the error message string for the 3533 ** most recent sqlite3_* API call. This is a byte array object at the TCL 3534 ** level, and it includes the 0x00 0x00 terminator bytes at the end of the 3535 ** UTF-16 string. 3536 */ 3537 static int test_errmsg16( 3538 void * clientData, 3539 Tcl_Interp *interp, 3540 int objc, 3541 Tcl_Obj *CONST objv[] 3542 ){ 3543 #ifndef SQLITE_OMIT_UTF16 3544 sqlite3 *db; 3545 const void *zErr; 3546 const char *z; 3547 int bytes = 0; 3548 3549 if( objc!=2 ){ 3550 Tcl_AppendResult(interp, "wrong # args: should be \"", 3551 Tcl_GetString(objv[0]), " DB", 0); 3552 return TCL_ERROR; 3553 } 3554 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 3555 3556 zErr = sqlite3_errmsg16(db); 3557 if( zErr ){ 3558 z = zErr; 3559 for(bytes=0; z[bytes] || z[bytes+1]; bytes+=2){} 3560 } 3561 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes)); 3562 #endif /* SQLITE_OMIT_UTF16 */ 3563 return TCL_OK; 3564 } 3565 3566 /* 3567 ** Usage: sqlite3_prepare DB sql bytes ?tailvar? 3568 ** 3569 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 3570 ** database handle <DB>. The parameter <tailval> is the name of a global 3571 ** variable that is set to the unused portion of <sql> (if any). A 3572 ** STMT handle is returned. 3573 */ 3574 static int test_prepare( 3575 void * clientData, 3576 Tcl_Interp *interp, 3577 int objc, 3578 Tcl_Obj *CONST objv[] 3579 ){ 3580 sqlite3 *db; 3581 const char *zSql; 3582 int bytes; 3583 const char *zTail = 0; 3584 sqlite3_stmt *pStmt = 0; 3585 char zBuf[50]; 3586 int rc; 3587 3588 if( objc!=5 && objc!=4 ){ 3589 Tcl_AppendResult(interp, "wrong # args: should be \"", 3590 Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0); 3591 return TCL_ERROR; 3592 } 3593 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 3594 zSql = Tcl_GetString(objv[2]); 3595 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 3596 3597 rc = sqlite3_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); 3598 Tcl_ResetResult(interp); 3599 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 3600 if( zTail && objc>=5 ){ 3601 if( bytes>=0 ){ 3602 bytes = bytes - (int)(zTail-zSql); 3603 } 3604 if( (int)strlen(zTail)<bytes ){ 3605 bytes = (int)strlen(zTail); 3606 } 3607 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); 3608 } 3609 if( rc!=SQLITE_OK ){ 3610 assert( pStmt==0 ); 3611 sprintf(zBuf, "(%d) ", rc); 3612 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); 3613 return TCL_ERROR; 3614 } 3615 3616 if( pStmt ){ 3617 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 3618 Tcl_AppendResult(interp, zBuf, 0); 3619 } 3620 return TCL_OK; 3621 } 3622 3623 /* 3624 ** Usage: sqlite3_prepare_v2 DB sql bytes ?tailvar? 3625 ** 3626 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 3627 ** database handle <DB>. The parameter <tailval> is the name of a global 3628 ** variable that is set to the unused portion of <sql> (if any). A 3629 ** STMT handle is returned. 3630 */ 3631 static int test_prepare_v2( 3632 void * clientData, 3633 Tcl_Interp *interp, 3634 int objc, 3635 Tcl_Obj *CONST objv[] 3636 ){ 3637 sqlite3 *db; 3638 const char *zSql; 3639 char *zCopy = 0; /* malloc() copy of zSql */ 3640 int bytes; 3641 const char *zTail = 0; 3642 sqlite3_stmt *pStmt = 0; 3643 char zBuf[50]; 3644 int rc; 3645 3646 if( objc!=5 && objc!=4 ){ 3647 Tcl_AppendResult(interp, "wrong # args: should be \"", 3648 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); 3649 return TCL_ERROR; 3650 } 3651 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 3652 zSql = Tcl_GetString(objv[2]); 3653 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 3654 3655 /* Instead of using zSql directly, make a copy into a buffer obtained 3656 ** directly from malloc(). The idea is to make it easier for valgrind 3657 ** to spot buffer overreads. */ 3658 if( bytes>=0 ){ 3659 zCopy = malloc(bytes); 3660 memcpy(zCopy, zSql, bytes); 3661 }else{ 3662 int n = (int)strlen(zSql) + 1; 3663 zCopy = malloc(n); 3664 memcpy(zCopy, zSql, n); 3665 } 3666 rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, objc>=5 ? &zTail : 0); 3667 free(zCopy); 3668 zTail = &zSql[(zTail - zCopy)]; 3669 3670 assert(rc==SQLITE_OK || pStmt==0); 3671 Tcl_ResetResult(interp); 3672 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 3673 if( rc==SQLITE_OK && zTail && objc>=5 ){ 3674 if( bytes>=0 ){ 3675 bytes = bytes - (int)(zTail-zSql); 3676 } 3677 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); 3678 } 3679 if( rc!=SQLITE_OK ){ 3680 assert( pStmt==0 ); 3681 sprintf(zBuf, "(%d) ", rc); 3682 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); 3683 return TCL_ERROR; 3684 } 3685 3686 if( pStmt ){ 3687 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 3688 Tcl_AppendResult(interp, zBuf, 0); 3689 } 3690 return TCL_OK; 3691 } 3692 3693 /* 3694 ** Usage: sqlite3_prepare_tkt3134 DB 3695 ** 3696 ** Generate a prepared statement for a zero-byte string as a test 3697 ** for ticket #3134. The string should be preceded by a zero byte. 3698 */ 3699 static int test_prepare_tkt3134( 3700 void * clientData, 3701 Tcl_Interp *interp, 3702 int objc, 3703 Tcl_Obj *CONST objv[] 3704 ){ 3705 sqlite3 *db; 3706 static const char zSql[] = "\000SELECT 1"; 3707 sqlite3_stmt *pStmt = 0; 3708 char zBuf[50]; 3709 int rc; 3710 3711 if( objc!=2 ){ 3712 Tcl_AppendResult(interp, "wrong # args: should be \"", 3713 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); 3714 return TCL_ERROR; 3715 } 3716 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 3717 rc = sqlite3_prepare_v2(db, &zSql[1], 0, &pStmt, 0); 3718 assert(rc==SQLITE_OK || pStmt==0); 3719 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 3720 if( rc!=SQLITE_OK ){ 3721 assert( pStmt==0 ); 3722 sprintf(zBuf, "(%d) ", rc); 3723 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); 3724 return TCL_ERROR; 3725 } 3726 3727 if( pStmt ){ 3728 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 3729 Tcl_AppendResult(interp, zBuf, 0); 3730 } 3731 return TCL_OK; 3732 } 3733 3734 /* 3735 ** Usage: sqlite3_prepare16 DB sql bytes tailvar 3736 ** 3737 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 3738 ** database handle <DB>. The parameter <tailval> is the name of a global 3739 ** variable that is set to the unused portion of <sql> (if any). A 3740 ** STMT handle is returned. 3741 */ 3742 static int test_prepare16( 3743 void * clientData, 3744 Tcl_Interp *interp, 3745 int objc, 3746 Tcl_Obj *CONST objv[] 3747 ){ 3748 #ifndef SQLITE_OMIT_UTF16 3749 sqlite3 *db; 3750 const void *zSql; 3751 const void *zTail = 0; 3752 Tcl_Obj *pTail = 0; 3753 sqlite3_stmt *pStmt = 0; 3754 char zBuf[50]; 3755 int rc; 3756 int bytes; /* The integer specified as arg 3 */ 3757 int objlen; /* The byte-array length of arg 2 */ 3758 3759 if( objc!=5 && objc!=4 ){ 3760 Tcl_AppendResult(interp, "wrong # args: should be \"", 3761 Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0); 3762 return TCL_ERROR; 3763 } 3764 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 3765 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen); 3766 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 3767 3768 rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); 3769 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 3770 if( rc ){ 3771 return TCL_ERROR; 3772 } 3773 3774 if( objc>=5 ){ 3775 if( zTail ){ 3776 objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql); 3777 }else{ 3778 objlen = 0; 3779 } 3780 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); 3781 Tcl_IncrRefCount(pTail); 3782 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); 3783 Tcl_DecrRefCount(pTail); 3784 } 3785 3786 if( pStmt ){ 3787 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 3788 } 3789 Tcl_AppendResult(interp, zBuf, 0); 3790 #endif /* SQLITE_OMIT_UTF16 */ 3791 return TCL_OK; 3792 } 3793 3794 /* 3795 ** Usage: sqlite3_prepare16_v2 DB sql bytes ?tailvar? 3796 ** 3797 ** Compile up to <bytes> bytes of the supplied SQL string <sql> using 3798 ** database handle <DB>. The parameter <tailval> is the name of a global 3799 ** variable that is set to the unused portion of <sql> (if any). A 3800 ** STMT handle is returned. 3801 */ 3802 static int test_prepare16_v2( 3803 void * clientData, 3804 Tcl_Interp *interp, 3805 int objc, 3806 Tcl_Obj *CONST objv[] 3807 ){ 3808 #ifndef SQLITE_OMIT_UTF16 3809 sqlite3 *db; 3810 const void *zSql; 3811 const void *zTail = 0; 3812 Tcl_Obj *pTail = 0; 3813 sqlite3_stmt *pStmt = 0; 3814 char zBuf[50]; 3815 int rc; 3816 int bytes; /* The integer specified as arg 3 */ 3817 int objlen; /* The byte-array length of arg 2 */ 3818 3819 if( objc!=5 && objc!=4 ){ 3820 Tcl_AppendResult(interp, "wrong # args: should be \"", 3821 Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0); 3822 return TCL_ERROR; 3823 } 3824 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 3825 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen); 3826 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; 3827 3828 rc = sqlite3_prepare16_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); 3829 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; 3830 if( rc ){ 3831 return TCL_ERROR; 3832 } 3833 3834 if( objc>=5 ){ 3835 if( zTail ){ 3836 objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql); 3837 }else{ 3838 objlen = 0; 3839 } 3840 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); 3841 Tcl_IncrRefCount(pTail); 3842 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); 3843 Tcl_DecrRefCount(pTail); 3844 } 3845 3846 if( pStmt ){ 3847 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; 3848 } 3849 Tcl_AppendResult(interp, zBuf, 0); 3850 #endif /* SQLITE_OMIT_UTF16 */ 3851 return TCL_OK; 3852 } 3853 3854 /* 3855 ** Usage: sqlite3_open filename ?options-list? 3856 */ 3857 static int test_open( 3858 void * clientData, 3859 Tcl_Interp *interp, 3860 int objc, 3861 Tcl_Obj *CONST objv[] 3862 ){ 3863 const char *zFilename; 3864 sqlite3 *db; 3865 char zBuf[100]; 3866 3867 if( objc!=3 && objc!=2 && objc!=1 ){ 3868 Tcl_AppendResult(interp, "wrong # args: should be \"", 3869 Tcl_GetString(objv[0]), " filename options-list", 0); 3870 return TCL_ERROR; 3871 } 3872 3873 zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0; 3874 sqlite3_open(zFilename, &db); 3875 3876 if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR; 3877 Tcl_AppendResult(interp, zBuf, 0); 3878 return TCL_OK; 3879 } 3880 3881 /* 3882 ** Usage: sqlite3_open_v2 FILENAME FLAGS VFS 3883 */ 3884 static int test_open_v2( 3885 void * clientData, 3886 Tcl_Interp *interp, 3887 int objc, 3888 Tcl_Obj *CONST objv[] 3889 ){ 3890 const char *zFilename; 3891 const char *zVfs; 3892 int flags = 0; 3893 sqlite3 *db; 3894 int rc; 3895 char zBuf[100]; 3896 3897 int nFlag; 3898 Tcl_Obj **apFlag; 3899 int i; 3900 3901 if( objc!=4 ){ 3902 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS"); 3903 return TCL_ERROR; 3904 } 3905 zFilename = Tcl_GetString(objv[1]); 3906 zVfs = Tcl_GetString(objv[3]); 3907 if( zVfs[0]==0x00 ) zVfs = 0; 3908 3909 rc = Tcl_ListObjGetElements(interp, objv[2], &nFlag, &apFlag); 3910 if( rc!=TCL_OK ) return rc; 3911 for(i=0; i<nFlag; i++){ 3912 int iFlag; 3913 struct OpenFlag { 3914 const char *zFlag; 3915 int flag; 3916 } aFlag[] = { 3917 { "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY }, 3918 { "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE }, 3919 { "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE }, 3920 { "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE }, 3921 { "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE }, 3922 { "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY }, 3923 { "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB }, 3924 { "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB }, 3925 { "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB }, 3926 { "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL }, 3927 { "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL }, 3928 { "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL }, 3929 { "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL }, 3930 { "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX }, 3931 { "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX }, 3932 { "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE }, 3933 { "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE }, 3934 { "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL }, 3935 { "SQLITE_OPEN_URI", SQLITE_OPEN_URI }, 3936 { 0, 0 } 3937 }; 3938 rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]), 3939 "flag", 0, &iFlag 3940 ); 3941 if( rc!=TCL_OK ) return rc; 3942 flags |= aFlag[iFlag].flag; 3943 } 3944 3945 rc = sqlite3_open_v2(zFilename, &db, flags, zVfs); 3946 if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR; 3947 Tcl_AppendResult(interp, zBuf, 0); 3948 return TCL_OK; 3949 } 3950 3951 /* 3952 ** Usage: sqlite3_open16 filename options 3953 */ 3954 static int test_open16( 3955 void * clientData, 3956 Tcl_Interp *interp, 3957 int objc, 3958 Tcl_Obj *CONST objv[] 3959 ){ 3960 #ifndef SQLITE_OMIT_UTF16 3961 const void *zFilename; 3962 sqlite3 *db; 3963 char zBuf[100]; 3964 3965 if( objc!=3 ){ 3966 Tcl_AppendResult(interp, "wrong # args: should be \"", 3967 Tcl_GetString(objv[0]), " filename options-list", 0); 3968 return TCL_ERROR; 3969 } 3970 3971 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0); 3972 sqlite3_open16(zFilename, &db); 3973 3974 if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR; 3975 Tcl_AppendResult(interp, zBuf, 0); 3976 #endif /* SQLITE_OMIT_UTF16 */ 3977 return TCL_OK; 3978 } 3979 3980 /* 3981 ** Usage: sqlite3_complete16 <UTF-16 string> 3982 ** 3983 ** Return 1 if the supplied argument is a complete SQL statement, or zero 3984 ** otherwise. 3985 */ 3986 static int test_complete16( 3987 void * clientData, 3988 Tcl_Interp *interp, 3989 int objc, 3990 Tcl_Obj *CONST objv[] 3991 ){ 3992 #if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16) 3993 char *zBuf; 3994 3995 if( objc!=2 ){ 3996 Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>"); 3997 return TCL_ERROR; 3998 } 3999 4000 zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0); 4001 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf))); 4002 #endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */ 4003 return TCL_OK; 4004 } 4005 4006 /* 4007 ** Usage: sqlite3_step STMT 4008 ** 4009 ** Advance the statement to the next row. 4010 */ 4011 static int test_step( 4012 void * clientData, 4013 Tcl_Interp *interp, 4014 int objc, 4015 Tcl_Obj *CONST objv[] 4016 ){ 4017 sqlite3_stmt *pStmt; 4018 int rc; 4019 4020 if( objc!=2 ){ 4021 Tcl_AppendResult(interp, "wrong # args: should be \"", 4022 Tcl_GetString(objv[0]), " STMT", 0); 4023 return TCL_ERROR; 4024 } 4025 4026 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 4027 rc = sqlite3_step(pStmt); 4028 4029 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */ 4030 Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); 4031 return TCL_OK; 4032 } 4033 4034 static int test_sql( 4035 void * clientData, 4036 Tcl_Interp *interp, 4037 int objc, 4038 Tcl_Obj *CONST objv[] 4039 ){ 4040 sqlite3_stmt *pStmt; 4041 4042 if( objc!=2 ){ 4043 Tcl_WrongNumArgs(interp, 1, objv, "STMT"); 4044 return TCL_ERROR; 4045 } 4046 4047 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 4048 Tcl_SetResult(interp, (char *)sqlite3_sql(pStmt), TCL_VOLATILE); 4049 return TCL_OK; 4050 } 4051 4052 /* 4053 ** Usage: sqlite3_column_count STMT 4054 ** 4055 ** Return the number of columns returned by the sql statement STMT. 4056 */ 4057 static int test_column_count( 4058 void * clientData, 4059 Tcl_Interp *interp, 4060 int objc, 4061 Tcl_Obj *CONST objv[] 4062 ){ 4063 sqlite3_stmt *pStmt; 4064 4065 if( objc!=2 ){ 4066 Tcl_AppendResult(interp, "wrong # args: should be \"", 4067 Tcl_GetString(objv[0]), " STMT column", 0); 4068 return TCL_ERROR; 4069 } 4070 4071 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 4072 4073 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt))); 4074 return TCL_OK; 4075 } 4076 4077 /* 4078 ** Usage: sqlite3_column_type STMT column 4079 ** 4080 ** Return the type of the data in column 'column' of the current row. 4081 */ 4082 static int test_column_type( 4083 void * clientData, 4084 Tcl_Interp *interp, 4085 int objc, 4086 Tcl_Obj *CONST objv[] 4087 ){ 4088 sqlite3_stmt *pStmt; 4089 int col; 4090 int tp; 4091 4092 if( objc!=3 ){ 4093 Tcl_AppendResult(interp, "wrong # args: should be \"", 4094 Tcl_GetString(objv[0]), " STMT column", 0); 4095 return TCL_ERROR; 4096 } 4097 4098 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 4099 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 4100 4101 tp = sqlite3_column_type(pStmt, col); 4102 switch( tp ){ 4103 case SQLITE_INTEGER: 4104 Tcl_SetResult(interp, "INTEGER", TCL_STATIC); 4105 break; 4106 case SQLITE_NULL: 4107 Tcl_SetResult(interp, "NULL", TCL_STATIC); 4108 break; 4109 case SQLITE_FLOAT: 4110 Tcl_SetResult(interp, "FLOAT", TCL_STATIC); 4111 break; 4112 case SQLITE_TEXT: 4113 Tcl_SetResult(interp, "TEXT", TCL_STATIC); 4114 break; 4115 case SQLITE_BLOB: 4116 Tcl_SetResult(interp, "BLOB", TCL_STATIC); 4117 break; 4118 default: 4119 assert(0); 4120 } 4121 4122 return TCL_OK; 4123 } 4124 4125 /* 4126 ** Usage: sqlite3_column_int64 STMT column 4127 ** 4128 ** Return the data in column 'column' of the current row cast as an 4129 ** wide (64-bit) integer. 4130 */ 4131 static int test_column_int64( 4132 void * clientData, 4133 Tcl_Interp *interp, 4134 int objc, 4135 Tcl_Obj *CONST objv[] 4136 ){ 4137 sqlite3_stmt *pStmt; 4138 int col; 4139 i64 iVal; 4140 4141 if( objc!=3 ){ 4142 Tcl_AppendResult(interp, "wrong # args: should be \"", 4143 Tcl_GetString(objv[0]), " STMT column", 0); 4144 return TCL_ERROR; 4145 } 4146 4147 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 4148 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 4149 4150 iVal = sqlite3_column_int64(pStmt, col); 4151 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal)); 4152 return TCL_OK; 4153 } 4154 4155 /* 4156 ** Usage: sqlite3_column_blob STMT column 4157 */ 4158 static int test_column_blob( 4159 void * clientData, 4160 Tcl_Interp *interp, 4161 int objc, 4162 Tcl_Obj *CONST objv[] 4163 ){ 4164 sqlite3_stmt *pStmt; 4165 int col; 4166 4167 int len; 4168 const void *pBlob; 4169 4170 if( objc!=3 ){ 4171 Tcl_AppendResult(interp, "wrong # args: should be \"", 4172 Tcl_GetString(objv[0]), " STMT column", 0); 4173 return TCL_ERROR; 4174 } 4175 4176 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 4177 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 4178 4179 len = sqlite3_column_bytes(pStmt, col); 4180 pBlob = sqlite3_column_blob(pStmt, col); 4181 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len)); 4182 return TCL_OK; 4183 } 4184 4185 /* 4186 ** Usage: sqlite3_column_double STMT column 4187 ** 4188 ** Return the data in column 'column' of the current row cast as a double. 4189 */ 4190 static int test_column_double( 4191 void * clientData, 4192 Tcl_Interp *interp, 4193 int objc, 4194 Tcl_Obj *CONST objv[] 4195 ){ 4196 sqlite3_stmt *pStmt; 4197 int col; 4198 double rVal; 4199 4200 if( objc!=3 ){ 4201 Tcl_AppendResult(interp, "wrong # args: should be \"", 4202 Tcl_GetString(objv[0]), " STMT column", 0); 4203 return TCL_ERROR; 4204 } 4205 4206 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 4207 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 4208 4209 rVal = sqlite3_column_double(pStmt, col); 4210 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal)); 4211 return TCL_OK; 4212 } 4213 4214 /* 4215 ** Usage: sqlite3_data_count STMT 4216 ** 4217 ** Return the number of columns returned by the sql statement STMT. 4218 */ 4219 static int test_data_count( 4220 void * clientData, 4221 Tcl_Interp *interp, 4222 int objc, 4223 Tcl_Obj *CONST objv[] 4224 ){ 4225 sqlite3_stmt *pStmt; 4226 4227 if( objc!=2 ){ 4228 Tcl_AppendResult(interp, "wrong # args: should be \"", 4229 Tcl_GetString(objv[0]), " STMT column", 0); 4230 return TCL_ERROR; 4231 } 4232 4233 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 4234 4235 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt))); 4236 return TCL_OK; 4237 } 4238 4239 /* 4240 ** Usage: sqlite3_column_text STMT column 4241 ** 4242 ** Usage: sqlite3_column_decltype STMT column 4243 ** 4244 ** Usage: sqlite3_column_name STMT column 4245 */ 4246 static int test_stmt_utf8( 4247 void * clientData, /* Pointer to SQLite API function to be invoke */ 4248 Tcl_Interp *interp, 4249 int objc, 4250 Tcl_Obj *CONST objv[] 4251 ){ 4252 sqlite3_stmt *pStmt; 4253 int col; 4254 const char *(*xFunc)(sqlite3_stmt*, int); 4255 const char *zRet; 4256 4257 xFunc = (const char *(*)(sqlite3_stmt*, int))clientData; 4258 if( objc!=3 ){ 4259 Tcl_AppendResult(interp, "wrong # args: should be \"", 4260 Tcl_GetString(objv[0]), " STMT column", 0); 4261 return TCL_ERROR; 4262 } 4263 4264 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 4265 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 4266 zRet = xFunc(pStmt, col); 4267 if( zRet ){ 4268 Tcl_SetResult(interp, (char *)zRet, 0); 4269 } 4270 return TCL_OK; 4271 } 4272 4273 static int test_global_recover( 4274 void * clientData, 4275 Tcl_Interp *interp, 4276 int objc, 4277 Tcl_Obj *CONST objv[] 4278 ){ 4279 #ifndef SQLITE_OMIT_DEPRECATED 4280 int rc; 4281 if( objc!=1 ){ 4282 Tcl_WrongNumArgs(interp, 1, objv, ""); 4283 return TCL_ERROR; 4284 } 4285 rc = sqlite3_global_recover(); 4286 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 4287 #endif 4288 return TCL_OK; 4289 } 4290 4291 /* 4292 ** Usage: sqlite3_column_text STMT column 4293 ** 4294 ** Usage: sqlite3_column_decltype STMT column 4295 ** 4296 ** Usage: sqlite3_column_name STMT column 4297 */ 4298 static int test_stmt_utf16( 4299 void * clientData, /* Pointer to SQLite API function to be invoked */ 4300 Tcl_Interp *interp, 4301 int objc, 4302 Tcl_Obj *CONST objv[] 4303 ){ 4304 #ifndef SQLITE_OMIT_UTF16 4305 sqlite3_stmt *pStmt; 4306 int col; 4307 Tcl_Obj *pRet; 4308 const void *zName16; 4309 const void *(*xFunc)(sqlite3_stmt*, int); 4310 4311 xFunc = (const void *(*)(sqlite3_stmt*, int))clientData; 4312 if( objc!=3 ){ 4313 Tcl_AppendResult(interp, "wrong # args: should be \"", 4314 Tcl_GetString(objv[0]), " STMT column", 0); 4315 return TCL_ERROR; 4316 } 4317 4318 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 4319 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 4320 4321 zName16 = xFunc(pStmt, col); 4322 if( zName16 ){ 4323 int n; 4324 const char *z = zName16; 4325 for(n=0; z[n] || z[n+1]; n+=2){} 4326 pRet = Tcl_NewByteArrayObj(zName16, n+2); 4327 Tcl_SetObjResult(interp, pRet); 4328 } 4329 #endif /* SQLITE_OMIT_UTF16 */ 4330 4331 return TCL_OK; 4332 } 4333 4334 /* 4335 ** Usage: sqlite3_column_int STMT column 4336 ** 4337 ** Usage: sqlite3_column_bytes STMT column 4338 ** 4339 ** Usage: sqlite3_column_bytes16 STMT column 4340 ** 4341 */ 4342 static int test_stmt_int( 4343 void * clientData, /* Pointer to SQLite API function to be invoked */ 4344 Tcl_Interp *interp, 4345 int objc, 4346 Tcl_Obj *CONST objv[] 4347 ){ 4348 sqlite3_stmt *pStmt; 4349 int col; 4350 int (*xFunc)(sqlite3_stmt*, int); 4351 4352 xFunc = (int (*)(sqlite3_stmt*, int))clientData; 4353 if( objc!=3 ){ 4354 Tcl_AppendResult(interp, "wrong # args: should be \"", 4355 Tcl_GetString(objv[0]), " STMT column", 0); 4356 return TCL_ERROR; 4357 } 4358 4359 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 4360 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; 4361 4362 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col))); 4363 return TCL_OK; 4364 } 4365 4366 /* 4367 ** Usage: sqlite_set_magic DB MAGIC-NUMBER 4368 ** 4369 ** Set the db->magic value. This is used to test error recovery logic. 4370 */ 4371 static int sqlite_set_magic( 4372 void * clientData, 4373 Tcl_Interp *interp, 4374 int argc, 4375 char **argv 4376 ){ 4377 sqlite3 *db; 4378 if( argc!=3 ){ 4379 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 4380 " DB MAGIC", 0); 4381 return TCL_ERROR; 4382 } 4383 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 4384 if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){ 4385 db->magic = SQLITE_MAGIC_OPEN; 4386 }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){ 4387 db->magic = SQLITE_MAGIC_CLOSED; 4388 }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){ 4389 db->magic = SQLITE_MAGIC_BUSY; 4390 }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){ 4391 db->magic = SQLITE_MAGIC_ERROR; 4392 }else if( Tcl_GetInt(interp, argv[2], (int*)&db->magic) ){ 4393 return TCL_ERROR; 4394 } 4395 return TCL_OK; 4396 } 4397 4398 /* 4399 ** Usage: sqlite3_interrupt DB 4400 ** 4401 ** Trigger an interrupt on DB 4402 */ 4403 static int test_interrupt( 4404 void * clientData, 4405 Tcl_Interp *interp, 4406 int argc, 4407 char **argv 4408 ){ 4409 sqlite3 *db; 4410 if( argc!=2 ){ 4411 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0); 4412 return TCL_ERROR; 4413 } 4414 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 4415 sqlite3_interrupt(db); 4416 return TCL_OK; 4417 } 4418 4419 static u8 *sqlite3_stack_baseline = 0; 4420 4421 /* 4422 ** Fill the stack with a known bitpattern. 4423 */ 4424 static void prepStack(void){ 4425 int i; 4426 u32 bigBuf[65536]; 4427 for(i=0; i<sizeof(bigBuf)/sizeof(bigBuf[0]); i++) bigBuf[i] = 0xdeadbeef; 4428 sqlite3_stack_baseline = (u8*)&bigBuf[65536]; 4429 } 4430 4431 /* 4432 ** Get the current stack depth. Used for debugging only. 4433 */ 4434 u64 sqlite3StackDepth(void){ 4435 u8 x; 4436 return (u64)(sqlite3_stack_baseline - &x); 4437 } 4438 4439 /* 4440 ** Usage: sqlite3_stack_used DB SQL 4441 ** 4442 ** Try to measure the amount of stack space used by a call to sqlite3_exec 4443 */ 4444 static int test_stack_used( 4445 void * clientData, 4446 Tcl_Interp *interp, 4447 int argc, 4448 char **argv 4449 ){ 4450 sqlite3 *db; 4451 int i; 4452 if( argc!=3 ){ 4453 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 4454 " DB SQL", 0); 4455 return TCL_ERROR; 4456 } 4457 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 4458 prepStack(); 4459 (void)sqlite3_exec(db, argv[2], 0, 0, 0); 4460 for(i=65535; i>=0 && ((u32*)sqlite3_stack_baseline)[-i]==0xdeadbeef; i--){} 4461 Tcl_SetObjResult(interp, Tcl_NewIntObj(i*4)); 4462 return TCL_OK; 4463 } 4464 4465 /* 4466 ** Usage: sqlite_delete_function DB function-name 4467 ** 4468 ** Delete the user function 'function-name' from database handle DB. It 4469 ** is assumed that the user function was created as UTF8, any number of 4470 ** arguments (the way the TCL interface does it). 4471 */ 4472 static int delete_function( 4473 void * clientData, 4474 Tcl_Interp *interp, 4475 int argc, 4476 char **argv 4477 ){ 4478 int rc; 4479 sqlite3 *db; 4480 if( argc!=3 ){ 4481 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 4482 " DB function-name", 0); 4483 return TCL_ERROR; 4484 } 4485 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 4486 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0); 4487 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 4488 return TCL_OK; 4489 } 4490 4491 /* 4492 ** Usage: sqlite_delete_collation DB collation-name 4493 ** 4494 ** Delete the collation sequence 'collation-name' from database handle 4495 ** DB. It is assumed that the collation sequence was created as UTF8 (the 4496 ** way the TCL interface does it). 4497 */ 4498 static int delete_collation( 4499 void * clientData, 4500 Tcl_Interp *interp, 4501 int argc, 4502 char **argv 4503 ){ 4504 int rc; 4505 sqlite3 *db; 4506 if( argc!=3 ){ 4507 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 4508 " DB function-name", 0); 4509 return TCL_ERROR; 4510 } 4511 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 4512 rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0); 4513 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 4514 return TCL_OK; 4515 } 4516 4517 /* 4518 ** Usage: sqlite3_get_autocommit DB 4519 ** 4520 ** Return true if the database DB is currently in auto-commit mode. 4521 ** Return false if not. 4522 */ 4523 static int get_autocommit( 4524 void * clientData, 4525 Tcl_Interp *interp, 4526 int argc, 4527 char **argv 4528 ){ 4529 char zBuf[30]; 4530 sqlite3 *db; 4531 if( argc!=2 ){ 4532 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 4533 " DB", 0); 4534 return TCL_ERROR; 4535 } 4536 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 4537 sprintf(zBuf, "%d", sqlite3_get_autocommit(db)); 4538 Tcl_AppendResult(interp, zBuf, 0); 4539 return TCL_OK; 4540 } 4541 4542 /* 4543 ** Usage: sqlite3_busy_timeout DB MS 4544 ** 4545 ** Set the busy timeout. This is more easily done using the timeout 4546 ** method of the TCL interface. But we need a way to test the case 4547 ** where it returns SQLITE_MISUSE. 4548 */ 4549 static int test_busy_timeout( 4550 void * clientData, 4551 Tcl_Interp *interp, 4552 int argc, 4553 char **argv 4554 ){ 4555 int rc, ms; 4556 sqlite3 *db; 4557 if( argc!=3 ){ 4558 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 4559 " DB", 0); 4560 return TCL_ERROR; 4561 } 4562 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; 4563 if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR; 4564 rc = sqlite3_busy_timeout(db, ms); 4565 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); 4566 return TCL_OK; 4567 } 4568 4569 /* 4570 ** Usage: tcl_variable_type VARIABLENAME 4571 ** 4572 ** Return the name of the internal representation for the 4573 ** value of the given variable. 4574 */ 4575 static int tcl_variable_type( 4576 void * clientData, 4577 Tcl_Interp *interp, 4578 int objc, 4579 Tcl_Obj *CONST objv[] 4580 ){ 4581 Tcl_Obj *pVar; 4582 if( objc!=2 ){ 4583 Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE"); 4584 return TCL_ERROR; 4585 } 4586 pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG); 4587 if( pVar==0 ) return TCL_ERROR; 4588 if( pVar->typePtr ){ 4589 Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1)); 4590 } 4591 return TCL_OK; 4592 } 4593 4594 /* 4595 ** Usage: sqlite3_release_memory ?N? 4596 ** 4597 ** Attempt to release memory currently held but not actually required. 4598 ** The integer N is the number of bytes we are trying to release. The 4599 ** return value is the amount of memory actually released. 4600 */ 4601 static int test_release_memory( 4602 void * clientData, 4603 Tcl_Interp *interp, 4604 int objc, 4605 Tcl_Obj *CONST objv[] 4606 ){ 4607 #if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO) 4608 int N; 4609 int amt; 4610 if( objc!=1 && objc!=2 ){ 4611 Tcl_WrongNumArgs(interp, 1, objv, "?N?"); 4612 return TCL_ERROR; 4613 } 4614 if( objc==2 ){ 4615 if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR; 4616 }else{ 4617 N = -1; 4618 } 4619 amt = sqlite3_release_memory(N); 4620 Tcl_SetObjResult(interp, Tcl_NewIntObj(amt)); 4621 #endif 4622 return TCL_OK; 4623 } 4624 4625 4626 /* 4627 ** Usage: sqlite3_db_release_memory DB 4628 ** 4629 ** Attempt to release memory currently held by database DB. Return the 4630 ** result code (which in the current implementation is always zero). 4631 */ 4632 static int test_db_release_memory( 4633 void * clientData, 4634 Tcl_Interp *interp, 4635 int objc, 4636 Tcl_Obj *CONST objv[] 4637 ){ 4638 sqlite3 *db; 4639 int rc; 4640 if( objc!=2 ){ 4641 Tcl_WrongNumArgs(interp, 1, objv, "DB"); 4642 return TCL_ERROR; 4643 } 4644 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 4645 rc = sqlite3_db_release_memory(db); 4646 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 4647 return TCL_OK; 4648 } 4649 4650 /* 4651 ** Usage: sqlite3_db_filename DB DBNAME 4652 ** 4653 ** Return the name of a file associated with a database. 4654 */ 4655 static int test_db_filename( 4656 void * clientData, 4657 Tcl_Interp *interp, 4658 int objc, 4659 Tcl_Obj *CONST objv[] 4660 ){ 4661 sqlite3 *db; 4662 const char *zDbName; 4663 if( objc!=3 ){ 4664 Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME"); 4665 return TCL_ERROR; 4666 } 4667 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 4668 zDbName = Tcl_GetString(objv[2]); 4669 Tcl_AppendResult(interp, sqlite3_db_filename(db, zDbName), (void*)0); 4670 return TCL_OK; 4671 } 4672 4673 /* 4674 ** Usage: sqlite3_db_readonly DB DBNAME 4675 ** 4676 ** Return 1 or 0 if DBNAME is readonly or not. Return -1 if DBNAME does 4677 ** not exist. 4678 */ 4679 static int test_db_readonly( 4680 void * clientData, 4681 Tcl_Interp *interp, 4682 int objc, 4683 Tcl_Obj *CONST objv[] 4684 ){ 4685 sqlite3 *db; 4686 const char *zDbName; 4687 if( objc!=3 ){ 4688 Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME"); 4689 return TCL_ERROR; 4690 } 4691 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 4692 zDbName = Tcl_GetString(objv[2]); 4693 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_db_readonly(db, zDbName))); 4694 return TCL_OK; 4695 } 4696 4697 /* 4698 ** Usage: sqlite3_soft_heap_limit ?N? 4699 ** 4700 ** Query or set the soft heap limit for the current thread. The 4701 ** limit is only changed if the N is present. The previous limit 4702 ** is returned. 4703 */ 4704 static int test_soft_heap_limit( 4705 void * clientData, 4706 Tcl_Interp *interp, 4707 int objc, 4708 Tcl_Obj *CONST objv[] 4709 ){ 4710 sqlite3_int64 amt; 4711 Tcl_WideInt N = -1; 4712 if( objc!=1 && objc!=2 ){ 4713 Tcl_WrongNumArgs(interp, 1, objv, "?N?"); 4714 return TCL_ERROR; 4715 } 4716 if( objc==2 ){ 4717 if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR; 4718 } 4719 amt = sqlite3_soft_heap_limit64(N); 4720 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt)); 4721 return TCL_OK; 4722 } 4723 4724 /* 4725 ** Usage: sqlite3_thread_cleanup 4726 ** 4727 ** Call the sqlite3_thread_cleanup API. 4728 */ 4729 static int test_thread_cleanup( 4730 void * clientData, 4731 Tcl_Interp *interp, 4732 int objc, 4733 Tcl_Obj *CONST objv[] 4734 ){ 4735 #ifndef SQLITE_OMIT_DEPRECATED 4736 sqlite3_thread_cleanup(); 4737 #endif 4738 return TCL_OK; 4739 } 4740 4741 /* 4742 ** Usage: sqlite3_pager_refcounts DB 4743 ** 4744 ** Return a list of numbers which are the PagerRefcount for all 4745 ** pagers on each database connection. 4746 */ 4747 static int test_pager_refcounts( 4748 void * clientData, 4749 Tcl_Interp *interp, 4750 int objc, 4751 Tcl_Obj *CONST objv[] 4752 ){ 4753 sqlite3 *db; 4754 int i; 4755 int v, *a; 4756 Tcl_Obj *pResult; 4757 4758 if( objc!=2 ){ 4759 Tcl_AppendResult(interp, "wrong # args: should be \"", 4760 Tcl_GetStringFromObj(objv[0], 0), " DB", 0); 4761 return TCL_ERROR; 4762 } 4763 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 4764 pResult = Tcl_NewObj(); 4765 for(i=0; i<db->nDb; i++){ 4766 if( db->aDb[i].pBt==0 ){ 4767 v = -1; 4768 }else{ 4769 sqlite3_mutex_enter(db->mutex); 4770 a = sqlite3PagerStats(sqlite3BtreePager(db->aDb[i].pBt)); 4771 v = a[0]; 4772 sqlite3_mutex_leave(db->mutex); 4773 } 4774 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(v)); 4775 } 4776 Tcl_SetObjResult(interp, pResult); 4777 return TCL_OK; 4778 } 4779 4780 4781 /* 4782 ** tclcmd: working_64bit_int 4783 ** 4784 ** Some TCL builds (ex: cygwin) do not support 64-bit integers. This 4785 ** leads to a number of test failures. The present command checks the 4786 ** TCL build to see whether or not it supports 64-bit integers. It 4787 ** returns TRUE if it does and FALSE if not. 4788 ** 4789 ** This command is used to warn users that their TCL build is defective 4790 ** and that the errors they are seeing in the test scripts might be 4791 ** a result of their defective TCL rather than problems in SQLite. 4792 */ 4793 static int working_64bit_int( 4794 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 4795 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 4796 int objc, /* Number of arguments */ 4797 Tcl_Obj *CONST objv[] /* Command arguments */ 4798 ){ 4799 Tcl_Obj *pTestObj; 4800 int working = 0; 4801 4802 pTestObj = Tcl_NewWideIntObj(1000000*(i64)1234567890); 4803 working = strcmp(Tcl_GetString(pTestObj), "1234567890000000")==0; 4804 Tcl_DecrRefCount(pTestObj); 4805 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(working)); 4806 return TCL_OK; 4807 } 4808 4809 4810 /* 4811 ** tclcmd: vfs_unlink_test 4812 ** 4813 ** This TCL command unregisters the primary VFS and then registers 4814 ** it back again. This is used to test the ability to register a 4815 ** VFS when none are previously registered, and the ability to 4816 ** unregister the only available VFS. Ticket #2738 4817 */ 4818 static int vfs_unlink_test( 4819 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 4820 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 4821 int objc, /* Number of arguments */ 4822 Tcl_Obj *CONST objv[] /* Command arguments */ 4823 ){ 4824 int i; 4825 sqlite3_vfs *pMain; 4826 sqlite3_vfs *apVfs[20]; 4827 sqlite3_vfs one, two; 4828 4829 sqlite3_vfs_unregister(0); /* Unregister of NULL is harmless */ 4830 one.zName = "__one"; 4831 two.zName = "__two"; 4832 4833 /* Calling sqlite3_vfs_register with 2nd argument of 0 does not 4834 ** change the default VFS 4835 */ 4836 pMain = sqlite3_vfs_find(0); 4837 sqlite3_vfs_register(&one, 0); 4838 assert( pMain==0 || pMain==sqlite3_vfs_find(0) ); 4839 sqlite3_vfs_register(&two, 0); 4840 assert( pMain==0 || pMain==sqlite3_vfs_find(0) ); 4841 4842 /* We can find a VFS by its name */ 4843 assert( sqlite3_vfs_find("__one")==&one ); 4844 assert( sqlite3_vfs_find("__two")==&two ); 4845 4846 /* Calling sqlite_vfs_register with non-zero second parameter changes the 4847 ** default VFS, even if the 1st parameter is an existig VFS that is 4848 ** previously registered as the non-default. 4849 */ 4850 sqlite3_vfs_register(&one, 1); 4851 assert( sqlite3_vfs_find("__one")==&one ); 4852 assert( sqlite3_vfs_find("__two")==&two ); 4853 assert( sqlite3_vfs_find(0)==&one ); 4854 sqlite3_vfs_register(&two, 1); 4855 assert( sqlite3_vfs_find("__one")==&one ); 4856 assert( sqlite3_vfs_find("__two")==&two ); 4857 assert( sqlite3_vfs_find(0)==&two ); 4858 if( pMain ){ 4859 sqlite3_vfs_register(pMain, 1); 4860 assert( sqlite3_vfs_find("__one")==&one ); 4861 assert( sqlite3_vfs_find("__two")==&two ); 4862 assert( sqlite3_vfs_find(0)==pMain ); 4863 } 4864 4865 /* Unlink the default VFS. Repeat until there are no more VFSes 4866 ** registered. 4867 */ 4868 for(i=0; i<sizeof(apVfs)/sizeof(apVfs[0]); i++){ 4869 apVfs[i] = sqlite3_vfs_find(0); 4870 if( apVfs[i] ){ 4871 assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) ); 4872 sqlite3_vfs_unregister(apVfs[i]); 4873 assert( 0==sqlite3_vfs_find(apVfs[i]->zName) ); 4874 } 4875 } 4876 assert( 0==sqlite3_vfs_find(0) ); 4877 4878 /* Register the main VFS as non-default (will be made default, since 4879 ** it'll be the only one in existence). 4880 */ 4881 sqlite3_vfs_register(pMain, 0); 4882 assert( sqlite3_vfs_find(0)==pMain ); 4883 4884 /* Un-register the main VFS again to restore an empty VFS list */ 4885 sqlite3_vfs_unregister(pMain); 4886 assert( 0==sqlite3_vfs_find(0) ); 4887 4888 /* Relink all VFSes in reverse order. */ 4889 for(i=sizeof(apVfs)/sizeof(apVfs[0])-1; i>=0; i--){ 4890 if( apVfs[i] ){ 4891 sqlite3_vfs_register(apVfs[i], 1); 4892 assert( apVfs[i]==sqlite3_vfs_find(0) ); 4893 assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) ); 4894 } 4895 } 4896 4897 /* Unregister out sample VFSes. */ 4898 sqlite3_vfs_unregister(&one); 4899 sqlite3_vfs_unregister(&two); 4900 4901 /* Unregistering a VFS that is not currently registered is harmless */ 4902 sqlite3_vfs_unregister(&one); 4903 sqlite3_vfs_unregister(&two); 4904 assert( sqlite3_vfs_find("__one")==0 ); 4905 assert( sqlite3_vfs_find("__two")==0 ); 4906 4907 /* We should be left with the original default VFS back as the 4908 ** original */ 4909 assert( sqlite3_vfs_find(0)==pMain ); 4910 4911 return TCL_OK; 4912 } 4913 4914 /* 4915 ** tclcmd: vfs_initfail_test 4916 ** 4917 ** This TCL command attempts to vfs_find and vfs_register when the 4918 ** sqlite3_initialize() interface is failing. All calls should fail. 4919 */ 4920 static int vfs_initfail_test( 4921 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 4922 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 4923 int objc, /* Number of arguments */ 4924 Tcl_Obj *CONST objv[] /* Command arguments */ 4925 ){ 4926 sqlite3_vfs one; 4927 one.zName = "__one"; 4928 4929 if( sqlite3_vfs_find(0) ) return TCL_ERROR; 4930 sqlite3_vfs_register(&one, 0); 4931 if( sqlite3_vfs_find(0) ) return TCL_ERROR; 4932 sqlite3_vfs_register(&one, 1); 4933 if( sqlite3_vfs_find(0) ) return TCL_ERROR; 4934 return TCL_OK; 4935 } 4936 4937 /* 4938 ** Saved VFSes 4939 */ 4940 static sqlite3_vfs *apVfs[20]; 4941 static int nVfs = 0; 4942 4943 /* 4944 ** tclcmd: vfs_unregister_all 4945 ** 4946 ** Unregister all VFSes. 4947 */ 4948 static int vfs_unregister_all( 4949 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 4950 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 4951 int objc, /* Number of arguments */ 4952 Tcl_Obj *CONST objv[] /* Command arguments */ 4953 ){ 4954 int i; 4955 for(i=0; i<ArraySize(apVfs); i++){ 4956 apVfs[i] = sqlite3_vfs_find(0); 4957 if( apVfs[i]==0 ) break; 4958 sqlite3_vfs_unregister(apVfs[i]); 4959 } 4960 nVfs = i; 4961 return TCL_OK; 4962 } 4963 /* 4964 ** tclcmd: vfs_reregister_all 4965 ** 4966 ** Restore all VFSes that were removed using vfs_unregister_all 4967 */ 4968 static int vfs_reregister_all( 4969 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 4970 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 4971 int objc, /* Number of arguments */ 4972 Tcl_Obj *CONST objv[] /* Command arguments */ 4973 ){ 4974 int i; 4975 for(i=0; i<nVfs; i++){ 4976 sqlite3_vfs_register(apVfs[i], i==0); 4977 } 4978 return TCL_OK; 4979 } 4980 4981 4982 /* 4983 ** tclcmd: file_control_test DB 4984 ** 4985 ** This TCL command runs the sqlite3_file_control interface and 4986 ** verifies correct operation of the same. 4987 */ 4988 static int file_control_test( 4989 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 4990 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 4991 int objc, /* Number of arguments */ 4992 Tcl_Obj *CONST objv[] /* Command arguments */ 4993 ){ 4994 int iArg = 0; 4995 sqlite3 *db; 4996 int rc; 4997 4998 if( objc!=2 ){ 4999 Tcl_AppendResult(interp, "wrong # args: should be \"", 5000 Tcl_GetStringFromObj(objv[0], 0), " DB", 0); 5001 return TCL_ERROR; 5002 } 5003 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 5004 rc = sqlite3_file_control(db, 0, 0, &iArg); 5005 assert( rc==SQLITE_NOTFOUND ); 5006 rc = sqlite3_file_control(db, "notadatabase", SQLITE_FCNTL_LOCKSTATE, &iArg); 5007 assert( rc==SQLITE_ERROR ); 5008 rc = sqlite3_file_control(db, "main", -1, &iArg); 5009 assert( rc==SQLITE_NOTFOUND ); 5010 rc = sqlite3_file_control(db, "temp", -1, &iArg); 5011 assert( rc==SQLITE_NOTFOUND || rc==SQLITE_ERROR ); 5012 5013 return TCL_OK; 5014 } 5015 5016 5017 /* 5018 ** tclcmd: file_control_lasterrno_test DB 5019 ** 5020 ** This TCL command runs the sqlite3_file_control interface and 5021 ** verifies correct operation of the SQLITE_LAST_ERRNO verb. 5022 */ 5023 static int file_control_lasterrno_test( 5024 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5025 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5026 int objc, /* Number of arguments */ 5027 Tcl_Obj *CONST objv[] /* Command arguments */ 5028 ){ 5029 int iArg = 0; 5030 sqlite3 *db; 5031 int rc; 5032 5033 if( objc!=2 ){ 5034 Tcl_AppendResult(interp, "wrong # args: should be \"", 5035 Tcl_GetStringFromObj(objv[0], 0), " DB", 0); 5036 return TCL_ERROR; 5037 } 5038 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 5039 return TCL_ERROR; 5040 } 5041 rc = sqlite3_file_control(db, NULL, SQLITE_LAST_ERRNO, &iArg); 5042 if( rc ){ 5043 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 5044 return TCL_ERROR; 5045 } 5046 if( iArg!=0 ) { 5047 Tcl_AppendResult(interp, "Unexpected non-zero errno: ", 5048 Tcl_GetStringFromObj(Tcl_NewIntObj(iArg), 0), " ", 0); 5049 return TCL_ERROR; 5050 } 5051 return TCL_OK; 5052 } 5053 5054 /* 5055 ** tclcmd: file_control_chunksize_test DB DBNAME SIZE 5056 ** 5057 ** This TCL command runs the sqlite3_file_control interface and 5058 ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and 5059 ** SQLITE_SET_LOCKPROXYFILE verbs. 5060 */ 5061 static int file_control_chunksize_test( 5062 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5063 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5064 int objc, /* Number of arguments */ 5065 Tcl_Obj *CONST objv[] /* Command arguments */ 5066 ){ 5067 int nSize; /* New chunk size */ 5068 char *zDb; /* Db name ("main", "temp" etc.) */ 5069 sqlite3 *db; /* Database handle */ 5070 int rc; /* file_control() return code */ 5071 5072 if( objc!=4 ){ 5073 Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE"); 5074 return TCL_ERROR; 5075 } 5076 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) 5077 || Tcl_GetIntFromObj(interp, objv[3], &nSize) 5078 ){ 5079 return TCL_ERROR; 5080 } 5081 zDb = Tcl_GetString(objv[2]); 5082 if( zDb[0]=='\0' ) zDb = NULL; 5083 5084 rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_CHUNK_SIZE, (void *)&nSize); 5085 if( rc ){ 5086 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); 5087 return TCL_ERROR; 5088 } 5089 return TCL_OK; 5090 } 5091 5092 /* 5093 ** tclcmd: file_control_sizehint_test DB DBNAME SIZE 5094 ** 5095 ** This TCL command runs the sqlite3_file_control interface 5096 ** with SQLITE_FCNTL_SIZE_HINT 5097 */ 5098 static int file_control_sizehint_test( 5099 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5100 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5101 int objc, /* Number of arguments */ 5102 Tcl_Obj *CONST objv[] /* Command arguments */ 5103 ){ 5104 Tcl_WideInt nSize; /* Hinted size */ 5105 char *zDb; /* Db name ("main", "temp" etc.) */ 5106 sqlite3 *db; /* Database handle */ 5107 int rc; /* file_control() return code */ 5108 5109 if( objc!=4 ){ 5110 Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE"); 5111 return TCL_ERROR; 5112 } 5113 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) 5114 || Tcl_GetWideIntFromObj(interp, objv[3], &nSize) 5115 ){ 5116 return TCL_ERROR; 5117 } 5118 zDb = Tcl_GetString(objv[2]); 5119 if( zDb[0]=='\0' ) zDb = NULL; 5120 5121 rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_SIZE_HINT, (void *)&nSize); 5122 if( rc ){ 5123 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); 5124 return TCL_ERROR; 5125 } 5126 return TCL_OK; 5127 } 5128 5129 /* 5130 ** tclcmd: file_control_lockproxy_test DB PWD 5131 ** 5132 ** This TCL command runs the sqlite3_file_control interface and 5133 ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and 5134 ** SQLITE_SET_LOCKPROXYFILE verbs. 5135 */ 5136 static int file_control_lockproxy_test( 5137 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5138 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5139 int objc, /* Number of arguments */ 5140 Tcl_Obj *CONST objv[] /* Command arguments */ 5141 ){ 5142 sqlite3 *db; 5143 5144 if( objc!=3 ){ 5145 Tcl_AppendResult(interp, "wrong # args: should be \"", 5146 Tcl_GetStringFromObj(objv[0], 0), " DB PWD", 0); 5147 return TCL_ERROR; 5148 } 5149 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 5150 return TCL_ERROR; 5151 } 5152 5153 #if !defined(SQLITE_ENABLE_LOCKING_STYLE) 5154 # if defined(__APPLE__) 5155 # define SQLITE_ENABLE_LOCKING_STYLE 1 5156 # else 5157 # define SQLITE_ENABLE_LOCKING_STYLE 0 5158 # endif 5159 #endif 5160 #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) 5161 { 5162 char *testPath; 5163 int rc; 5164 int nPwd; 5165 const char *zPwd; 5166 char proxyPath[400]; 5167 5168 zPwd = Tcl_GetStringFromObj(objv[2], &nPwd); 5169 if( sizeof(proxyPath)<nPwd+20 ){ 5170 Tcl_AppendResult(interp, "PWD too big", (void*)0); 5171 return TCL_ERROR; 5172 } 5173 sprintf(proxyPath, "%s/test.proxy", zPwd); 5174 rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath); 5175 if( rc ){ 5176 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 5177 return TCL_ERROR; 5178 } 5179 rc = sqlite3_file_control(db, NULL, SQLITE_GET_LOCKPROXYFILE, &testPath); 5180 if( strncmp(proxyPath,testPath,11) ){ 5181 Tcl_AppendResult(interp, "Lock proxy file did not match the " 5182 "previously assigned value", 0); 5183 return TCL_ERROR; 5184 } 5185 if( rc ){ 5186 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 5187 return TCL_ERROR; 5188 } 5189 rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath); 5190 if( rc ){ 5191 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 5192 return TCL_ERROR; 5193 } 5194 } 5195 #endif 5196 return TCL_OK; 5197 } 5198 5199 #if SQLITE_OS_WIN 5200 /* 5201 ** tclcmd: file_control_win32_av_retry DB NRETRY DELAY 5202 ** 5203 ** This TCL command runs the sqlite3_file_control interface with 5204 ** the SQLITE_FCNTL_WIN32_AV_RETRY opcode. 5205 */ 5206 static int file_control_win32_av_retry( 5207 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5208 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5209 int objc, /* Number of arguments */ 5210 Tcl_Obj *CONST objv[] /* Command arguments */ 5211 ){ 5212 sqlite3 *db; 5213 int rc; 5214 int a[2]; 5215 char z[100]; 5216 5217 if( objc!=4 ){ 5218 Tcl_AppendResult(interp, "wrong # args: should be \"", 5219 Tcl_GetStringFromObj(objv[0], 0), " DB NRETRY DELAY", 0); 5220 return TCL_ERROR; 5221 } 5222 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 5223 return TCL_ERROR; 5224 } 5225 if( Tcl_GetIntFromObj(interp, objv[2], &a[0]) ) return TCL_ERROR; 5226 if( Tcl_GetIntFromObj(interp, objv[3], &a[1]) ) return TCL_ERROR; 5227 rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a); 5228 sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]); 5229 Tcl_AppendResult(interp, z, (char*)0); 5230 return TCL_OK; 5231 } 5232 5233 /* 5234 ** tclcmd: file_control_win32_set_handle DB HANDLE 5235 ** 5236 ** This TCL command runs the sqlite3_file_control interface with 5237 ** the SQLITE_FCNTL_WIN32_SET_HANDLE opcode. 5238 */ 5239 static int file_control_win32_set_handle( 5240 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5241 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5242 int objc, /* Number of arguments */ 5243 Tcl_Obj *CONST objv[] /* Command arguments */ 5244 ){ 5245 sqlite3 *db; 5246 int rc; 5247 HANDLE hFile = NULL; 5248 char z[100]; 5249 5250 if( objc!=3 ){ 5251 Tcl_AppendResult(interp, "wrong # args: should be \"", 5252 Tcl_GetStringFromObj(objv[0], 0), " DB HANDLE", 0); 5253 return TCL_ERROR; 5254 } 5255 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 5256 return TCL_ERROR; 5257 } 5258 if( getWin32Handle(interp, Tcl_GetString(objv[2]), &hFile) ){ 5259 return TCL_ERROR; 5260 } 5261 rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_SET_HANDLE, 5262 (void*)&hFile); 5263 sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile); 5264 Tcl_AppendResult(interp, z, (char*)0); 5265 return TCL_OK; 5266 } 5267 #endif 5268 5269 /* 5270 ** tclcmd: file_control_persist_wal DB PERSIST-FLAG 5271 ** 5272 ** This TCL command runs the sqlite3_file_control interface with 5273 ** the SQLITE_FCNTL_PERSIST_WAL opcode. 5274 */ 5275 static int file_control_persist_wal( 5276 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5277 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5278 int objc, /* Number of arguments */ 5279 Tcl_Obj *CONST objv[] /* Command arguments */ 5280 ){ 5281 sqlite3 *db; 5282 int rc; 5283 int bPersist; 5284 char z[100]; 5285 5286 if( objc!=3 ){ 5287 Tcl_AppendResult(interp, "wrong # args: should be \"", 5288 Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0); 5289 return TCL_ERROR; 5290 } 5291 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 5292 return TCL_ERROR; 5293 } 5294 if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR; 5295 rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist); 5296 sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist); 5297 Tcl_AppendResult(interp, z, (char*)0); 5298 return TCL_OK; 5299 } 5300 5301 /* 5302 ** tclcmd: file_control_powersafe_overwrite DB PSOW-FLAG 5303 ** 5304 ** This TCL command runs the sqlite3_file_control interface with 5305 ** the SQLITE_FCNTL_POWERSAFE_OVERWRITE opcode. 5306 */ 5307 static int file_control_powersafe_overwrite( 5308 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5309 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5310 int objc, /* Number of arguments */ 5311 Tcl_Obj *CONST objv[] /* Command arguments */ 5312 ){ 5313 sqlite3 *db; 5314 int rc; 5315 int b; 5316 char z[100]; 5317 5318 if( objc!=3 ){ 5319 Tcl_AppendResult(interp, "wrong # args: should be \"", 5320 Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0); 5321 return TCL_ERROR; 5322 } 5323 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 5324 return TCL_ERROR; 5325 } 5326 if( Tcl_GetIntFromObj(interp, objv[2], &b) ) return TCL_ERROR; 5327 rc = sqlite3_file_control(db,NULL,SQLITE_FCNTL_POWERSAFE_OVERWRITE,(void*)&b); 5328 sqlite3_snprintf(sizeof(z), z, "%d %d", rc, b); 5329 Tcl_AppendResult(interp, z, (char*)0); 5330 return TCL_OK; 5331 } 5332 5333 5334 /* 5335 ** tclcmd: file_control_vfsname DB ?AUXDB? 5336 ** 5337 ** Return a string that describes the stack of VFSes. 5338 */ 5339 static int file_control_vfsname( 5340 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5341 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5342 int objc, /* Number of arguments */ 5343 Tcl_Obj *CONST objv[] /* Command arguments */ 5344 ){ 5345 sqlite3 *db; 5346 const char *zDbName = "main"; 5347 char *zVfsName = 0; 5348 5349 if( objc!=2 && objc!=3 ){ 5350 Tcl_AppendResult(interp, "wrong # args: should be \"", 5351 Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0); 5352 return TCL_ERROR; 5353 } 5354 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 5355 return TCL_ERROR; 5356 } 5357 if( objc==3 ){ 5358 zDbName = Tcl_GetString(objv[2]); 5359 } 5360 sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName); 5361 Tcl_AppendResult(interp, zVfsName, (char*)0); 5362 sqlite3_free(zVfsName); 5363 return TCL_OK; 5364 } 5365 5366 /* 5367 ** tclcmd: file_control_tempfilename DB ?AUXDB? 5368 ** 5369 ** Return a string that is a temporary filename 5370 */ 5371 static int file_control_tempfilename( 5372 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5373 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5374 int objc, /* Number of arguments */ 5375 Tcl_Obj *CONST objv[] /* Command arguments */ 5376 ){ 5377 sqlite3 *db; 5378 const char *zDbName = "main"; 5379 char *zTName = 0; 5380 5381 if( objc!=2 && objc!=3 ){ 5382 Tcl_AppendResult(interp, "wrong # args: should be \"", 5383 Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0); 5384 return TCL_ERROR; 5385 } 5386 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 5387 return TCL_ERROR; 5388 } 5389 if( objc==3 ){ 5390 zDbName = Tcl_GetString(objv[2]); 5391 } 5392 sqlite3_file_control(db, zDbName, SQLITE_FCNTL_TEMPFILENAME, (void*)&zTName); 5393 Tcl_AppendResult(interp, zTName, (char*)0); 5394 sqlite3_free(zTName); 5395 return TCL_OK; 5396 } 5397 5398 5399 /* 5400 ** tclcmd: sqlite3_vfs_list 5401 ** 5402 ** Return a tcl list containing the names of all registered vfs's. 5403 */ 5404 static int vfs_list( 5405 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5406 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5407 int objc, /* Number of arguments */ 5408 Tcl_Obj *CONST objv[] /* Command arguments */ 5409 ){ 5410 sqlite3_vfs *pVfs; 5411 Tcl_Obj *pRet = Tcl_NewObj(); 5412 if( objc!=1 ){ 5413 Tcl_WrongNumArgs(interp, 1, objv, ""); 5414 return TCL_ERROR; 5415 } 5416 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){ 5417 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(pVfs->zName, -1)); 5418 } 5419 Tcl_SetObjResult(interp, pRet); 5420 return TCL_OK; 5421 } 5422 5423 /* 5424 ** tclcmd: sqlite3_limit DB ID VALUE 5425 ** 5426 ** This TCL command runs the sqlite3_limit interface and 5427 ** verifies correct operation of the same. 5428 */ 5429 static int test_limit( 5430 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5431 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5432 int objc, /* Number of arguments */ 5433 Tcl_Obj *CONST objv[] /* Command arguments */ 5434 ){ 5435 sqlite3 *db; 5436 int rc; 5437 static const struct { 5438 char *zName; 5439 int id; 5440 } aId[] = { 5441 { "SQLITE_LIMIT_LENGTH", SQLITE_LIMIT_LENGTH }, 5442 { "SQLITE_LIMIT_SQL_LENGTH", SQLITE_LIMIT_SQL_LENGTH }, 5443 { "SQLITE_LIMIT_COLUMN", SQLITE_LIMIT_COLUMN }, 5444 { "SQLITE_LIMIT_EXPR_DEPTH", SQLITE_LIMIT_EXPR_DEPTH }, 5445 { "SQLITE_LIMIT_COMPOUND_SELECT", SQLITE_LIMIT_COMPOUND_SELECT }, 5446 { "SQLITE_LIMIT_VDBE_OP", SQLITE_LIMIT_VDBE_OP }, 5447 { "SQLITE_LIMIT_FUNCTION_ARG", SQLITE_LIMIT_FUNCTION_ARG }, 5448 { "SQLITE_LIMIT_ATTACHED", SQLITE_LIMIT_ATTACHED }, 5449 { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH }, 5450 { "SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER }, 5451 { "SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH }, 5452 { "SQLITE_LIMIT_WORKER_THREADS", SQLITE_LIMIT_WORKER_THREADS }, 5453 5454 /* Out of range test cases */ 5455 { "SQLITE_LIMIT_TOOSMALL", -1, }, 5456 { "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_WORKER_THREADS+1 }, 5457 }; 5458 int i, id; 5459 int val; 5460 const char *zId; 5461 5462 if( objc!=4 ){ 5463 Tcl_AppendResult(interp, "wrong # args: should be \"", 5464 Tcl_GetStringFromObj(objv[0], 0), " DB ID VALUE", 0); 5465 return TCL_ERROR; 5466 } 5467 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 5468 zId = Tcl_GetString(objv[2]); 5469 for(i=0; i<sizeof(aId)/sizeof(aId[0]); i++){ 5470 if( strcmp(zId, aId[i].zName)==0 ){ 5471 id = aId[i].id; 5472 break; 5473 } 5474 } 5475 if( i>=sizeof(aId)/sizeof(aId[0]) ){ 5476 Tcl_AppendResult(interp, "unknown limit type: ", zId, (char*)0); 5477 return TCL_ERROR; 5478 } 5479 if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR; 5480 rc = sqlite3_limit(db, id, val); 5481 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 5482 return TCL_OK; 5483 } 5484 5485 /* 5486 ** tclcmd: save_prng_state 5487 ** 5488 ** Save the state of the pseudo-random number generator. 5489 ** At the same time, verify that sqlite3_test_control works even when 5490 ** called with an out-of-range opcode. 5491 */ 5492 static int save_prng_state( 5493 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5494 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5495 int objc, /* Number of arguments */ 5496 Tcl_Obj *CONST objv[] /* Command arguments */ 5497 ){ 5498 int rc = sqlite3_test_control(9999); 5499 assert( rc==0 ); 5500 rc = sqlite3_test_control(-1); 5501 assert( rc==0 ); 5502 sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SAVE); 5503 return TCL_OK; 5504 } 5505 /* 5506 ** tclcmd: restore_prng_state 5507 */ 5508 static int restore_prng_state( 5509 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5510 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5511 int objc, /* Number of arguments */ 5512 Tcl_Obj *CONST objv[] /* Command arguments */ 5513 ){ 5514 sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESTORE); 5515 return TCL_OK; 5516 } 5517 /* 5518 ** tclcmd: reset_prng_state 5519 */ 5520 static int reset_prng_state( 5521 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5522 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5523 int objc, /* Number of arguments */ 5524 Tcl_Obj *CONST objv[] /* Command arguments */ 5525 ){ 5526 sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESET); 5527 return TCL_OK; 5528 } 5529 5530 /* 5531 ** tclcmd: database_may_be_corrupt 5532 ** 5533 ** Indicate that database files might be corrupt. In other words, set the normal 5534 ** state of operation. 5535 */ 5536 static int database_may_be_corrupt( 5537 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5538 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5539 int objc, /* Number of arguments */ 5540 Tcl_Obj *CONST objv[] /* Command arguments */ 5541 ){ 5542 sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 0); 5543 return TCL_OK; 5544 } 5545 /* 5546 ** tclcmd: database_never_corrupt 5547 ** 5548 ** Indicate that database files are always well-formed. This enables extra assert() 5549 ** statements that test conditions that are always true for well-formed databases. 5550 */ 5551 static int database_never_corrupt( 5552 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5553 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5554 int objc, /* Number of arguments */ 5555 Tcl_Obj *CONST objv[] /* Command arguments */ 5556 ){ 5557 sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, 1); 5558 return TCL_OK; 5559 } 5560 5561 /* 5562 ** tclcmd: pcache_stats 5563 */ 5564 static int test_pcache_stats( 5565 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 5566 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5567 int objc, /* Number of arguments */ 5568 Tcl_Obj *CONST objv[] /* Command arguments */ 5569 ){ 5570 int nMin; 5571 int nMax; 5572 int nCurrent; 5573 int nRecyclable; 5574 Tcl_Obj *pRet; 5575 5576 sqlite3PcacheStats(&nCurrent, &nMax, &nMin, &nRecyclable); 5577 5578 pRet = Tcl_NewObj(); 5579 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("current", -1)); 5580 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCurrent)); 5581 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("max", -1)); 5582 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMax)); 5583 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("min", -1)); 5584 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMin)); 5585 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("recyclable", -1)); 5586 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nRecyclable)); 5587 5588 Tcl_SetObjResult(interp, pRet); 5589 5590 return TCL_OK; 5591 } 5592 5593 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY 5594 static void test_unlock_notify_cb(void **aArg, int nArg){ 5595 int ii; 5596 for(ii=0; ii<nArg; ii++){ 5597 Tcl_EvalEx((Tcl_Interp *)aArg[ii], "unlock_notify", -1, TCL_EVAL_GLOBAL); 5598 } 5599 } 5600 #endif /* SQLITE_ENABLE_UNLOCK_NOTIFY */ 5601 5602 /* 5603 ** tclcmd: sqlite3_unlock_notify db 5604 */ 5605 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY 5606 static int test_unlock_notify( 5607 ClientData clientData, /* Unused */ 5608 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5609 int objc, /* Number of arguments */ 5610 Tcl_Obj *CONST objv[] /* Command arguments */ 5611 ){ 5612 sqlite3 *db; 5613 int rc; 5614 5615 if( objc!=2 ){ 5616 Tcl_WrongNumArgs(interp, 1, objv, "DB"); 5617 return TCL_ERROR; 5618 } 5619 5620 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 5621 return TCL_ERROR; 5622 } 5623 rc = sqlite3_unlock_notify(db, test_unlock_notify_cb, (void *)interp); 5624 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 5625 return TCL_OK; 5626 } 5627 #endif 5628 5629 /* 5630 ** tclcmd: sqlite3_wal_checkpoint db ?NAME? 5631 */ 5632 static int test_wal_checkpoint( 5633 ClientData clientData, /* Unused */ 5634 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5635 int objc, /* Number of arguments */ 5636 Tcl_Obj *CONST objv[] /* Command arguments */ 5637 ){ 5638 char *zDb = 0; 5639 sqlite3 *db; 5640 int rc; 5641 5642 if( objc!=3 && objc!=2 ){ 5643 Tcl_WrongNumArgs(interp, 1, objv, "DB ?NAME?"); 5644 return TCL_ERROR; 5645 } 5646 5647 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 5648 return TCL_ERROR; 5649 } 5650 if( objc==3 ){ 5651 zDb = Tcl_GetString(objv[2]); 5652 } 5653 rc = sqlite3_wal_checkpoint(db, zDb); 5654 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 5655 return TCL_OK; 5656 } 5657 5658 /* 5659 ** tclcmd: sqlite3_wal_checkpoint_v2 db MODE ?NAME? 5660 ** 5661 ** This command calls the wal_checkpoint_v2() function with the specified 5662 ** mode argument (passive, full or restart). If present, the database name 5663 ** NAME is passed as the second argument to wal_checkpoint_v2(). If it the 5664 ** NAME argument is not present, a NULL pointer is passed instead. 5665 ** 5666 ** If wal_checkpoint_v2() returns any value other than SQLITE_BUSY or 5667 ** SQLITE_OK, then this command returns TCL_ERROR. The Tcl result is set 5668 ** to the error message obtained from sqlite3_errmsg(). 5669 ** 5670 ** Otherwise, this command returns a list of three integers. The first integer 5671 ** is 1 if SQLITE_BUSY was returned, or 0 otherwise. The following two integers 5672 ** are the values returned via the output parameters by wal_checkpoint_v2() - 5673 ** the number of frames in the log and the number of frames in the log 5674 ** that have been checkpointed. 5675 */ 5676 static int test_wal_checkpoint_v2( 5677 ClientData clientData, /* Unused */ 5678 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5679 int objc, /* Number of arguments */ 5680 Tcl_Obj *CONST objv[] /* Command arguments */ 5681 ){ 5682 char *zDb = 0; 5683 sqlite3 *db; 5684 int rc; 5685 5686 int eMode; 5687 int nLog = -555; 5688 int nCkpt = -555; 5689 Tcl_Obj *pRet; 5690 5691 const char * aMode[] = { "passive", "full", "restart", "truncate", 0 }; 5692 assert( SQLITE_CHECKPOINT_PASSIVE==0 ); 5693 assert( SQLITE_CHECKPOINT_FULL==1 ); 5694 assert( SQLITE_CHECKPOINT_RESTART==2 ); 5695 assert( SQLITE_CHECKPOINT_TRUNCATE==3 ); 5696 5697 if( objc!=3 && objc!=4 ){ 5698 Tcl_WrongNumArgs(interp, 1, objv, "DB MODE ?NAME?"); 5699 return TCL_ERROR; 5700 } 5701 5702 if( objc==4 ){ 5703 zDb = Tcl_GetString(objv[3]); 5704 } 5705 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) || ( 5706 TCL_OK!=Tcl_GetIntFromObj(0, objv[2], &eMode) 5707 && TCL_OK!=Tcl_GetIndexFromObj(interp, objv[2], aMode, "mode", 0, &eMode) 5708 )){ 5709 return TCL_ERROR; 5710 } 5711 5712 rc = sqlite3_wal_checkpoint_v2(db, zDb, eMode, &nLog, &nCkpt); 5713 if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ 5714 const char *zErrCode = sqlite3ErrName(rc); 5715 Tcl_ResetResult(interp); 5716 Tcl_AppendResult(interp, zErrCode, " - ", (char *)sqlite3_errmsg(db), 0); 5717 return TCL_ERROR; 5718 } 5719 5720 pRet = Tcl_NewObj(); 5721 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(rc==SQLITE_BUSY?1:0)); 5722 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nLog)); 5723 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCkpt)); 5724 Tcl_SetObjResult(interp, pRet); 5725 5726 return TCL_OK; 5727 } 5728 5729 /* 5730 ** tclcmd: sqlite3_wal_autocheckpoint db VALUE 5731 */ 5732 static int test_wal_autocheckpoint( 5733 ClientData clientData, /* Unused */ 5734 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5735 int objc, /* Number of arguments */ 5736 Tcl_Obj *CONST objv[] /* Command arguments */ 5737 ){ 5738 sqlite3 *db; 5739 int rc; 5740 int iVal; 5741 5742 5743 if( objc!=3 ){ 5744 Tcl_WrongNumArgs(interp, 1, objv, "DB VALUE"); 5745 return TCL_ERROR; 5746 } 5747 5748 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) 5749 || Tcl_GetIntFromObj(0, objv[2], &iVal) 5750 ){ 5751 return TCL_ERROR; 5752 } 5753 5754 rc = sqlite3_wal_autocheckpoint(db, iVal); 5755 Tcl_ResetResult(interp); 5756 if( rc!=SQLITE_OK ){ 5757 const char *zErrCode = sqlite3ErrName(rc); 5758 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErrCode, -1)); 5759 return TCL_ERROR; 5760 } 5761 5762 return TCL_OK; 5763 } 5764 5765 5766 /* 5767 ** tclcmd: test_sqlite3_log ?SCRIPT? 5768 */ 5769 static struct LogCallback { 5770 Tcl_Interp *pInterp; 5771 Tcl_Obj *pObj; 5772 } logcallback = {0, 0}; 5773 static void xLogcallback(void *unused, int err, char *zMsg){ 5774 Tcl_Obj *pNew = Tcl_DuplicateObj(logcallback.pObj); 5775 Tcl_IncrRefCount(pNew); 5776 Tcl_ListObjAppendElement( 5777 0, pNew, Tcl_NewStringObj(sqlite3ErrName(err), -1) 5778 ); 5779 Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zMsg, -1)); 5780 Tcl_EvalObjEx(logcallback.pInterp, pNew, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT); 5781 Tcl_DecrRefCount(pNew); 5782 } 5783 static int test_sqlite3_log( 5784 ClientData clientData, 5785 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 5786 int objc, /* Number of arguments */ 5787 Tcl_Obj *CONST objv[] /* Command arguments */ 5788 ){ 5789 if( objc>2 ){ 5790 Tcl_WrongNumArgs(interp, 1, objv, "SCRIPT"); 5791 return TCL_ERROR; 5792 } 5793 if( logcallback.pObj ){ 5794 Tcl_DecrRefCount(logcallback.pObj); 5795 logcallback.pObj = 0; 5796 logcallback.pInterp = 0; 5797 sqlite3_config(SQLITE_CONFIG_LOG, 0, 0); 5798 } 5799 if( objc>1 ){ 5800 logcallback.pObj = objv[1]; 5801 Tcl_IncrRefCount(logcallback.pObj); 5802 logcallback.pInterp = interp; 5803 sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, 0); 5804 } 5805 return TCL_OK; 5806 } 5807 5808 /* 5809 ** tcl_objproc COMMANDNAME ARGS... 5810 ** 5811 ** Run a TCL command using its objProc interface. Throw an error if 5812 ** the command has no objProc interface. 5813 */ 5814 static int runAsObjProc( 5815 void * clientData, 5816 Tcl_Interp *interp, 5817 int objc, 5818 Tcl_Obj *CONST objv[] 5819 ){ 5820 Tcl_CmdInfo cmdInfo; 5821 if( objc<2 ){ 5822 Tcl_WrongNumArgs(interp, 1, objv, "COMMAND ..."); 5823 return TCL_ERROR; 5824 } 5825 if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){ 5826 Tcl_AppendResult(interp, "command not found: ", 5827 Tcl_GetString(objv[1]), (char*)0); 5828 return TCL_ERROR; 5829 } 5830 if( cmdInfo.objProc==0 ){ 5831 Tcl_AppendResult(interp, "command has no objProc: ", 5832 Tcl_GetString(objv[1]), (char*)0); 5833 return TCL_ERROR; 5834 } 5835 return cmdInfo.objProc(cmdInfo.objClientData, interp, objc-1, objv+1); 5836 } 5837 5838 #ifndef SQLITE_OMIT_EXPLAIN 5839 /* 5840 ** WARNING: The following function, printExplainQueryPlan() is an exact 5841 ** copy of example code from eqp.in (eqp.html). If this code is modified, 5842 ** then the documentation copy needs to be modified as well. 5843 */ 5844 /* 5845 ** Argument pStmt is a prepared SQL statement. This function compiles 5846 ** an EXPLAIN QUERY PLAN command to report on the prepared statement, 5847 ** and prints the report to stdout using printf(). 5848 */ 5849 int printExplainQueryPlan(sqlite3_stmt *pStmt){ 5850 const char *zSql; /* Input SQL */ 5851 char *zExplain; /* SQL with EXPLAIN QUERY PLAN prepended */ 5852 sqlite3_stmt *pExplain; /* Compiled EXPLAIN QUERY PLAN command */ 5853 int rc; /* Return code from sqlite3_prepare_v2() */ 5854 5855 zSql = sqlite3_sql(pStmt); 5856 if( zSql==0 ) return SQLITE_ERROR; 5857 5858 zExplain = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zSql); 5859 if( zExplain==0 ) return SQLITE_NOMEM; 5860 5861 rc = sqlite3_prepare_v2(sqlite3_db_handle(pStmt), zExplain, -1, &pExplain, 0); 5862 sqlite3_free(zExplain); 5863 if( rc!=SQLITE_OK ) return rc; 5864 5865 while( SQLITE_ROW==sqlite3_step(pExplain) ){ 5866 int iSelectid = sqlite3_column_int(pExplain, 0); 5867 int iOrder = sqlite3_column_int(pExplain, 1); 5868 int iFrom = sqlite3_column_int(pExplain, 2); 5869 const char *zDetail = (const char *)sqlite3_column_text(pExplain, 3); 5870 5871 printf("%d %d %d %s\n", iSelectid, iOrder, iFrom, zDetail); 5872 } 5873 5874 return sqlite3_finalize(pExplain); 5875 } 5876 5877 static int test_print_eqp( 5878 void * clientData, 5879 Tcl_Interp *interp, 5880 int objc, 5881 Tcl_Obj *CONST objv[] 5882 ){ 5883 int rc; 5884 sqlite3_stmt *pStmt; 5885 5886 if( objc!=2 ){ 5887 Tcl_WrongNumArgs(interp, 1, objv, "STMT"); 5888 return TCL_ERROR; 5889 } 5890 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; 5891 rc = printExplainQueryPlan(pStmt); 5892 /* This is needed on Windows so that a test case using this 5893 ** function can open a read pipe and get the output of 5894 ** printExplainQueryPlan() immediately. 5895 */ 5896 fflush(stdout); 5897 Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); 5898 return TCL_OK; 5899 } 5900 #endif /* SQLITE_OMIT_EXPLAIN */ 5901 5902 /* 5903 ** sqlite3_test_control VERB ARGS... 5904 */ 5905 static int test_test_control( 5906 void * clientData, 5907 Tcl_Interp *interp, 5908 int objc, 5909 Tcl_Obj *CONST objv[] 5910 ){ 5911 struct Verb { 5912 const char *zName; 5913 int i; 5914 } aVerb[] = { 5915 { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT }, 5916 { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP }, 5917 }; 5918 int iVerb; 5919 int iFlag; 5920 int rc; 5921 5922 if( objc<2 ){ 5923 Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS..."); 5924 return TCL_ERROR; 5925 } 5926 5927 rc = Tcl_GetIndexFromObjStruct( 5928 interp, objv[1], aVerb, sizeof(aVerb[0]), "VERB", 0, &iVerb 5929 ); 5930 if( rc!=TCL_OK ) return rc; 5931 5932 iFlag = aVerb[iVerb].i; 5933 switch( iFlag ){ 5934 case SQLITE_TESTCTRL_LOCALTIME_FAULT: { 5935 int val; 5936 if( objc!=3 ){ 5937 Tcl_WrongNumArgs(interp, 2, objv, "ONOFF"); 5938 return TCL_ERROR; 5939 } 5940 if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; 5941 sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val); 5942 break; 5943 } 5944 5945 case SQLITE_TESTCTRL_SORTER_MMAP: { 5946 int val; 5947 sqlite3 *db; 5948 if( objc!=4 ){ 5949 Tcl_WrongNumArgs(interp, 2, objv, "DB LIMIT"); 5950 return TCL_ERROR; 5951 } 5952 if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR; 5953 if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR; 5954 sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, val); 5955 break; 5956 } 5957 } 5958 5959 Tcl_ResetResult(interp); 5960 return TCL_OK; 5961 } 5962 5963 #if SQLITE_OS_UNIX 5964 #include <sys/time.h> 5965 #include <sys/resource.h> 5966 5967 static int test_getrusage( 5968 void * clientData, 5969 Tcl_Interp *interp, 5970 int objc, 5971 Tcl_Obj *CONST objv[] 5972 ){ 5973 char buf[1024]; 5974 struct rusage r; 5975 memset(&r, 0, sizeof(r)); 5976 getrusage(RUSAGE_SELF, &r); 5977 5978 sprintf(buf, "ru_utime=%d.%06d ru_stime=%d.%06d ru_minflt=%d ru_majflt=%d", 5979 (int)r.ru_utime.tv_sec, (int)r.ru_utime.tv_usec, 5980 (int)r.ru_stime.tv_sec, (int)r.ru_stime.tv_usec, 5981 (int)r.ru_minflt, (int)r.ru_majflt 5982 ); 5983 Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1)); 5984 return TCL_OK; 5985 } 5986 #endif 5987 5988 #if SQLITE_OS_WIN 5989 /* 5990 ** Information passed from the main thread into the windows file locker 5991 ** background thread. 5992 */ 5993 struct win32FileLocker { 5994 char *evName; /* Name of event to signal thread startup */ 5995 HANDLE h; /* Handle of the file to be locked */ 5996 int delay1; /* Delay before locking */ 5997 int delay2; /* Delay before unlocking */ 5998 int ok; /* Finished ok */ 5999 int err; /* True if an error occurs */ 6000 }; 6001 #endif 6002 6003 6004 #if SQLITE_OS_WIN 6005 #include <process.h> 6006 /* 6007 ** The background thread that does file locking. 6008 */ 6009 static void win32_file_locker(void *pAppData){ 6010 struct win32FileLocker *p = (struct win32FileLocker*)pAppData; 6011 if( p->evName ){ 6012 HANDLE ev = OpenEvent(EVENT_MODIFY_STATE, FALSE, p->evName); 6013 if ( ev ){ 6014 SetEvent(ev); 6015 CloseHandle(ev); 6016 } 6017 } 6018 if( p->delay1 ) Sleep(p->delay1); 6019 if( LockFile(p->h, 0, 0, 100000000, 0) ){ 6020 Sleep(p->delay2); 6021 UnlockFile(p->h, 0, 0, 100000000, 0); 6022 p->ok = 1; 6023 }else{ 6024 p->err = 1; 6025 } 6026 CloseHandle(p->h); 6027 p->h = 0; 6028 p->delay1 = 0; 6029 p->delay2 = 0; 6030 } 6031 #endif 6032 6033 #if SQLITE_OS_WIN 6034 /* 6035 ** lock_win32_file FILENAME DELAY1 DELAY2 6036 ** 6037 ** Get an exclusive manditory lock on file for DELAY2 milliseconds. 6038 ** Wait DELAY1 milliseconds before acquiring the lock. 6039 */ 6040 static int win32_file_lock( 6041 void * clientData, 6042 Tcl_Interp *interp, 6043 int objc, 6044 Tcl_Obj *CONST objv[] 6045 ){ 6046 static struct win32FileLocker x = { "win32_file_lock", 0, 0, 0, 0, 0 }; 6047 const char *zFilename; 6048 char zBuf[200]; 6049 int retry = 0; 6050 HANDLE ev; 6051 DWORD wResult; 6052 6053 if( objc!=4 && objc!=1 ){ 6054 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2"); 6055 return TCL_ERROR; 6056 } 6057 if( objc==1 ){ 6058 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d", 6059 x.ok, x.err, x.delay1, x.delay2, x.h); 6060 Tcl_AppendResult(interp, zBuf, (char*)0); 6061 return TCL_OK; 6062 } 6063 while( x.h && retry<30 ){ 6064 retry++; 6065 Sleep(100); 6066 } 6067 if( x.h ){ 6068 Tcl_AppendResult(interp, "busy", (char*)0); 6069 return TCL_ERROR; 6070 } 6071 if( Tcl_GetIntFromObj(interp, objv[2], &x.delay1) ) return TCL_ERROR; 6072 if( Tcl_GetIntFromObj(interp, objv[3], &x.delay2) ) return TCL_ERROR; 6073 zFilename = Tcl_GetString(objv[1]); 6074 x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE, 6075 FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS, 6076 FILE_ATTRIBUTE_NORMAL, 0); 6077 if( !x.h ){ 6078 Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0); 6079 return TCL_ERROR; 6080 } 6081 ev = CreateEvent(NULL, TRUE, FALSE, x.evName); 6082 if ( !ev ){ 6083 Tcl_AppendResult(interp, "cannot create event: ", x.evName, (char*)0); 6084 return TCL_ERROR; 6085 } 6086 _beginthread(win32_file_locker, 0, (void*)&x); 6087 Sleep(0); 6088 if ( (wResult = WaitForSingleObject(ev, 10000))!=WAIT_OBJECT_0 ){ 6089 sqlite3_snprintf(sizeof(zBuf), zBuf, "0x%x", wResult); 6090 Tcl_AppendResult(interp, "wait failed: ", zBuf, (char*)0); 6091 CloseHandle(ev); 6092 return TCL_ERROR; 6093 } 6094 CloseHandle(ev); 6095 return TCL_OK; 6096 } 6097 6098 /* 6099 ** exists_win32_path PATH 6100 ** 6101 ** Returns non-zero if the specified path exists, whose fully qualified name 6102 ** may exceed 260 characters if it is prefixed with "\\?\". 6103 */ 6104 static int win32_exists_path( 6105 void *clientData, 6106 Tcl_Interp *interp, 6107 int objc, 6108 Tcl_Obj *CONST objv[] 6109 ){ 6110 if( objc!=2 ){ 6111 Tcl_WrongNumArgs(interp, 1, objv, "PATH"); 6112 return TCL_ERROR; 6113 } 6114 Tcl_SetObjResult(interp, Tcl_NewBooleanObj( 6115 GetFileAttributesW( Tcl_GetUnicode(objv[1]))!=INVALID_FILE_ATTRIBUTES )); 6116 return TCL_OK; 6117 } 6118 6119 /* 6120 ** find_win32_file PATTERN 6121 ** 6122 ** Returns a list of entries in a directory that match the specified pattern, 6123 ** whose fully qualified name may exceed 248 characters if it is prefixed with 6124 ** "\\?\". 6125 */ 6126 static int win32_find_file( 6127 void *clientData, 6128 Tcl_Interp *interp, 6129 int objc, 6130 Tcl_Obj *CONST objv[] 6131 ){ 6132 HANDLE hFindFile = INVALID_HANDLE_VALUE; 6133 WIN32_FIND_DATAW findData; 6134 Tcl_Obj *listObj; 6135 DWORD lastErrno; 6136 if( objc!=2 ){ 6137 Tcl_WrongNumArgs(interp, 1, objv, "PATTERN"); 6138 return TCL_ERROR; 6139 } 6140 hFindFile = FindFirstFileW(Tcl_GetUnicode(objv[1]), &findData); 6141 if( hFindFile==INVALID_HANDLE_VALUE ){ 6142 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError())); 6143 return TCL_ERROR; 6144 } 6145 listObj = Tcl_NewObj(); 6146 Tcl_IncrRefCount(listObj); 6147 do { 6148 Tcl_ListObjAppendElement(interp, listObj, Tcl_NewUnicodeObj( 6149 findData.cFileName, -1)); 6150 Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj( 6151 findData.dwFileAttributes)); 6152 } while( FindNextFileW(hFindFile, &findData) ); 6153 lastErrno = GetLastError(); 6154 if( lastErrno!=NO_ERROR && lastErrno!=ERROR_NO_MORE_FILES ){ 6155 FindClose(hFindFile); 6156 Tcl_DecrRefCount(listObj); 6157 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError())); 6158 return TCL_ERROR; 6159 } 6160 FindClose(hFindFile); 6161 Tcl_SetObjResult(interp, listObj); 6162 return TCL_OK; 6163 } 6164 6165 /* 6166 ** delete_win32_file FILENAME 6167 ** 6168 ** Deletes the specified file, whose fully qualified name may exceed 260 6169 ** characters if it is prefixed with "\\?\". 6170 */ 6171 static int win32_delete_file( 6172 void *clientData, 6173 Tcl_Interp *interp, 6174 int objc, 6175 Tcl_Obj *CONST objv[] 6176 ){ 6177 if( objc!=2 ){ 6178 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME"); 6179 return TCL_ERROR; 6180 } 6181 if( !DeleteFileW(Tcl_GetUnicode(objv[1])) ){ 6182 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError())); 6183 return TCL_ERROR; 6184 } 6185 Tcl_ResetResult(interp); 6186 return TCL_OK; 6187 } 6188 6189 /* 6190 ** make_win32_dir DIRECTORY 6191 ** 6192 ** Creates the specified directory, whose fully qualified name may exceed 248 6193 ** characters if it is prefixed with "\\?\". 6194 */ 6195 static int win32_mkdir( 6196 void *clientData, 6197 Tcl_Interp *interp, 6198 int objc, 6199 Tcl_Obj *CONST objv[] 6200 ){ 6201 if( objc!=2 ){ 6202 Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY"); 6203 return TCL_ERROR; 6204 } 6205 if( !CreateDirectoryW(Tcl_GetUnicode(objv[1]), NULL) ){ 6206 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError())); 6207 return TCL_ERROR; 6208 } 6209 Tcl_ResetResult(interp); 6210 return TCL_OK; 6211 } 6212 6213 /* 6214 ** remove_win32_dir DIRECTORY 6215 ** 6216 ** Removes the specified directory, whose fully qualified name may exceed 248 6217 ** characters if it is prefixed with "\\?\". 6218 */ 6219 static int win32_rmdir( 6220 void *clientData, 6221 Tcl_Interp *interp, 6222 int objc, 6223 Tcl_Obj *CONST objv[] 6224 ){ 6225 if( objc!=2 ){ 6226 Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY"); 6227 return TCL_ERROR; 6228 } 6229 if( !RemoveDirectoryW(Tcl_GetUnicode(objv[1])) ){ 6230 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError())); 6231 return TCL_ERROR; 6232 } 6233 Tcl_ResetResult(interp); 6234 return TCL_OK; 6235 } 6236 #endif 6237 6238 6239 /* 6240 ** optimization_control DB OPT BOOLEAN 6241 ** 6242 ** Enable or disable query optimizations using the sqlite3_test_control() 6243 ** interface. Disable if BOOLEAN is false and enable if BOOLEAN is true. 6244 ** OPT is the name of the optimization to be disabled. 6245 */ 6246 static int optimization_control( 6247 void * clientData, 6248 Tcl_Interp *interp, 6249 int objc, 6250 Tcl_Obj *CONST objv[] 6251 ){ 6252 int i; 6253 sqlite3 *db; 6254 const char *zOpt; 6255 int onoff; 6256 int mask = 0; 6257 static const struct { 6258 const char *zOptName; 6259 int mask; 6260 } aOpt[] = { 6261 { "all", SQLITE_AllOpts }, 6262 { "none", 0 }, 6263 { "query-flattener", SQLITE_QueryFlattener }, 6264 { "column-cache", SQLITE_ColumnCache }, 6265 { "groupby-order", SQLITE_GroupByOrder }, 6266 { "factor-constants", SQLITE_FactorOutConst }, 6267 { "distinct-opt", SQLITE_DistinctOpt }, 6268 { "cover-idx-scan", SQLITE_CoverIdxScan }, 6269 { "order-by-idx-join", SQLITE_OrderByIdxJoin }, 6270 { "transitive", SQLITE_Transitive }, 6271 { "subquery-coroutine", SQLITE_SubqCoroutine }, 6272 { "omit-noop-join", SQLITE_OmitNoopJoin }, 6273 { "stat3", SQLITE_Stat34 }, 6274 { "stat4", SQLITE_Stat34 }, 6275 }; 6276 6277 if( objc!=4 ){ 6278 Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN"); 6279 return TCL_ERROR; 6280 } 6281 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 6282 if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR; 6283 zOpt = Tcl_GetString(objv[2]); 6284 for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){ 6285 if( strcmp(zOpt, aOpt[i].zOptName)==0 ){ 6286 mask = aOpt[i].mask; 6287 break; 6288 } 6289 } 6290 if( onoff ) mask = ~mask; 6291 if( i>=sizeof(aOpt)/sizeof(aOpt[0]) ){ 6292 Tcl_AppendResult(interp, "unknown optimization - should be one of:", 6293 (char*)0); 6294 for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){ 6295 Tcl_AppendResult(interp, " ", aOpt[i].zOptName, (char*)0); 6296 } 6297 return TCL_ERROR; 6298 } 6299 sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask); 6300 return TCL_OK; 6301 } 6302 6303 typedef struct sqlite3_api_routines sqlite3_api_routines; 6304 /* 6305 ** load_static_extension DB NAME ... 6306 ** 6307 ** Load one or more statically linked extensions. 6308 */ 6309 static int tclLoadStaticExtensionCmd( 6310 void * clientData, 6311 Tcl_Interp *interp, 6312 int objc, 6313 Tcl_Obj *CONST objv[] 6314 ){ 6315 extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*); 6316 extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*); 6317 extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*); 6318 extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*); 6319 extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*); 6320 extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*); 6321 extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*); 6322 extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*); 6323 extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*); 6324 extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*); 6325 extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*); 6326 extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*); 6327 static const struct { 6328 const char *zExtName; 6329 int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*); 6330 } aExtension[] = { 6331 { "amatch", sqlite3_amatch_init }, 6332 { "closure", sqlite3_closure_init }, 6333 { "eval", sqlite3_eval_init }, 6334 { "fileio", sqlite3_fileio_init }, 6335 { "fuzzer", sqlite3_fuzzer_init }, 6336 { "ieee754", sqlite3_ieee_init }, 6337 { "nextchar", sqlite3_nextchar_init }, 6338 { "percentile", sqlite3_percentile_init }, 6339 { "regexp", sqlite3_regexp_init }, 6340 { "spellfix", sqlite3_spellfix_init }, 6341 { "totype", sqlite3_totype_init }, 6342 { "wholenumber", sqlite3_wholenumber_init }, 6343 }; 6344 sqlite3 *db; 6345 const char *zName; 6346 int i, j, rc; 6347 char *zErrMsg = 0; 6348 if( objc<3 ){ 6349 Tcl_WrongNumArgs(interp, 1, objv, "DB NAME ..."); 6350 return TCL_ERROR; 6351 } 6352 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 6353 for(j=2; j<objc; j++){ 6354 zName = Tcl_GetString(objv[j]); 6355 for(i=0; i<ArraySize(aExtension); i++){ 6356 if( strcmp(zName, aExtension[i].zExtName)==0 ) break; 6357 } 6358 if( i>=ArraySize(aExtension) ){ 6359 Tcl_AppendResult(interp, "no such extension: ", zName, (char*)0); 6360 return TCL_ERROR; 6361 } 6362 rc = aExtension[i].pInit(db, &zErrMsg, 0); 6363 if( rc!=SQLITE_OK || zErrMsg ){ 6364 Tcl_AppendResult(interp, "initialization of ", zName, " failed: ", zErrMsg, 6365 (char*)0); 6366 sqlite3_free(zErrMsg); 6367 return TCL_ERROR; 6368 } 6369 } 6370 return TCL_OK; 6371 } 6372 6373 /* 6374 ** sorter_test_fakeheap BOOL 6375 ** 6376 */ 6377 static int sorter_test_fakeheap( 6378 void * clientData, 6379 Tcl_Interp *interp, 6380 int objc, 6381 Tcl_Obj *CONST objv[] 6382 ){ 6383 int bArg; 6384 if( objc!=2 ){ 6385 Tcl_WrongNumArgs(interp, 1, objv, "BOOL"); 6386 return TCL_ERROR; 6387 } 6388 6389 if( Tcl_GetBooleanFromObj(interp, objv[1], &bArg) ){ 6390 return TCL_ERROR; 6391 } 6392 6393 if( bArg ){ 6394 if( sqlite3GlobalConfig.pHeap==0 ){ 6395 sqlite3GlobalConfig.pHeap = SQLITE_INT_TO_PTR(-1); 6396 } 6397 }else{ 6398 if( sqlite3GlobalConfig.pHeap==SQLITE_INT_TO_PTR(-1) ){ 6399 sqlite3GlobalConfig.pHeap = 0; 6400 } 6401 } 6402 6403 Tcl_ResetResult(interp); 6404 return TCL_OK; 6405 } 6406 6407 /* 6408 ** sorter_test_sort4_helper DB SQL1 NSTEP SQL2 6409 ** 6410 ** Compile SQL statement $SQL1 and step it $NSTEP times. For each row, 6411 ** check that the leftmost and rightmost columns returned are both integers, 6412 ** and that both contain the same value. 6413 ** 6414 ** Then execute statement $SQL2. Check that the statement returns the same 6415 ** set of integers in the same order as in the previous step (using $SQL1). 6416 */ 6417 static int sorter_test_sort4_helper( 6418 void * clientData, 6419 Tcl_Interp *interp, 6420 int objc, 6421 Tcl_Obj *CONST objv[] 6422 ){ 6423 const char *zSql1; 6424 const char *zSql2; 6425 int nStep; 6426 int iStep; 6427 int iCksum1 = 0; 6428 int iCksum2 = 0; 6429 int rc; 6430 int iB; 6431 sqlite3 *db; 6432 sqlite3_stmt *pStmt; 6433 6434 if( objc!=5 ){ 6435 Tcl_WrongNumArgs(interp, 1, objv, "DB SQL1 NSTEP SQL2"); 6436 return TCL_ERROR; 6437 } 6438 6439 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 6440 zSql1 = Tcl_GetString(objv[2]); 6441 if( Tcl_GetIntFromObj(interp, objv[3], &nStep) ) return TCL_ERROR; 6442 zSql2 = Tcl_GetString(objv[4]); 6443 6444 rc = sqlite3_prepare_v2(db, zSql1, -1, &pStmt, 0); 6445 if( rc!=SQLITE_OK ) goto sql_error; 6446 6447 iB = sqlite3_column_count(pStmt)-1; 6448 for(iStep=0; iStep<nStep && SQLITE_ROW==sqlite3_step(pStmt); iStep++){ 6449 int a = sqlite3_column_int(pStmt, 0); 6450 if( a!=sqlite3_column_int(pStmt, iB) ){ 6451 Tcl_AppendResult(interp, "data error: (a!=b)", 0); 6452 return TCL_ERROR; 6453 } 6454 6455 iCksum1 += (iCksum1 << 3) + a; 6456 } 6457 rc = sqlite3_finalize(pStmt); 6458 if( rc!=SQLITE_OK ) goto sql_error; 6459 6460 rc = sqlite3_prepare_v2(db, zSql2, -1, &pStmt, 0); 6461 if( rc!=SQLITE_OK ) goto sql_error; 6462 for(iStep=0; SQLITE_ROW==sqlite3_step(pStmt); iStep++){ 6463 int a = sqlite3_column_int(pStmt, 0); 6464 iCksum2 += (iCksum2 << 3) + a; 6465 } 6466 rc = sqlite3_finalize(pStmt); 6467 if( rc!=SQLITE_OK ) goto sql_error; 6468 6469 if( iCksum1!=iCksum2 ){ 6470 Tcl_AppendResult(interp, "checksum mismatch", 0); 6471 return TCL_ERROR; 6472 } 6473 6474 return TCL_OK; 6475 sql_error: 6476 Tcl_AppendResult(interp, "sql error: ", sqlite3_errmsg(db), 0); 6477 return TCL_ERROR; 6478 } 6479 6480 6481 #ifdef SQLITE_USER_AUTHENTICATION 6482 #include "sqlite3userauth.h" 6483 /* 6484 ** tclcmd: sqlite3_user_authenticate DB USERNAME PASSWORD 6485 */ 6486 static int test_user_authenticate( 6487 ClientData clientData, /* Unused */ 6488 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 6489 int objc, /* Number of arguments */ 6490 Tcl_Obj *CONST objv[] /* Command arguments */ 6491 ){ 6492 char *zUser = 0; 6493 char *zPasswd = 0; 6494 int nPasswd = 0; 6495 sqlite3 *db; 6496 int rc; 6497 6498 if( objc!=4 ){ 6499 Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD"); 6500 return TCL_ERROR; 6501 } 6502 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 6503 return TCL_ERROR; 6504 } 6505 zUser = Tcl_GetString(objv[2]); 6506 zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd); 6507 rc = sqlite3_user_authenticate(db, zUser, zPasswd, nPasswd); 6508 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 6509 return TCL_OK; 6510 } 6511 #endif /* SQLITE_USER_AUTHENTICATION */ 6512 6513 #ifdef SQLITE_USER_AUTHENTICATION 6514 /* 6515 ** tclcmd: sqlite3_user_add DB USERNAME PASSWORD ISADMIN 6516 */ 6517 static int test_user_add( 6518 ClientData clientData, /* Unused */ 6519 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 6520 int objc, /* Number of arguments */ 6521 Tcl_Obj *CONST objv[] /* Command arguments */ 6522 ){ 6523 char *zUser = 0; 6524 char *zPasswd = 0; 6525 int nPasswd = 0; 6526 int isAdmin = 0; 6527 sqlite3 *db; 6528 int rc; 6529 6530 if( objc!=5 ){ 6531 Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN"); 6532 return TCL_ERROR; 6533 } 6534 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 6535 return TCL_ERROR; 6536 } 6537 zUser = Tcl_GetString(objv[2]); 6538 zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd); 6539 Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin); 6540 rc = sqlite3_user_add(db, zUser, zPasswd, nPasswd, isAdmin); 6541 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 6542 return TCL_OK; 6543 } 6544 #endif /* SQLITE_USER_AUTHENTICATION */ 6545 6546 #ifdef SQLITE_USER_AUTHENTICATION 6547 /* 6548 ** tclcmd: sqlite3_user_change DB USERNAME PASSWORD ISADMIN 6549 */ 6550 static int test_user_change( 6551 ClientData clientData, /* Unused */ 6552 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 6553 int objc, /* Number of arguments */ 6554 Tcl_Obj *CONST objv[] /* Command arguments */ 6555 ){ 6556 char *zUser = 0; 6557 char *zPasswd = 0; 6558 int nPasswd = 0; 6559 int isAdmin = 0; 6560 sqlite3 *db; 6561 int rc; 6562 6563 if( objc!=5 ){ 6564 Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN"); 6565 return TCL_ERROR; 6566 } 6567 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 6568 return TCL_ERROR; 6569 } 6570 zUser = Tcl_GetString(objv[2]); 6571 zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd); 6572 Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin); 6573 rc = sqlite3_user_change(db, zUser, zPasswd, nPasswd, isAdmin); 6574 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 6575 return TCL_OK; 6576 } 6577 #endif /* SQLITE_USER_AUTHENTICATION */ 6578 6579 #ifdef SQLITE_USER_AUTHENTICATION 6580 /* 6581 ** tclcmd: sqlite3_user_delete DB USERNAME 6582 */ 6583 static int test_user_delete( 6584 ClientData clientData, /* Unused */ 6585 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 6586 int objc, /* Number of arguments */ 6587 Tcl_Obj *CONST objv[] /* Command arguments */ 6588 ){ 6589 char *zUser = 0; 6590 sqlite3 *db; 6591 int rc; 6592 6593 if( objc!=3 ){ 6594 Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME"); 6595 return TCL_ERROR; 6596 } 6597 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ 6598 return TCL_ERROR; 6599 } 6600 zUser = Tcl_GetString(objv[2]); 6601 rc = sqlite3_user_delete(db, zUser); 6602 Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); 6603 return TCL_OK; 6604 } 6605 #endif /* SQLITE_USER_AUTHENTICATION */ 6606 6607 /* 6608 ** Register commands with the TCL interpreter. 6609 */ 6610 int Sqlitetest1_Init(Tcl_Interp *interp){ 6611 extern int sqlite3_search_count; 6612 extern int sqlite3_found_count; 6613 extern int sqlite3_interrupt_count; 6614 extern int sqlite3_open_file_count; 6615 extern int sqlite3_sort_count; 6616 extern int sqlite3_current_time; 6617 #if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE 6618 extern int sqlite3_hostid_num; 6619 #endif 6620 extern int sqlite3_max_blobsize; 6621 extern int sqlite3BtreeSharedCacheReport(void*, 6622 Tcl_Interp*,int,Tcl_Obj*CONST*); 6623 static struct { 6624 char *zName; 6625 Tcl_CmdProc *xProc; 6626 } aCmd[] = { 6627 { "db_enter", (Tcl_CmdProc*)db_enter }, 6628 { "db_leave", (Tcl_CmdProc*)db_leave }, 6629 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int }, 6630 { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 }, 6631 { "sqlite3_mprintf_long", (Tcl_CmdProc*)sqlite3_mprintf_long }, 6632 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str }, 6633 { "sqlite3_snprintf_str", (Tcl_CmdProc*)sqlite3_snprintf_str }, 6634 { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly}, 6635 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double }, 6636 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled }, 6637 { "sqlite3_mprintf_hexdouble", (Tcl_CmdProc*)sqlite3_mprintf_hexdouble}, 6638 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z }, 6639 { "sqlite3_mprintf_n_test", (Tcl_CmdProc*)test_mprintf_n }, 6640 { "sqlite3_snprintf_int", (Tcl_CmdProc*)test_snprintf_int }, 6641 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid }, 6642 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf }, 6643 { "sqlite3_exec_hex", (Tcl_CmdProc*)test_exec_hex }, 6644 { "sqlite3_exec", (Tcl_CmdProc*)test_exec }, 6645 { "sqlite3_exec_nr", (Tcl_CmdProc*)test_exec_nr }, 6646 #ifndef SQLITE_OMIT_GET_TABLE 6647 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf }, 6648 #endif 6649 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close }, 6650 { "sqlite3_close_v2", (Tcl_CmdProc*)sqlite_test_close_v2 }, 6651 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function }, 6652 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate }, 6653 { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, 6654 { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, 6655 { "sqlite_bind", (Tcl_CmdProc*)test_bind }, 6656 { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, 6657 { "sqlite3_key", (Tcl_CmdProc*)test_key }, 6658 { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey }, 6659 { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic }, 6660 { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt }, 6661 { "sqlite_delete_function", (Tcl_CmdProc*)delete_function }, 6662 { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation }, 6663 { "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit }, 6664 { "sqlite3_stack_used", (Tcl_CmdProc*)test_stack_used }, 6665 { "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout }, 6666 { "printf", (Tcl_CmdProc*)test_printf }, 6667 { "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace }, 6668 { "clang_sanitize_address", (Tcl_CmdProc*)clang_sanitize_address }, 6669 }; 6670 static struct { 6671 char *zName; 6672 Tcl_ObjCmdProc *xProc; 6673 void *clientData; 6674 } aObjCmd[] = { 6675 { "sqlite3_connection_pointer", get_sqlite_pointer, 0 }, 6676 { "sqlite3_bind_int", test_bind_int, 0 }, 6677 { "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 }, 6678 { "sqlite3_bind_int64", test_bind_int64, 0 }, 6679 { "sqlite3_bind_double", test_bind_double, 0 }, 6680 { "sqlite3_bind_null", test_bind_null ,0 }, 6681 { "sqlite3_bind_text", test_bind_text ,0 }, 6682 { "sqlite3_bind_text16", test_bind_text16 ,0 }, 6683 { "sqlite3_bind_blob", test_bind_blob ,0 }, 6684 { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0}, 6685 { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0}, 6686 { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0}, 6687 { "sqlite3_clear_bindings", test_clear_bindings, 0}, 6688 { "sqlite3_sleep", test_sleep, 0}, 6689 { "sqlite3_errcode", test_errcode ,0 }, 6690 { "sqlite3_extended_errcode", test_ex_errcode ,0 }, 6691 { "sqlite3_errmsg", test_errmsg ,0 }, 6692 { "sqlite3_errmsg16", test_errmsg16 ,0 }, 6693 { "sqlite3_open", test_open ,0 }, 6694 { "sqlite3_open16", test_open16 ,0 }, 6695 { "sqlite3_open_v2", test_open_v2 ,0 }, 6696 { "sqlite3_complete16", test_complete16 ,0 }, 6697 6698 { "sqlite3_prepare", test_prepare ,0 }, 6699 { "sqlite3_prepare16", test_prepare16 ,0 }, 6700 { "sqlite3_prepare_v2", test_prepare_v2 ,0 }, 6701 { "sqlite3_prepare_tkt3134", test_prepare_tkt3134, 0}, 6702 { "sqlite3_prepare16_v2", test_prepare16_v2 ,0 }, 6703 { "sqlite3_finalize", test_finalize ,0 }, 6704 { "sqlite3_stmt_status", test_stmt_status ,0 }, 6705 { "sqlite3_reset", test_reset ,0 }, 6706 { "sqlite3_expired", test_expired ,0 }, 6707 { "sqlite3_transfer_bindings", test_transfer_bind ,0 }, 6708 { "sqlite3_changes", test_changes ,0 }, 6709 { "sqlite3_step", test_step ,0 }, 6710 { "sqlite3_sql", test_sql ,0 }, 6711 { "sqlite3_next_stmt", test_next_stmt ,0 }, 6712 { "sqlite3_stmt_readonly", test_stmt_readonly ,0 }, 6713 { "sqlite3_stmt_busy", test_stmt_busy ,0 }, 6714 { "uses_stmt_journal", uses_stmt_journal ,0 }, 6715 6716 { "sqlite3_release_memory", test_release_memory, 0}, 6717 { "sqlite3_db_release_memory", test_db_release_memory, 0}, 6718 { "sqlite3_db_filename", test_db_filename, 0}, 6719 { "sqlite3_db_readonly", test_db_readonly, 0}, 6720 { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0}, 6721 { "sqlite3_thread_cleanup", test_thread_cleanup, 0}, 6722 { "sqlite3_pager_refcounts", test_pager_refcounts, 0}, 6723 6724 { "sqlite3_load_extension", test_load_extension, 0}, 6725 { "sqlite3_enable_load_extension", test_enable_load, 0}, 6726 { "sqlite3_extended_result_codes", test_extended_result_codes, 0}, 6727 { "sqlite3_limit", test_limit, 0}, 6728 6729 { "save_prng_state", save_prng_state, 0 }, 6730 { "restore_prng_state", restore_prng_state, 0 }, 6731 { "reset_prng_state", reset_prng_state, 0 }, 6732 { "database_never_corrupt", database_never_corrupt, 0}, 6733 { "database_may_be_corrupt", database_may_be_corrupt, 0}, 6734 { "optimization_control", optimization_control,0}, 6735 #if SQLITE_OS_WIN 6736 { "lock_win32_file", win32_file_lock, 0 }, 6737 { "exists_win32_path", win32_exists_path, 0 }, 6738 { "find_win32_file", win32_find_file, 0 }, 6739 { "delete_win32_file", win32_delete_file, 0 }, 6740 { "make_win32_dir", win32_mkdir, 0 }, 6741 { "remove_win32_dir", win32_rmdir, 0 }, 6742 #endif 6743 { "tcl_objproc", runAsObjProc, 0 }, 6744 6745 /* sqlite3_column_*() API */ 6746 { "sqlite3_column_count", test_column_count ,0 }, 6747 { "sqlite3_data_count", test_data_count ,0 }, 6748 { "sqlite3_column_type", test_column_type ,0 }, 6749 { "sqlite3_column_blob", test_column_blob ,0 }, 6750 { "sqlite3_column_double", test_column_double ,0 }, 6751 { "sqlite3_column_int64", test_column_int64 ,0 }, 6752 { "sqlite3_column_text", test_stmt_utf8, (void*)sqlite3_column_text }, 6753 { "sqlite3_column_name", test_stmt_utf8, (void*)sqlite3_column_name }, 6754 { "sqlite3_column_int", test_stmt_int, (void*)sqlite3_column_int }, 6755 { "sqlite3_column_bytes", test_stmt_int, (void*)sqlite3_column_bytes}, 6756 #ifndef SQLITE_OMIT_DECLTYPE 6757 { "sqlite3_column_decltype",test_stmt_utf8,(void*)sqlite3_column_decltype}, 6758 #endif 6759 #ifdef SQLITE_ENABLE_COLUMN_METADATA 6760 { "sqlite3_column_database_name",test_stmt_utf8,(void*)sqlite3_column_database_name}, 6761 { "sqlite3_column_table_name",test_stmt_utf8,(void*)sqlite3_column_table_name}, 6762 { "sqlite3_column_origin_name",test_stmt_utf8,(void*)sqlite3_column_origin_name}, 6763 #endif 6764 6765 #ifndef SQLITE_OMIT_UTF16 6766 { "sqlite3_column_bytes16", test_stmt_int, (void*)sqlite3_column_bytes16 }, 6767 { "sqlite3_column_text16", test_stmt_utf16, (void*)sqlite3_column_text16}, 6768 { "sqlite3_column_name16", test_stmt_utf16, (void*)sqlite3_column_name16}, 6769 { "add_alignment_test_collations", add_alignment_test_collations, 0 }, 6770 #ifndef SQLITE_OMIT_DECLTYPE 6771 { "sqlite3_column_decltype16",test_stmt_utf16,(void*)sqlite3_column_decltype16}, 6772 #endif 6773 #ifdef SQLITE_ENABLE_COLUMN_METADATA 6774 {"sqlite3_column_database_name16", 6775 test_stmt_utf16, (void*)sqlite3_column_database_name16}, 6776 {"sqlite3_column_table_name16", test_stmt_utf16, (void*)sqlite3_column_table_name16}, 6777 {"sqlite3_column_origin_name16", test_stmt_utf16, (void*)sqlite3_column_origin_name16}, 6778 #endif 6779 #endif 6780 { "sqlite3_create_collation_v2", test_create_collation_v2, 0 }, 6781 { "sqlite3_global_recover", test_global_recover, 0 }, 6782 { "working_64bit_int", working_64bit_int, 0 }, 6783 { "vfs_unlink_test", vfs_unlink_test, 0 }, 6784 { "vfs_initfail_test", vfs_initfail_test, 0 }, 6785 { "vfs_unregister_all", vfs_unregister_all, 0 }, 6786 { "vfs_reregister_all", vfs_reregister_all, 0 }, 6787 { "file_control_test", file_control_test, 0 }, 6788 { "file_control_lasterrno_test", file_control_lasterrno_test, 0 }, 6789 { "file_control_lockproxy_test", file_control_lockproxy_test, 0 }, 6790 { "file_control_chunksize_test", file_control_chunksize_test, 0 }, 6791 { "file_control_sizehint_test", file_control_sizehint_test, 0 }, 6792 #if SQLITE_OS_WIN 6793 { "file_control_win32_av_retry", file_control_win32_av_retry, 0 }, 6794 { "file_control_win32_set_handle", file_control_win32_set_handle, 0 }, 6795 #endif 6796 { "file_control_persist_wal", file_control_persist_wal, 0 }, 6797 { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0}, 6798 { "file_control_vfsname", file_control_vfsname, 0 }, 6799 { "file_control_tempfilename", file_control_tempfilename, 0 }, 6800 { "sqlite3_vfs_list", vfs_list, 0 }, 6801 { "sqlite3_create_function_v2", test_create_function_v2, 0 }, 6802 6803 /* Functions from os.h */ 6804 #ifndef SQLITE_OMIT_UTF16 6805 { "add_test_collate", test_collate, 0 }, 6806 { "add_test_collate_needed", test_collate_needed, 0 }, 6807 { "add_test_function", test_function, 0 }, 6808 { "add_test_utf16bin_collate", test_utf16bin_collate, 0 }, 6809 #endif 6810 { "sqlite3_test_errstr", test_errstr, 0 }, 6811 { "tcl_variable_type", tcl_variable_type, 0 }, 6812 #ifndef SQLITE_OMIT_SHARED_CACHE 6813 { "sqlite3_enable_shared_cache", test_enable_shared, 0 }, 6814 { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0}, 6815 #endif 6816 { "sqlite3_libversion_number", test_libversion_number, 0 }, 6817 { "sqlite3_table_column_metadata", test_table_column_metadata, 0 }, 6818 #ifndef SQLITE_OMIT_INCRBLOB 6819 { "sqlite3_blob_reopen", test_blob_reopen, 0 }, 6820 #endif 6821 { "pcache_stats", test_pcache_stats, 0 }, 6822 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY 6823 { "sqlite3_unlock_notify", test_unlock_notify, 0 }, 6824 #endif 6825 { "sqlite3_wal_checkpoint", test_wal_checkpoint, 0 }, 6826 { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0 }, 6827 { "sqlite3_wal_autocheckpoint",test_wal_autocheckpoint, 0 }, 6828 { "test_sqlite3_log", test_sqlite3_log, 0 }, 6829 #ifndef SQLITE_OMIT_EXPLAIN 6830 { "print_explain_query_plan", test_print_eqp, 0 }, 6831 #endif 6832 { "sqlite3_test_control", test_test_control }, 6833 #if SQLITE_OS_UNIX 6834 { "getrusage", test_getrusage }, 6835 #endif 6836 { "load_static_extension", tclLoadStaticExtensionCmd }, 6837 { "sorter_test_fakeheap", sorter_test_fakeheap }, 6838 { "sorter_test_sort4_helper", sorter_test_sort4_helper }, 6839 #ifdef SQLITE_USER_AUTHENTICATION 6840 { "sqlite3_user_authenticate", test_user_authenticate, 0 }, 6841 { "sqlite3_user_add", test_user_add, 0 }, 6842 { "sqlite3_user_change", test_user_change, 0 }, 6843 { "sqlite3_user_delete", test_user_delete, 0 }, 6844 #endif 6845 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS 6846 { "sqlite3_stmt_scanstatus", test_stmt_scanstatus, 0 }, 6847 { "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset, 0 }, 6848 #endif 6849 6850 }; 6851 static int bitmask_size = sizeof(Bitmask)*8; 6852 int i; 6853 extern int sqlite3_sync_count, sqlite3_fullsync_count; 6854 extern int sqlite3_opentemp_count; 6855 extern int sqlite3_like_count; 6856 extern int sqlite3_xferopt_count; 6857 extern int sqlite3_pager_readdb_count; 6858 extern int sqlite3_pager_writedb_count; 6859 extern int sqlite3_pager_writej_count; 6860 #if SQLITE_OS_WIN 6861 extern LONG volatile sqlite3_os_type; 6862 #endif 6863 #ifdef SQLITE_DEBUG 6864 extern int sqlite3WhereTrace; 6865 extern int sqlite3OSTrace; 6866 extern int sqlite3WalTrace; 6867 #endif 6868 #ifdef SQLITE_TEST 6869 #ifdef SQLITE_ENABLE_FTS3 6870 extern int sqlite3_fts3_enable_parentheses; 6871 #endif 6872 #endif 6873 6874 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ 6875 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); 6876 } 6877 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ 6878 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 6879 aObjCmd[i].xProc, aObjCmd[i].clientData, 0); 6880 } 6881 Tcl_LinkVar(interp, "sqlite_search_count", 6882 (char*)&sqlite3_search_count, TCL_LINK_INT); 6883 Tcl_LinkVar(interp, "sqlite_found_count", 6884 (char*)&sqlite3_found_count, TCL_LINK_INT); 6885 Tcl_LinkVar(interp, "sqlite_sort_count", 6886 (char*)&sqlite3_sort_count, TCL_LINK_INT); 6887 Tcl_LinkVar(interp, "sqlite3_max_blobsize", 6888 (char*)&sqlite3_max_blobsize, TCL_LINK_INT); 6889 Tcl_LinkVar(interp, "sqlite_like_count", 6890 (char*)&sqlite3_like_count, TCL_LINK_INT); 6891 Tcl_LinkVar(interp, "sqlite_interrupt_count", 6892 (char*)&sqlite3_interrupt_count, TCL_LINK_INT); 6893 Tcl_LinkVar(interp, "sqlite_open_file_count", 6894 (char*)&sqlite3_open_file_count, TCL_LINK_INT); 6895 Tcl_LinkVar(interp, "sqlite_current_time", 6896 (char*)&sqlite3_current_time, TCL_LINK_INT); 6897 #if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE 6898 Tcl_LinkVar(interp, "sqlite_hostid_num", 6899 (char*)&sqlite3_hostid_num, TCL_LINK_INT); 6900 #endif 6901 Tcl_LinkVar(interp, "sqlite3_xferopt_count", 6902 (char*)&sqlite3_xferopt_count, TCL_LINK_INT); 6903 Tcl_LinkVar(interp, "sqlite3_pager_readdb_count", 6904 (char*)&sqlite3_pager_readdb_count, TCL_LINK_INT); 6905 Tcl_LinkVar(interp, "sqlite3_pager_writedb_count", 6906 (char*)&sqlite3_pager_writedb_count, TCL_LINK_INT); 6907 Tcl_LinkVar(interp, "sqlite3_pager_writej_count", 6908 (char*)&sqlite3_pager_writej_count, TCL_LINK_INT); 6909 #ifndef SQLITE_OMIT_UTF16 6910 Tcl_LinkVar(interp, "unaligned_string_counter", 6911 (char*)&unaligned_string_counter, TCL_LINK_INT); 6912 #endif 6913 #ifndef SQLITE_OMIT_UTF16 6914 Tcl_LinkVar(interp, "sqlite_last_needed_collation", 6915 (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY); 6916 #endif 6917 #if SQLITE_OS_WIN 6918 Tcl_LinkVar(interp, "sqlite_os_type", 6919 (char*)&sqlite3_os_type, TCL_LINK_LONG); 6920 #endif 6921 #ifdef SQLITE_TEST 6922 { 6923 static const char *query_plan = "*** OBSOLETE VARIABLE ***"; 6924 Tcl_LinkVar(interp, "sqlite_query_plan", 6925 (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY); 6926 } 6927 #endif 6928 #ifdef SQLITE_DEBUG 6929 Tcl_LinkVar(interp, "sqlite_where_trace", 6930 (char*)&sqlite3WhereTrace, TCL_LINK_INT); 6931 Tcl_LinkVar(interp, "sqlite_os_trace", 6932 (char*)&sqlite3OSTrace, TCL_LINK_INT); 6933 #ifndef SQLITE_OMIT_WAL 6934 Tcl_LinkVar(interp, "sqlite_wal_trace", 6935 (char*)&sqlite3WalTrace, TCL_LINK_INT); 6936 #endif 6937 #endif 6938 #ifndef SQLITE_OMIT_DISKIO 6939 Tcl_LinkVar(interp, "sqlite_opentemp_count", 6940 (char*)&sqlite3_opentemp_count, TCL_LINK_INT); 6941 #endif 6942 Tcl_LinkVar(interp, "sqlite_static_bind_value", 6943 (char*)&sqlite_static_bind_value, TCL_LINK_STRING); 6944 Tcl_LinkVar(interp, "sqlite_static_bind_nbyte", 6945 (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT); 6946 Tcl_LinkVar(interp, "sqlite_temp_directory", 6947 (char*)&sqlite3_temp_directory, TCL_LINK_STRING); 6948 Tcl_LinkVar(interp, "sqlite_data_directory", 6949 (char*)&sqlite3_data_directory, TCL_LINK_STRING); 6950 Tcl_LinkVar(interp, "bitmask_size", 6951 (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY); 6952 Tcl_LinkVar(interp, "sqlite_sync_count", 6953 (char*)&sqlite3_sync_count, TCL_LINK_INT); 6954 Tcl_LinkVar(interp, "sqlite_fullsync_count", 6955 (char*)&sqlite3_fullsync_count, TCL_LINK_INT); 6956 #if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST) 6957 Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses", 6958 (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT); 6959 #endif 6960 return TCL_OK; 6961 } 6962