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.57 2008/03/21 16:45:48 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); 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 = sqlite3TextToPtr(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 = sqlite3TextToPtr(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 = sqlite3TextToPtr(argv[1]); 168 rc = sqlite3PagerCommitPhaseOne(pPager, 0, 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 = sqlite3TextToPtr(argv[1]); 200 rc = sqlite3PagerStmtBegin(pPager); 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 = sqlite3TextToPtr(argv[1]); 227 rc = sqlite3PagerStmtRollback(pPager); 228 if( rc!=SQLITE_OK ){ 229 Tcl_AppendResult(interp, errorName(rc), 0); 230 return TCL_ERROR; 231 } 232 return TCL_OK; 233 } 234 235 /* 236 ** Usage: pager_stmt_commit ID 237 ** 238 ** Commit changes to a checkpoint 239 */ 240 static int pager_stmt_commit( 241 void *NotUsed, 242 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 243 int argc, /* Number of arguments */ 244 const char **argv /* Text of each argument */ 245 ){ 246 Pager *pPager; 247 int rc; 248 if( argc!=2 ){ 249 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 250 " ID\"", 0); 251 return TCL_ERROR; 252 } 253 pPager = sqlite3TextToPtr(argv[1]); 254 rc = sqlite3PagerStmtCommit(pPager); 255 if( rc!=SQLITE_OK ){ 256 Tcl_AppendResult(interp, errorName(rc), 0); 257 return TCL_ERROR; 258 } 259 return TCL_OK; 260 } 261 262 /* 263 ** Usage: pager_stats ID 264 ** 265 ** Return pager statistics. 266 */ 267 static int pager_stats( 268 void *NotUsed, 269 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 270 int argc, /* Number of arguments */ 271 const char **argv /* Text of each argument */ 272 ){ 273 Pager *pPager; 274 int i, *a; 275 if( argc!=2 ){ 276 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 277 " ID\"", 0); 278 return TCL_ERROR; 279 } 280 pPager = sqlite3TextToPtr(argv[1]); 281 a = sqlite3PagerStats(pPager); 282 for(i=0; i<9; i++){ 283 static char *zName[] = { 284 "ref", "page", "max", "size", "state", "err", 285 "hit", "miss", "ovfl", 286 }; 287 char zBuf[100]; 288 Tcl_AppendElement(interp, zName[i]); 289 sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",a[i]); 290 Tcl_AppendElement(interp, zBuf); 291 } 292 return TCL_OK; 293 } 294 295 /* 296 ** Usage: pager_pagecount ID 297 ** 298 ** Return the size of the database file. 299 */ 300 static int pager_pagecount( 301 void *NotUsed, 302 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 303 int argc, /* Number of arguments */ 304 const char **argv /* Text of each argument */ 305 ){ 306 Pager *pPager; 307 char zBuf[100]; 308 if( argc!=2 ){ 309 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 310 " ID\"", 0); 311 return TCL_ERROR; 312 } 313 pPager = sqlite3TextToPtr(argv[1]); 314 sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",sqlite3PagerPagecount(pPager)); 315 Tcl_AppendResult(interp, zBuf, 0); 316 return TCL_OK; 317 } 318 319 /* 320 ** Usage: page_get ID PGNO 321 ** 322 ** Return a pointer to a page from the database. 323 */ 324 static int page_get( 325 void *NotUsed, 326 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 327 int argc, /* Number of arguments */ 328 const char **argv /* Text of each argument */ 329 ){ 330 Pager *pPager; 331 char zBuf[100]; 332 DbPage *pPage; 333 int pgno; 334 int rc; 335 if( argc!=3 ){ 336 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 337 " ID PGNO\"", 0); 338 return TCL_ERROR; 339 } 340 pPager = sqlite3TextToPtr(argv[1]); 341 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; 342 rc = sqlite3PagerGet(pPager, pgno, &pPage); 343 if( rc!=SQLITE_OK ){ 344 Tcl_AppendResult(interp, errorName(rc), 0); 345 return TCL_ERROR; 346 } 347 sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage); 348 Tcl_AppendResult(interp, zBuf, 0); 349 return TCL_OK; 350 } 351 352 /* 353 ** Usage: page_lookup ID PGNO 354 ** 355 ** Return a pointer to a page if the page is already in cache. 356 ** If not in cache, return an empty string. 357 */ 358 static int page_lookup( 359 void *NotUsed, 360 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 361 int argc, /* Number of arguments */ 362 const char **argv /* Text of each argument */ 363 ){ 364 Pager *pPager; 365 char zBuf[100]; 366 DbPage *pPage; 367 int pgno; 368 if( argc!=3 ){ 369 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 370 " ID PGNO\"", 0); 371 return TCL_ERROR; 372 } 373 pPager = sqlite3TextToPtr(argv[1]); 374 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; 375 pPage = sqlite3PagerLookup(pPager, pgno); 376 if( pPage ){ 377 sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage); 378 Tcl_AppendResult(interp, zBuf, 0); 379 } 380 return TCL_OK; 381 } 382 383 /* 384 ** Usage: pager_truncate ID PGNO 385 */ 386 static int pager_truncate( 387 void *NotUsed, 388 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 389 int argc, /* Number of arguments */ 390 const char **argv /* Text of each argument */ 391 ){ 392 Pager *pPager; 393 int rc; 394 int pgno; 395 if( argc!=3 ){ 396 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 397 " ID PGNO\"", 0); 398 return TCL_ERROR; 399 } 400 pPager = sqlite3TextToPtr(argv[1]); 401 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; 402 rc = sqlite3PagerTruncate(pPager, pgno); 403 if( rc!=SQLITE_OK ){ 404 Tcl_AppendResult(interp, errorName(rc), 0); 405 return TCL_ERROR; 406 } 407 return TCL_OK; 408 } 409 410 411 /* 412 ** Usage: page_unref PAGE 413 ** 414 ** Drop a pointer to a page. 415 */ 416 static int page_unref( 417 void *NotUsed, 418 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 419 int argc, /* Number of arguments */ 420 const char **argv /* Text of each argument */ 421 ){ 422 DbPage *pPage; 423 int rc; 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 *)sqlite3TextToPtr(argv[1]); 430 rc = sqlite3PagerUnref(pPage); 431 if( rc!=SQLITE_OK ){ 432 Tcl_AppendResult(interp, errorName(rc), 0); 433 return TCL_ERROR; 434 } 435 return TCL_OK; 436 } 437 438 /* 439 ** Usage: page_read PAGE 440 ** 441 ** Return the content of a page 442 */ 443 static int page_read( 444 void *NotUsed, 445 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 446 int argc, /* Number of arguments */ 447 const char **argv /* Text of each argument */ 448 ){ 449 char zBuf[100]; 450 DbPage *pPage; 451 if( argc!=2 ){ 452 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 453 " PAGE\"", 0); 454 return TCL_ERROR; 455 } 456 pPage = sqlite3TextToPtr(argv[1]); 457 memcpy(zBuf, sqlite3PagerGetData(pPage), sizeof(zBuf)); 458 Tcl_AppendResult(interp, zBuf, 0); 459 return TCL_OK; 460 } 461 462 /* 463 ** Usage: page_number PAGE 464 ** 465 ** Return the page number for a page. 466 */ 467 static int page_number( 468 void *NotUsed, 469 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 470 int argc, /* Number of arguments */ 471 const char **argv /* Text of each argument */ 472 ){ 473 char zBuf[100]; 474 DbPage *pPage; 475 if( argc!=2 ){ 476 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 477 " PAGE\"", 0); 478 return TCL_ERROR; 479 } 480 pPage = (DbPage *)sqlite3TextToPtr(argv[1]); 481 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3PagerPagenumber(pPage)); 482 Tcl_AppendResult(interp, zBuf, 0); 483 return TCL_OK; 484 } 485 486 /* 487 ** Usage: page_write PAGE DATA 488 ** 489 ** Write something into a page. 490 */ 491 static int page_write( 492 void *NotUsed, 493 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 494 int argc, /* Number of arguments */ 495 const char **argv /* Text of each argument */ 496 ){ 497 DbPage *pPage; 498 char *pData; 499 int rc; 500 if( argc!=3 ){ 501 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 502 " PAGE DATA\"", 0); 503 return TCL_ERROR; 504 } 505 pPage = (DbPage *)sqlite3TextToPtr(argv[1]); 506 rc = sqlite3PagerWrite(pPage); 507 if( rc!=SQLITE_OK ){ 508 Tcl_AppendResult(interp, errorName(rc), 0); 509 return TCL_ERROR; 510 } 511 pData = sqlite3PagerGetData(pPage); 512 strncpy(pData, argv[2], test_pagesize-1); 513 pData[test_pagesize-1] = 0; 514 return TCL_OK; 515 } 516 517 #ifndef SQLITE_OMIT_DISKIO 518 /* 519 ** Usage: fake_big_file N FILENAME 520 ** 521 ** Write a few bytes at the N megabyte point of FILENAME. This will 522 ** create a large file. If the file was a valid SQLite database, then 523 ** the next time the database is opened, SQLite will begin allocating 524 ** new pages after N. If N is 2096 or bigger, this will test the 525 ** ability of SQLite to write to large files. 526 */ 527 static int fake_big_file( 528 void *NotUsed, 529 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 530 int argc, /* Number of arguments */ 531 const char **argv /* Text of each argument */ 532 ){ 533 sqlite3_vfs *pVfs; 534 sqlite3_file *fd = 0; 535 int rc; 536 int n; 537 i64 offset; 538 if( argc!=3 ){ 539 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 540 " N-MEGABYTES FILE\"", 0); 541 return TCL_ERROR; 542 } 543 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; 544 545 pVfs = sqlite3_vfs_find(0); 546 rc = sqlite3OsOpenMalloc(pVfs, argv[2], &fd, 547 (SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB), 0 548 ); 549 if( rc ){ 550 Tcl_AppendResult(interp, "open failed: ", errorName(rc), 0); 551 return TCL_ERROR; 552 } 553 offset = n; 554 offset *= 1024*1024; 555 rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset); 556 sqlite3OsCloseFree(fd); 557 if( rc ){ 558 Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0); 559 return TCL_ERROR; 560 } 561 return TCL_OK; 562 } 563 #endif 564 565 566 /* 567 ** sqlite3BitvecBuiltinTest SIZE PROGRAM 568 ** 569 ** Invoke the SQLITE_TESTCTRL_BITVEC_TEST operator on test_control. 570 ** See comments on sqlite3BitvecBuiltinTest() for additional information. 571 */ 572 static int testBitvecBuiltinTest( 573 void *NotUsed, 574 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 575 int argc, /* Number of arguments */ 576 const char **argv /* Text of each argument */ 577 ){ 578 int sz, rc; 579 int nProg = 0; 580 int aProg[100]; 581 const char *z; 582 if( argc!=3 ){ 583 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 584 " SIZE PROGRAM\"", (void*)0); 585 } 586 if( Tcl_GetInt(interp, argv[1], &sz) ) return TCL_ERROR; 587 z = argv[2]; 588 while( nProg<99 && *z ){ 589 while( *z && !isdigit(*z) ){ z++; } 590 if( *z==0 ) break; 591 aProg[nProg++] = atoi(z); 592 while( isdigit(*z) ){ z++; } 593 } 594 aProg[nProg] = 0; 595 rc = sqlite3_test_control(SQLITE_TESTCTRL_BITVEC_TEST, sz, aProg); 596 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 597 return TCL_OK; 598 } 599 600 /* 601 ** Register commands with the TCL interpreter. 602 */ 603 int Sqlitetest2_Init(Tcl_Interp *interp){ 604 extern int sqlite3_io_error_persist; 605 extern int sqlite3_io_error_pending; 606 extern int sqlite3_io_error_hit; 607 extern int sqlite3_io_error_hardhit; 608 extern int sqlite3_diskfull_pending; 609 extern int sqlite3_diskfull; 610 extern int sqlite3_pager_n_sort_bucket; 611 static struct { 612 char *zName; 613 Tcl_CmdProc *xProc; 614 } aCmd[] = { 615 { "pager_open", (Tcl_CmdProc*)pager_open }, 616 { "pager_close", (Tcl_CmdProc*)pager_close }, 617 { "pager_commit", (Tcl_CmdProc*)pager_commit }, 618 { "pager_rollback", (Tcl_CmdProc*)pager_rollback }, 619 { "pager_stmt_begin", (Tcl_CmdProc*)pager_stmt_begin }, 620 { "pager_stmt_commit", (Tcl_CmdProc*)pager_stmt_commit }, 621 { "pager_stmt_rollback", (Tcl_CmdProc*)pager_stmt_rollback }, 622 { "pager_stats", (Tcl_CmdProc*)pager_stats }, 623 { "pager_pagecount", (Tcl_CmdProc*)pager_pagecount }, 624 { "page_get", (Tcl_CmdProc*)page_get }, 625 { "page_lookup", (Tcl_CmdProc*)page_lookup }, 626 { "page_unref", (Tcl_CmdProc*)page_unref }, 627 { "page_read", (Tcl_CmdProc*)page_read }, 628 { "page_write", (Tcl_CmdProc*)page_write }, 629 { "page_number", (Tcl_CmdProc*)page_number }, 630 { "pager_truncate", (Tcl_CmdProc*)pager_truncate }, 631 #ifndef SQLITE_OMIT_DISKIO 632 { "fake_big_file", (Tcl_CmdProc*)fake_big_file }, 633 #endif 634 { "sqlite3BitvecBuiltinTest",(Tcl_CmdProc*)testBitvecBuiltinTest}, 635 }; 636 int i; 637 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ 638 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); 639 } 640 Tcl_LinkVar(interp, "sqlite_io_error_pending", 641 (char*)&sqlite3_io_error_pending, TCL_LINK_INT); 642 Tcl_LinkVar(interp, "sqlite_io_error_persist", 643 (char*)&sqlite3_io_error_persist, TCL_LINK_INT); 644 Tcl_LinkVar(interp, "sqlite_io_error_hit", 645 (char*)&sqlite3_io_error_hit, TCL_LINK_INT); 646 Tcl_LinkVar(interp, "sqlite_io_error_hardhit", 647 (char*)&sqlite3_io_error_hardhit, TCL_LINK_INT); 648 Tcl_LinkVar(interp, "sqlite_diskfull_pending", 649 (char*)&sqlite3_diskfull_pending, TCL_LINK_INT); 650 Tcl_LinkVar(interp, "sqlite_diskfull", 651 (char*)&sqlite3_diskfull, TCL_LINK_INT); 652 Tcl_LinkVar(interp, "sqlite_pending_byte", 653 (char*)&sqlite3_pending_byte, TCL_LINK_INT); 654 Tcl_LinkVar(interp, "sqlite_pager_n_sort_bucket", 655 (char*)&sqlite3_pager_n_sort_bucket, TCL_LINK_INT); 656 return TCL_OK; 657 } 658