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.73 2009/07/21 19:25:24 danielk1977 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 = sqlite3PagerSharedLock(pPager); 346 if( rc==SQLITE_OK ){ 347 rc = sqlite3PagerGet(pPager, pgno, &pPage); 348 } 349 if( rc!=SQLITE_OK ){ 350 Tcl_AppendResult(interp, errorName(rc), 0); 351 return TCL_ERROR; 352 } 353 sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage); 354 Tcl_AppendResult(interp, zBuf, 0); 355 return TCL_OK; 356 } 357 358 /* 359 ** Usage: page_lookup ID PGNO 360 ** 361 ** Return a pointer to a page if the page is already in cache. 362 ** If not in cache, return an empty string. 363 */ 364 static int page_lookup( 365 void *NotUsed, 366 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 367 int argc, /* Number of arguments */ 368 const char **argv /* Text of each argument */ 369 ){ 370 Pager *pPager; 371 char zBuf[100]; 372 DbPage *pPage; 373 int pgno; 374 if( argc!=3 ){ 375 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 376 " ID PGNO\"", 0); 377 return TCL_ERROR; 378 } 379 pPager = sqlite3TestTextToPtr(argv[1]); 380 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; 381 pPage = sqlite3PagerLookup(pPager, pgno); 382 if( pPage ){ 383 sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage); 384 Tcl_AppendResult(interp, zBuf, 0); 385 } 386 return TCL_OK; 387 } 388 389 /* 390 ** Usage: pager_truncate ID PGNO 391 */ 392 static int pager_truncate( 393 void *NotUsed, 394 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 395 int argc, /* Number of arguments */ 396 const char **argv /* Text of each argument */ 397 ){ 398 Pager *pPager; 399 int pgno; 400 if( argc!=3 ){ 401 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 402 " ID PGNO\"", 0); 403 return TCL_ERROR; 404 } 405 pPager = sqlite3TestTextToPtr(argv[1]); 406 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; 407 sqlite3PagerTruncateImage(pPager, pgno); 408 return TCL_OK; 409 } 410 411 412 /* 413 ** Usage: page_unref PAGE 414 ** 415 ** Drop a pointer to a page. 416 */ 417 static int page_unref( 418 void *NotUsed, 419 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 420 int argc, /* Number of arguments */ 421 const char **argv /* Text of each argument */ 422 ){ 423 DbPage *pPage; 424 if( argc!=2 ){ 425 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 426 " PAGE\"", 0); 427 return TCL_ERROR; 428 } 429 pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]); 430 sqlite3PagerUnref(pPage); 431 return TCL_OK; 432 } 433 434 /* 435 ** Usage: page_read PAGE 436 ** 437 ** Return the content of a page 438 */ 439 static int page_read( 440 void *NotUsed, 441 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 442 int argc, /* Number of arguments */ 443 const char **argv /* Text of each argument */ 444 ){ 445 char zBuf[100]; 446 DbPage *pPage; 447 if( argc!=2 ){ 448 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 449 " PAGE\"", 0); 450 return TCL_ERROR; 451 } 452 pPage = sqlite3TestTextToPtr(argv[1]); 453 memcpy(zBuf, sqlite3PagerGetData(pPage), sizeof(zBuf)); 454 Tcl_AppendResult(interp, zBuf, 0); 455 return TCL_OK; 456 } 457 458 /* 459 ** Usage: page_number PAGE 460 ** 461 ** Return the page number for a page. 462 */ 463 static int page_number( 464 void *NotUsed, 465 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 466 int argc, /* Number of arguments */ 467 const char **argv /* Text of each argument */ 468 ){ 469 char zBuf[100]; 470 DbPage *pPage; 471 if( argc!=2 ){ 472 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 473 " PAGE\"", 0); 474 return TCL_ERROR; 475 } 476 pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]); 477 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3PagerPagenumber(pPage)); 478 Tcl_AppendResult(interp, zBuf, 0); 479 return TCL_OK; 480 } 481 482 /* 483 ** Usage: page_write PAGE DATA 484 ** 485 ** Write something into a page. 486 */ 487 static int page_write( 488 void *NotUsed, 489 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 490 int argc, /* Number of arguments */ 491 const char **argv /* Text of each argument */ 492 ){ 493 DbPage *pPage; 494 char *pData; 495 int rc; 496 if( argc!=3 ){ 497 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 498 " PAGE DATA\"", 0); 499 return TCL_ERROR; 500 } 501 pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]); 502 rc = sqlite3PagerWrite(pPage); 503 if( rc!=SQLITE_OK ){ 504 Tcl_AppendResult(interp, errorName(rc), 0); 505 return TCL_ERROR; 506 } 507 pData = sqlite3PagerGetData(pPage); 508 strncpy(pData, argv[2], test_pagesize-1); 509 pData[test_pagesize-1] = 0; 510 return TCL_OK; 511 } 512 513 #ifndef SQLITE_OMIT_DISKIO 514 /* 515 ** Usage: fake_big_file N FILENAME 516 ** 517 ** Write a few bytes at the N megabyte point of FILENAME. This will 518 ** create a large file. If the file was a valid SQLite database, then 519 ** the next time the database is opened, SQLite will begin allocating 520 ** new pages after N. If N is 2096 or bigger, this will test the 521 ** ability of SQLite to write to large files. 522 */ 523 static int fake_big_file( 524 void *NotUsed, 525 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 526 int argc, /* Number of arguments */ 527 const char **argv /* Text of each argument */ 528 ){ 529 sqlite3_vfs *pVfs; 530 sqlite3_file *fd = 0; 531 int rc; 532 int n; 533 i64 offset; 534 if( argc!=3 ){ 535 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 536 " N-MEGABYTES FILE\"", 0); 537 return TCL_ERROR; 538 } 539 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; 540 541 pVfs = sqlite3_vfs_find(0); 542 rc = sqlite3OsOpenMalloc(pVfs, argv[2], &fd, 543 (SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB), 0 544 ); 545 if( rc ){ 546 Tcl_AppendResult(interp, "open failed: ", errorName(rc), 0); 547 return TCL_ERROR; 548 } 549 offset = n; 550 offset *= 1024*1024; 551 rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset); 552 sqlite3OsCloseFree(fd); 553 if( rc ){ 554 Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0); 555 return TCL_ERROR; 556 } 557 return TCL_OK; 558 } 559 #endif 560 561 562 /* 563 ** test_control_pending_byte PENDING_BYTE 564 ** 565 ** Set the PENDING_BYTE using the sqlite3_test_control() interface. 566 */ 567 static int testPendingByte( 568 void *NotUsed, 569 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 570 int argc, /* Number of arguments */ 571 const char **argv /* Text of each argument */ 572 ){ 573 int pbyte; 574 int rc; 575 if( argc!=2 ){ 576 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 577 " PENDING-BYTE\"", (void*)0); 578 } 579 if( Tcl_GetInt(interp, argv[1], &pbyte) ) return TCL_ERROR; 580 rc = sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, pbyte); 581 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 582 return TCL_OK; 583 } 584 585 /* 586 ** sqlite3BitvecBuiltinTest SIZE PROGRAM 587 ** 588 ** Invoke the SQLITE_TESTCTRL_BITVEC_TEST operator on test_control. 589 ** See comments on sqlite3BitvecBuiltinTest() for additional information. 590 */ 591 static int testBitvecBuiltinTest( 592 void *NotUsed, 593 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 594 int argc, /* Number of arguments */ 595 const char **argv /* Text of each argument */ 596 ){ 597 int sz, rc; 598 int nProg = 0; 599 int aProg[100]; 600 const char *z; 601 if( argc!=3 ){ 602 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 603 " SIZE PROGRAM\"", (void*)0); 604 } 605 if( Tcl_GetInt(interp, argv[1], &sz) ) return TCL_ERROR; 606 z = argv[2]; 607 while( nProg<99 && *z ){ 608 while( *z && !sqlite3Isdigit(*z) ){ z++; } 609 if( *z==0 ) break; 610 aProg[nProg++] = atoi(z); 611 while( sqlite3Isdigit(*z) ){ z++; } 612 } 613 aProg[nProg] = 0; 614 rc = sqlite3_test_control(SQLITE_TESTCTRL_BITVEC_TEST, sz, aProg); 615 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 616 return TCL_OK; 617 } 618 619 /* 620 ** Register commands with the TCL interpreter. 621 */ 622 int Sqlitetest2_Init(Tcl_Interp *interp){ 623 extern int sqlite3_io_error_persist; 624 extern int sqlite3_io_error_pending; 625 extern int sqlite3_io_error_hit; 626 extern int sqlite3_io_error_hardhit; 627 extern int sqlite3_diskfull_pending; 628 extern int sqlite3_diskfull; 629 static struct { 630 char *zName; 631 Tcl_CmdProc *xProc; 632 } aCmd[] = { 633 { "pager_open", (Tcl_CmdProc*)pager_open }, 634 { "pager_close", (Tcl_CmdProc*)pager_close }, 635 { "pager_commit", (Tcl_CmdProc*)pager_commit }, 636 { "pager_rollback", (Tcl_CmdProc*)pager_rollback }, 637 { "pager_stmt_begin", (Tcl_CmdProc*)pager_stmt_begin }, 638 { "pager_stmt_commit", (Tcl_CmdProc*)pager_stmt_commit }, 639 { "pager_stmt_rollback", (Tcl_CmdProc*)pager_stmt_rollback }, 640 { "pager_stats", (Tcl_CmdProc*)pager_stats }, 641 { "pager_pagecount", (Tcl_CmdProc*)pager_pagecount }, 642 { "page_get", (Tcl_CmdProc*)page_get }, 643 { "page_lookup", (Tcl_CmdProc*)page_lookup }, 644 { "page_unref", (Tcl_CmdProc*)page_unref }, 645 { "page_read", (Tcl_CmdProc*)page_read }, 646 { "page_write", (Tcl_CmdProc*)page_write }, 647 { "page_number", (Tcl_CmdProc*)page_number }, 648 { "pager_truncate", (Tcl_CmdProc*)pager_truncate }, 649 #ifndef SQLITE_OMIT_DISKIO 650 { "fake_big_file", (Tcl_CmdProc*)fake_big_file }, 651 #endif 652 { "sqlite3BitvecBuiltinTest",(Tcl_CmdProc*)testBitvecBuiltinTest }, 653 { "sqlite3_test_control_pending_byte", (Tcl_CmdProc*)testPendingByte }, 654 }; 655 int i; 656 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ 657 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); 658 } 659 Tcl_LinkVar(interp, "sqlite_io_error_pending", 660 (char*)&sqlite3_io_error_pending, TCL_LINK_INT); 661 Tcl_LinkVar(interp, "sqlite_io_error_persist", 662 (char*)&sqlite3_io_error_persist, TCL_LINK_INT); 663 Tcl_LinkVar(interp, "sqlite_io_error_hit", 664 (char*)&sqlite3_io_error_hit, TCL_LINK_INT); 665 Tcl_LinkVar(interp, "sqlite_io_error_hardhit", 666 (char*)&sqlite3_io_error_hardhit, TCL_LINK_INT); 667 Tcl_LinkVar(interp, "sqlite_diskfull_pending", 668 (char*)&sqlite3_diskfull_pending, TCL_LINK_INT); 669 Tcl_LinkVar(interp, "sqlite_diskfull", 670 (char*)&sqlite3_diskfull, TCL_LINK_INT); 671 Tcl_LinkVar(interp, "sqlite_pending_byte", 672 (char*)&sqlite3PendingByte, TCL_LINK_INT | TCL_LINK_READ_ONLY); 673 return TCL_OK; 674 } 675