1 /* 2 ** 2001 September 15 3 ** 4 ** The author disclaims copyright to this source code. In place of 5 ** a legal notice, here is a blessing: 6 ** 7 ** May you do good and not evil. 8 ** May you find forgiveness for yourself and forgive others. 9 ** May you share freely, never taking more than you give. 10 ** 11 ************************************************************************* 12 ** Code for testing the pager.c module in SQLite. This code 13 ** is not included in the SQLite library. It is used for automated 14 ** testing of the SQLite library. 15 ** 16 ** $Id: test2.c,v 1.72 2009/07/16 18:21:18 drh Exp $ 17 */ 18 #include "sqliteInt.h" 19 #include "tcl.h" 20 #include <stdlib.h> 21 #include <string.h> 22 #include <ctype.h> 23 24 /* 25 ** Interpret an SQLite error number 26 */ 27 static char *errorName(int rc){ 28 char *zName; 29 switch( rc ){ 30 case SQLITE_OK: zName = "SQLITE_OK"; break; 31 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; 32 case SQLITE_PERM: zName = "SQLITE_PERM"; break; 33 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; 34 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; 35 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; 36 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; 37 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; 38 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; 39 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; 40 case SQLITE_FULL: zName = "SQLITE_FULL"; break; 41 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; 42 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break; 43 case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break; 44 case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break; 45 case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break; 46 case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break; 47 case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break; 48 case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break; 49 default: zName = "SQLITE_Unknown"; break; 50 } 51 return zName; 52 } 53 54 /* 55 ** Page size and reserved size used for testing. 56 */ 57 static int test_pagesize = 1024; 58 59 /* 60 ** Usage: pager_open FILENAME N-PAGE 61 ** 62 ** Open a new pager 63 */ 64 static int pager_open( 65 void *NotUsed, 66 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 67 int argc, /* Number of arguments */ 68 const char **argv /* Text of each argument */ 69 ){ 70 u16 pageSize; 71 Pager *pPager; 72 int nPage; 73 int rc; 74 char zBuf[100]; 75 if( argc!=3 ){ 76 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 77 " FILENAME N-PAGE\"", 0); 78 return TCL_ERROR; 79 } 80 if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR; 81 rc = sqlite3PagerOpen(sqlite3_vfs_find(0), &pPager, argv[1], 0, 0, 82 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB); 83 if( rc!=SQLITE_OK ){ 84 Tcl_AppendResult(interp, errorName(rc), 0); 85 return TCL_ERROR; 86 } 87 sqlite3PagerSetCachesize(pPager, nPage); 88 pageSize = test_pagesize; 89 sqlite3PagerSetPagesize(pPager, &pageSize, -1); 90 sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPager); 91 Tcl_AppendResult(interp, zBuf, 0); 92 return TCL_OK; 93 } 94 95 /* 96 ** Usage: pager_close ID 97 ** 98 ** Close the given pager. 99 */ 100 static int pager_close( 101 void *NotUsed, 102 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 103 int argc, /* Number of arguments */ 104 const char **argv /* Text of each argument */ 105 ){ 106 Pager *pPager; 107 int rc; 108 if( argc!=2 ){ 109 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 110 " ID\"", 0); 111 return TCL_ERROR; 112 } 113 pPager = sqlite3TestTextToPtr(argv[1]); 114 rc = sqlite3PagerClose(pPager); 115 if( rc!=SQLITE_OK ){ 116 Tcl_AppendResult(interp, errorName(rc), 0); 117 return TCL_ERROR; 118 } 119 return TCL_OK; 120 } 121 122 /* 123 ** Usage: pager_rollback ID 124 ** 125 ** Rollback changes 126 */ 127 static int pager_rollback( 128 void *NotUsed, 129 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 130 int argc, /* Number of arguments */ 131 const char **argv /* Text of each argument */ 132 ){ 133 Pager *pPager; 134 int rc; 135 if( argc!=2 ){ 136 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 137 " ID\"", 0); 138 return TCL_ERROR; 139 } 140 pPager = sqlite3TestTextToPtr(argv[1]); 141 rc = sqlite3PagerRollback(pPager); 142 if( rc!=SQLITE_OK ){ 143 Tcl_AppendResult(interp, errorName(rc), 0); 144 return TCL_ERROR; 145 } 146 return TCL_OK; 147 } 148 149 /* 150 ** Usage: pager_commit ID 151 ** 152 ** Commit all changes 153 */ 154 static int pager_commit( 155 void *NotUsed, 156 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 157 int argc, /* Number of arguments */ 158 const char **argv /* Text of each argument */ 159 ){ 160 Pager *pPager; 161 int rc; 162 if( argc!=2 ){ 163 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 164 " ID\"", 0); 165 return TCL_ERROR; 166 } 167 pPager = sqlite3TestTextToPtr(argv[1]); 168 rc = sqlite3PagerCommitPhaseOne(pPager, 0, 0); 169 if( rc!=SQLITE_OK ){ 170 Tcl_AppendResult(interp, errorName(rc), 0); 171 return TCL_ERROR; 172 } 173 rc = sqlite3PagerCommitPhaseTwo(pPager); 174 if( rc!=SQLITE_OK ){ 175 Tcl_AppendResult(interp, errorName(rc), 0); 176 return TCL_ERROR; 177 } 178 return TCL_OK; 179 } 180 181 /* 182 ** Usage: pager_stmt_begin ID 183 ** 184 ** Start a new checkpoint. 185 */ 186 static int pager_stmt_begin( 187 void *NotUsed, 188 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 189 int argc, /* Number of arguments */ 190 const char **argv /* Text of each argument */ 191 ){ 192 Pager *pPager; 193 int rc; 194 if( argc!=2 ){ 195 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 196 " ID\"", 0); 197 return TCL_ERROR; 198 } 199 pPager = sqlite3TestTextToPtr(argv[1]); 200 rc = sqlite3PagerOpenSavepoint(pPager, 1); 201 if( rc!=SQLITE_OK ){ 202 Tcl_AppendResult(interp, errorName(rc), 0); 203 return TCL_ERROR; 204 } 205 return TCL_OK; 206 } 207 208 /* 209 ** Usage: pager_stmt_rollback ID 210 ** 211 ** Rollback changes to a checkpoint 212 */ 213 static int pager_stmt_rollback( 214 void *NotUsed, 215 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 216 int argc, /* Number of arguments */ 217 const char **argv /* Text of each argument */ 218 ){ 219 Pager *pPager; 220 int rc; 221 if( argc!=2 ){ 222 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 223 " ID\"", 0); 224 return TCL_ERROR; 225 } 226 pPager = sqlite3TestTextToPtr(argv[1]); 227 rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, 0); 228 sqlite3PagerSavepoint(pPager, SAVEPOINT_RELEASE, 0); 229 if( rc!=SQLITE_OK ){ 230 Tcl_AppendResult(interp, errorName(rc), 0); 231 return TCL_ERROR; 232 } 233 return TCL_OK; 234 } 235 236 /* 237 ** Usage: pager_stmt_commit ID 238 ** 239 ** Commit changes to a checkpoint 240 */ 241 static int pager_stmt_commit( 242 void *NotUsed, 243 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 244 int argc, /* Number of arguments */ 245 const char **argv /* Text of each argument */ 246 ){ 247 Pager *pPager; 248 int rc; 249 if( argc!=2 ){ 250 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 251 " ID\"", 0); 252 return TCL_ERROR; 253 } 254 pPager = sqlite3TestTextToPtr(argv[1]); 255 rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_RELEASE, 0); 256 if( rc!=SQLITE_OK ){ 257 Tcl_AppendResult(interp, errorName(rc), 0); 258 return TCL_ERROR; 259 } 260 return TCL_OK; 261 } 262 263 /* 264 ** Usage: pager_stats ID 265 ** 266 ** Return pager statistics. 267 */ 268 static int pager_stats( 269 void *NotUsed, 270 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 271 int argc, /* Number of arguments */ 272 const char **argv /* Text of each argument */ 273 ){ 274 Pager *pPager; 275 int i, *a; 276 if( argc!=2 ){ 277 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 278 " ID\"", 0); 279 return TCL_ERROR; 280 } 281 pPager = sqlite3TestTextToPtr(argv[1]); 282 a = sqlite3PagerStats(pPager); 283 for(i=0; i<9; i++){ 284 static char *zName[] = { 285 "ref", "page", "max", "size", "state", "err", 286 "hit", "miss", "ovfl", 287 }; 288 char zBuf[100]; 289 Tcl_AppendElement(interp, zName[i]); 290 sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",a[i]); 291 Tcl_AppendElement(interp, zBuf); 292 } 293 return TCL_OK; 294 } 295 296 /* 297 ** Usage: pager_pagecount ID 298 ** 299 ** Return the size of the database file. 300 */ 301 static int pager_pagecount( 302 void *NotUsed, 303 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 304 int argc, /* Number of arguments */ 305 const char **argv /* Text of each argument */ 306 ){ 307 Pager *pPager; 308 char zBuf[100]; 309 int nPage; 310 if( argc!=2 ){ 311 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 312 " ID\"", 0); 313 return TCL_ERROR; 314 } 315 pPager = sqlite3TestTextToPtr(argv[1]); 316 sqlite3PagerPagecount(pPager, &nPage); 317 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nPage); 318 Tcl_AppendResult(interp, zBuf, 0); 319 return TCL_OK; 320 } 321 322 /* 323 ** Usage: page_get ID PGNO 324 ** 325 ** Return a pointer to a page from the database. 326 */ 327 static int page_get( 328 void *NotUsed, 329 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 330 int argc, /* Number of arguments */ 331 const char **argv /* Text of each argument */ 332 ){ 333 Pager *pPager; 334 char zBuf[100]; 335 DbPage *pPage; 336 int pgno; 337 int rc; 338 if( argc!=3 ){ 339 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 340 " ID PGNO\"", 0); 341 return TCL_ERROR; 342 } 343 pPager = sqlite3TestTextToPtr(argv[1]); 344 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; 345 rc = sqlite3PagerGet(pPager, pgno, &pPage); 346 if( rc!=SQLITE_OK ){ 347 Tcl_AppendResult(interp, errorName(rc), 0); 348 return TCL_ERROR; 349 } 350 sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage); 351 Tcl_AppendResult(interp, zBuf, 0); 352 return TCL_OK; 353 } 354 355 /* 356 ** Usage: page_lookup ID PGNO 357 ** 358 ** Return a pointer to a page if the page is already in cache. 359 ** If not in cache, return an empty string. 360 */ 361 static int page_lookup( 362 void *NotUsed, 363 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 364 int argc, /* Number of arguments */ 365 const char **argv /* Text of each argument */ 366 ){ 367 Pager *pPager; 368 char zBuf[100]; 369 DbPage *pPage; 370 int pgno; 371 if( argc!=3 ){ 372 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 373 " ID PGNO\"", 0); 374 return TCL_ERROR; 375 } 376 pPager = sqlite3TestTextToPtr(argv[1]); 377 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; 378 pPage = sqlite3PagerLookup(pPager, pgno); 379 if( pPage ){ 380 sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage); 381 Tcl_AppendResult(interp, zBuf, 0); 382 } 383 return TCL_OK; 384 } 385 386 /* 387 ** Usage: pager_truncate ID PGNO 388 */ 389 static int pager_truncate( 390 void *NotUsed, 391 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 392 int argc, /* Number of arguments */ 393 const char **argv /* Text of each argument */ 394 ){ 395 Pager *pPager; 396 int pgno; 397 if( argc!=3 ){ 398 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 399 " ID PGNO\"", 0); 400 return TCL_ERROR; 401 } 402 pPager = sqlite3TestTextToPtr(argv[1]); 403 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; 404 sqlite3PagerTruncateImage(pPager, pgno); 405 return TCL_OK; 406 } 407 408 409 /* 410 ** Usage: page_unref PAGE 411 ** 412 ** Drop a pointer to a page. 413 */ 414 static int page_unref( 415 void *NotUsed, 416 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 417 int argc, /* Number of arguments */ 418 const char **argv /* Text of each argument */ 419 ){ 420 DbPage *pPage; 421 if( argc!=2 ){ 422 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 423 " PAGE\"", 0); 424 return TCL_ERROR; 425 } 426 pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]); 427 sqlite3PagerUnref(pPage); 428 return TCL_OK; 429 } 430 431 /* 432 ** Usage: page_read PAGE 433 ** 434 ** Return the content of a page 435 */ 436 static int page_read( 437 void *NotUsed, 438 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 439 int argc, /* Number of arguments */ 440 const char **argv /* Text of each argument */ 441 ){ 442 char zBuf[100]; 443 DbPage *pPage; 444 if( argc!=2 ){ 445 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 446 " PAGE\"", 0); 447 return TCL_ERROR; 448 } 449 pPage = sqlite3TestTextToPtr(argv[1]); 450 memcpy(zBuf, sqlite3PagerGetData(pPage), sizeof(zBuf)); 451 Tcl_AppendResult(interp, zBuf, 0); 452 return TCL_OK; 453 } 454 455 /* 456 ** Usage: page_number PAGE 457 ** 458 ** Return the page number for a page. 459 */ 460 static int page_number( 461 void *NotUsed, 462 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 463 int argc, /* Number of arguments */ 464 const char **argv /* Text of each argument */ 465 ){ 466 char zBuf[100]; 467 DbPage *pPage; 468 if( argc!=2 ){ 469 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 470 " PAGE\"", 0); 471 return TCL_ERROR; 472 } 473 pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]); 474 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3PagerPagenumber(pPage)); 475 Tcl_AppendResult(interp, zBuf, 0); 476 return TCL_OK; 477 } 478 479 /* 480 ** Usage: page_write PAGE DATA 481 ** 482 ** Write something into a page. 483 */ 484 static int page_write( 485 void *NotUsed, 486 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 487 int argc, /* Number of arguments */ 488 const char **argv /* Text of each argument */ 489 ){ 490 DbPage *pPage; 491 char *pData; 492 int rc; 493 if( argc!=3 ){ 494 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 495 " PAGE DATA\"", 0); 496 return TCL_ERROR; 497 } 498 pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]); 499 rc = sqlite3PagerWrite(pPage); 500 if( rc!=SQLITE_OK ){ 501 Tcl_AppendResult(interp, errorName(rc), 0); 502 return TCL_ERROR; 503 } 504 pData = sqlite3PagerGetData(pPage); 505 strncpy(pData, argv[2], test_pagesize-1); 506 pData[test_pagesize-1] = 0; 507 return TCL_OK; 508 } 509 510 #ifndef SQLITE_OMIT_DISKIO 511 /* 512 ** Usage: fake_big_file N FILENAME 513 ** 514 ** Write a few bytes at the N megabyte point of FILENAME. This will 515 ** create a large file. If the file was a valid SQLite database, then 516 ** the next time the database is opened, SQLite will begin allocating 517 ** new pages after N. If N is 2096 or bigger, this will test the 518 ** ability of SQLite to write to large files. 519 */ 520 static int fake_big_file( 521 void *NotUsed, 522 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 523 int argc, /* Number of arguments */ 524 const char **argv /* Text of each argument */ 525 ){ 526 sqlite3_vfs *pVfs; 527 sqlite3_file *fd = 0; 528 int rc; 529 int n; 530 i64 offset; 531 if( argc!=3 ){ 532 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 533 " N-MEGABYTES FILE\"", 0); 534 return TCL_ERROR; 535 } 536 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; 537 538 pVfs = sqlite3_vfs_find(0); 539 rc = sqlite3OsOpenMalloc(pVfs, argv[2], &fd, 540 (SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB), 0 541 ); 542 if( rc ){ 543 Tcl_AppendResult(interp, "open failed: ", errorName(rc), 0); 544 return TCL_ERROR; 545 } 546 offset = n; 547 offset *= 1024*1024; 548 rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset); 549 sqlite3OsCloseFree(fd); 550 if( rc ){ 551 Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0); 552 return TCL_ERROR; 553 } 554 return TCL_OK; 555 } 556 #endif 557 558 559 /* 560 ** test_control_pending_byte PENDING_BYTE 561 ** 562 ** Set the PENDING_BYTE using the sqlite3_test_control() interface. 563 */ 564 static int testPendingByte( 565 void *NotUsed, 566 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 567 int argc, /* Number of arguments */ 568 const char **argv /* Text of each argument */ 569 ){ 570 int pbyte; 571 int rc; 572 if( argc!=2 ){ 573 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 574 " PENDING-BYTE\"", (void*)0); 575 } 576 if( Tcl_GetInt(interp, argv[1], &pbyte) ) return TCL_ERROR; 577 rc = sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, pbyte); 578 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 579 return TCL_OK; 580 } 581 582 /* 583 ** sqlite3BitvecBuiltinTest SIZE PROGRAM 584 ** 585 ** Invoke the SQLITE_TESTCTRL_BITVEC_TEST operator on test_control. 586 ** See comments on sqlite3BitvecBuiltinTest() for additional information. 587 */ 588 static int testBitvecBuiltinTest( 589 void *NotUsed, 590 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 591 int argc, /* Number of arguments */ 592 const char **argv /* Text of each argument */ 593 ){ 594 int sz, rc; 595 int nProg = 0; 596 int aProg[100]; 597 const char *z; 598 if( argc!=3 ){ 599 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 600 " SIZE PROGRAM\"", (void*)0); 601 } 602 if( Tcl_GetInt(interp, argv[1], &sz) ) return TCL_ERROR; 603 z = argv[2]; 604 while( nProg<99 && *z ){ 605 while( *z && !sqlite3Isdigit(*z) ){ z++; } 606 if( *z==0 ) break; 607 aProg[nProg++] = atoi(z); 608 while( sqlite3Isdigit(*z) ){ z++; } 609 } 610 aProg[nProg] = 0; 611 rc = sqlite3_test_control(SQLITE_TESTCTRL_BITVEC_TEST, sz, aProg); 612 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 613 return TCL_OK; 614 } 615 616 /* 617 ** Register commands with the TCL interpreter. 618 */ 619 int Sqlitetest2_Init(Tcl_Interp *interp){ 620 extern int sqlite3_io_error_persist; 621 extern int sqlite3_io_error_pending; 622 extern int sqlite3_io_error_hit; 623 extern int sqlite3_io_error_hardhit; 624 extern int sqlite3_diskfull_pending; 625 extern int sqlite3_diskfull; 626 static struct { 627 char *zName; 628 Tcl_CmdProc *xProc; 629 } aCmd[] = { 630 { "pager_open", (Tcl_CmdProc*)pager_open }, 631 { "pager_close", (Tcl_CmdProc*)pager_close }, 632 { "pager_commit", (Tcl_CmdProc*)pager_commit }, 633 { "pager_rollback", (Tcl_CmdProc*)pager_rollback }, 634 { "pager_stmt_begin", (Tcl_CmdProc*)pager_stmt_begin }, 635 { "pager_stmt_commit", (Tcl_CmdProc*)pager_stmt_commit }, 636 { "pager_stmt_rollback", (Tcl_CmdProc*)pager_stmt_rollback }, 637 { "pager_stats", (Tcl_CmdProc*)pager_stats }, 638 { "pager_pagecount", (Tcl_CmdProc*)pager_pagecount }, 639 { "page_get", (Tcl_CmdProc*)page_get }, 640 { "page_lookup", (Tcl_CmdProc*)page_lookup }, 641 { "page_unref", (Tcl_CmdProc*)page_unref }, 642 { "page_read", (Tcl_CmdProc*)page_read }, 643 { "page_write", (Tcl_CmdProc*)page_write }, 644 { "page_number", (Tcl_CmdProc*)page_number }, 645 { "pager_truncate", (Tcl_CmdProc*)pager_truncate }, 646 #ifndef SQLITE_OMIT_DISKIO 647 { "fake_big_file", (Tcl_CmdProc*)fake_big_file }, 648 #endif 649 { "sqlite3BitvecBuiltinTest",(Tcl_CmdProc*)testBitvecBuiltinTest }, 650 { "sqlite3_test_control_pending_byte", (Tcl_CmdProc*)testPendingByte }, 651 }; 652 int i; 653 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ 654 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); 655 } 656 Tcl_LinkVar(interp, "sqlite_io_error_pending", 657 (char*)&sqlite3_io_error_pending, TCL_LINK_INT); 658 Tcl_LinkVar(interp, "sqlite_io_error_persist", 659 (char*)&sqlite3_io_error_persist, TCL_LINK_INT); 660 Tcl_LinkVar(interp, "sqlite_io_error_hit", 661 (char*)&sqlite3_io_error_hit, TCL_LINK_INT); 662 Tcl_LinkVar(interp, "sqlite_io_error_hardhit", 663 (char*)&sqlite3_io_error_hardhit, TCL_LINK_INT); 664 Tcl_LinkVar(interp, "sqlite_diskfull_pending", 665 (char*)&sqlite3_diskfull_pending, TCL_LINK_INT); 666 Tcl_LinkVar(interp, "sqlite_diskfull", 667 (char*)&sqlite3_diskfull, TCL_LINK_INT); 668 Tcl_LinkVar(interp, "sqlite_pending_byte", 669 (char*)&sqlite3PendingByte, TCL_LINK_INT | TCL_LINK_READ_ONLY); 670 return TCL_OK; 671 } 672