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