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