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