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 btree.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: test3.c,v 1.43 2004/06/04 06:22:02 danielk1977 Exp $ 17 */ 18 #include "sqliteInt.h" 19 #include "pager.h" 20 #include "btree.h" 21 #include "tcl.h" 22 #include <stdlib.h> 23 #include <string.h> 24 25 /* 26 ** Interpret an SQLite error number 27 */ 28 static char *errorName(int rc){ 29 char *zName; 30 switch( rc ){ 31 case SQLITE_OK: zName = "SQLITE_OK"; break; 32 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; 33 case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break; 34 case SQLITE_PERM: zName = "SQLITE_PERM"; break; 35 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; 36 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; 37 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; 38 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; 39 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; 40 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; 41 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; 42 case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break; 43 case SQLITE_FULL: zName = "SQLITE_FULL"; break; 44 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; 45 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break; 46 case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break; 47 default: zName = "SQLITE_Unknown"; break; 48 } 49 return zName; 50 } 51 52 /* 53 ** Usage: btree_open FILENAME NCACHE FLAGS 54 ** 55 ** Open a new database 56 */ 57 static int btree_open( 58 void *NotUsed, 59 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 60 int argc, /* Number of arguments */ 61 const char **argv /* Text of each argument */ 62 ){ 63 Btree *pBt; 64 int rc, nCache, flags; 65 char zBuf[100]; 66 if( argc!=4 ){ 67 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 68 " FILENAME NCACHE FLAGS\"", 0); 69 return TCL_ERROR; 70 } 71 if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR; 72 if( Tcl_GetInt(interp, argv[3], &flags) ) return TCL_ERROR; 73 rc = sqlite3BtreeOpen(argv[1], &pBt, nCache, flags, 0); 74 if( rc!=SQLITE_OK ){ 75 Tcl_AppendResult(interp, errorName(rc), 0); 76 return TCL_ERROR; 77 } 78 sprintf(zBuf,"%p", pBt); 79 if( strncmp(zBuf,"0x",2) ){ 80 sprintf(zBuf, "0x%p", pBt); 81 } 82 Tcl_AppendResult(interp, zBuf, 0); 83 return TCL_OK; 84 } 85 86 /* 87 ** Usage: btree_close ID 88 ** 89 ** Close the given database. 90 */ 91 static int btree_close( 92 void *NotUsed, 93 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 94 int argc, /* Number of arguments */ 95 const char **argv /* Text of each argument */ 96 ){ 97 Btree *pBt; 98 int rc; 99 if( argc!=2 ){ 100 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 101 " ID\"", 0); 102 return TCL_ERROR; 103 } 104 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 105 rc = sqlite3BtreeClose(pBt); 106 if( rc!=SQLITE_OK ){ 107 Tcl_AppendResult(interp, errorName(rc), 0); 108 return TCL_ERROR; 109 } 110 return TCL_OK; 111 } 112 113 /* 114 ** Usage: btree_begin_transaction ID 115 ** 116 ** Start a new transaction 117 */ 118 static int btree_begin_transaction( 119 void *NotUsed, 120 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 121 int argc, /* Number of arguments */ 122 const char **argv /* Text of each argument */ 123 ){ 124 Btree *pBt; 125 int rc; 126 if( argc!=2 ){ 127 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 128 " ID\"", 0); 129 return TCL_ERROR; 130 } 131 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 132 rc = sqlite3BtreeBeginTrans(pBt, 1, 0); 133 if( rc!=SQLITE_OK ){ 134 Tcl_AppendResult(interp, errorName(rc), 0); 135 return TCL_ERROR; 136 } 137 return TCL_OK; 138 } 139 140 /* 141 ** Usage: btree_rollback ID 142 ** 143 ** Rollback changes 144 */ 145 static int btree_rollback( 146 void *NotUsed, 147 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 148 int argc, /* Number of arguments */ 149 const char **argv /* Text of each argument */ 150 ){ 151 Btree *pBt; 152 int rc; 153 if( argc!=2 ){ 154 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 155 " ID\"", 0); 156 return TCL_ERROR; 157 } 158 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 159 rc = sqlite3BtreeRollback(pBt); 160 if( rc!=SQLITE_OK ){ 161 Tcl_AppendResult(interp, errorName(rc), 0); 162 return TCL_ERROR; 163 } 164 return TCL_OK; 165 } 166 167 /* 168 ** Usage: btree_commit ID 169 ** 170 ** Commit all changes 171 */ 172 static int btree_commit( 173 void *NotUsed, 174 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 175 int argc, /* Number of arguments */ 176 const char **argv /* Text of each argument */ 177 ){ 178 Btree *pBt; 179 int rc; 180 if( argc!=2 ){ 181 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 182 " ID\"", 0); 183 return TCL_ERROR; 184 } 185 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 186 rc = sqlite3BtreeCommit(pBt); 187 if( rc!=SQLITE_OK ){ 188 Tcl_AppendResult(interp, errorName(rc), 0); 189 return TCL_ERROR; 190 } 191 return TCL_OK; 192 } 193 194 /* 195 ** Usage: btree_begin_statement ID 196 ** 197 ** Start a new statement transaction 198 */ 199 static int btree_begin_statement( 200 void *NotUsed, 201 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 202 int argc, /* Number of arguments */ 203 const char **argv /* Text of each argument */ 204 ){ 205 Btree *pBt; 206 int rc; 207 if( argc!=2 ){ 208 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 209 " ID\"", 0); 210 return TCL_ERROR; 211 } 212 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 213 rc = sqlite3BtreeBeginStmt(pBt); 214 if( rc!=SQLITE_OK ){ 215 Tcl_AppendResult(interp, errorName(rc), 0); 216 return TCL_ERROR; 217 } 218 return TCL_OK; 219 } 220 221 /* 222 ** Usage: btree_rollback_statement ID 223 ** 224 ** Rollback changes 225 */ 226 static int btree_rollback_statement( 227 void *NotUsed, 228 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 229 int argc, /* Number of arguments */ 230 const char **argv /* Text of each argument */ 231 ){ 232 Btree *pBt; 233 int rc; 234 if( argc!=2 ){ 235 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 236 " ID\"", 0); 237 return TCL_ERROR; 238 } 239 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 240 rc = sqlite3BtreeRollbackStmt(pBt); 241 if( rc!=SQLITE_OK ){ 242 Tcl_AppendResult(interp, errorName(rc), 0); 243 return TCL_ERROR; 244 } 245 return TCL_OK; 246 } 247 248 /* 249 ** Usage: btree_commit_statement ID 250 ** 251 ** Commit all changes 252 */ 253 static int btree_commit_statement( 254 void *NotUsed, 255 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 256 int argc, /* Number of arguments */ 257 const char **argv /* Text of each argument */ 258 ){ 259 Btree *pBt; 260 int rc; 261 if( argc!=2 ){ 262 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 263 " ID\"", 0); 264 return TCL_ERROR; 265 } 266 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 267 rc = sqlite3BtreeCommitStmt(pBt); 268 if( rc!=SQLITE_OK ){ 269 Tcl_AppendResult(interp, errorName(rc), 0); 270 return TCL_ERROR; 271 } 272 return TCL_OK; 273 } 274 275 /* 276 ** Usage: btree_create_table ID FLAGS 277 ** 278 ** Create a new table in the database 279 */ 280 static int btree_create_table( 281 void *NotUsed, 282 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 283 int argc, /* Number of arguments */ 284 const char **argv /* Text of each argument */ 285 ){ 286 Btree *pBt; 287 int rc, iTable, flags; 288 char zBuf[30]; 289 if( argc!=3 ){ 290 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 291 " ID FLAGS\"", 0); 292 return TCL_ERROR; 293 } 294 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 295 if( Tcl_GetInt(interp, argv[2], &flags) ) return TCL_ERROR; 296 rc = sqlite3BtreeCreateTable(pBt, &iTable, flags); 297 if( rc!=SQLITE_OK ){ 298 Tcl_AppendResult(interp, errorName(rc), 0); 299 return TCL_ERROR; 300 } 301 sprintf(zBuf, "%d", iTable); 302 Tcl_AppendResult(interp, zBuf, 0); 303 return TCL_OK; 304 } 305 306 /* 307 ** Usage: btree_drop_table ID TABLENUM 308 ** 309 ** Delete an entire table from the database 310 */ 311 static int btree_drop_table( 312 void *NotUsed, 313 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 314 int argc, /* Number of arguments */ 315 const char **argv /* Text of each argument */ 316 ){ 317 Btree *pBt; 318 int iTable; 319 int rc; 320 if( argc!=3 ){ 321 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 322 " ID TABLENUM\"", 0); 323 return TCL_ERROR; 324 } 325 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 326 if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR; 327 rc = sqlite3BtreeDropTable(pBt, iTable); 328 if( rc!=SQLITE_OK ){ 329 Tcl_AppendResult(interp, errorName(rc), 0); 330 return TCL_ERROR; 331 } 332 return TCL_OK; 333 } 334 335 /* 336 ** Usage: btree_clear_table ID TABLENUM 337 ** 338 ** Remove all entries from the given table but keep the table around. 339 */ 340 static int btree_clear_table( 341 void *NotUsed, 342 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 343 int argc, /* Number of arguments */ 344 const char **argv /* Text of each argument */ 345 ){ 346 Btree *pBt; 347 int iTable; 348 int rc; 349 if( argc!=3 ){ 350 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 351 " ID TABLENUM\"", 0); 352 return TCL_ERROR; 353 } 354 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 355 if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR; 356 rc = sqlite3BtreeClearTable(pBt, iTable); 357 if( rc!=SQLITE_OK ){ 358 Tcl_AppendResult(interp, errorName(rc), 0); 359 return TCL_ERROR; 360 } 361 return TCL_OK; 362 } 363 364 #define SQLITE_N_BTREE_META 16 365 366 /* 367 ** Usage: btree_get_meta ID 368 ** 369 ** Return meta data 370 */ 371 static int btree_get_meta( 372 void *NotUsed, 373 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 374 int argc, /* Number of arguments */ 375 const char **argv /* Text of each argument */ 376 ){ 377 Btree *pBt; 378 int rc; 379 int i; 380 if( argc!=2 ){ 381 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 382 " ID\"", 0); 383 return TCL_ERROR; 384 } 385 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 386 for(i=0; i<SQLITE_N_BTREE_META; i++){ 387 char zBuf[30]; 388 unsigned int v; 389 rc = sqlite3BtreeGetMeta(pBt, i, &v); 390 if( rc!=SQLITE_OK ){ 391 Tcl_AppendResult(interp, errorName(rc), 0); 392 return TCL_ERROR; 393 } 394 sprintf(zBuf,"%d",v); 395 Tcl_AppendElement(interp, zBuf); 396 } 397 return TCL_OK; 398 } 399 400 /* 401 ** Usage: btree_update_meta ID METADATA... 402 ** 403 ** Return meta data 404 */ 405 static int btree_update_meta( 406 void *NotUsed, 407 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 408 int argc, /* Number of arguments */ 409 const char **argv /* Text of each argument */ 410 ){ 411 Btree *pBt; 412 int rc; 413 int i; 414 int aMeta[SQLITE_N_BTREE_META]; 415 416 if( argc!=1+SQLITE_N_BTREE_META ){ 417 char zBuf[30]; 418 sprintf(zBuf,"%d",SQLITE_N_BTREE_META); 419 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 420 " ID METADATA...\" (METADATA is ", zBuf, " integers)", 0); 421 return TCL_ERROR; 422 } 423 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 424 for(i=1; i<SQLITE_N_BTREE_META; i++){ 425 if( Tcl_GetInt(interp, argv[i+1], &aMeta[i]) ) return TCL_ERROR; 426 } 427 for(i=1; i<SQLITE_N_BTREE_META; i++){ 428 rc = sqlite3BtreeUpdateMeta(pBt, i, aMeta[i]); 429 if( rc!=SQLITE_OK ){ 430 Tcl_AppendResult(interp, errorName(rc), 0); 431 return TCL_ERROR; 432 } 433 } 434 return TCL_OK; 435 } 436 437 /* 438 ** Usage: btree_page_dump ID PAGENUM 439 ** 440 ** Print a disassembly of a page on standard output 441 */ 442 static int btree_page_dump( 443 void *NotUsed, 444 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 445 int argc, /* Number of arguments */ 446 const char **argv /* Text of each argument */ 447 ){ 448 Btree *pBt; 449 int iPage; 450 int rc; 451 452 if( argc!=3 ){ 453 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 454 " ID\"", 0); 455 return TCL_ERROR; 456 } 457 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 458 if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR; 459 rc = sqlite3BtreePageDump(pBt, iPage, 0); 460 if( rc!=SQLITE_OK ){ 461 Tcl_AppendResult(interp, errorName(rc), 0); 462 return TCL_ERROR; 463 } 464 return TCL_OK; 465 } 466 467 /* 468 ** Usage: btree_tree_dump ID PAGENUM 469 ** 470 ** Print a disassembly of a page and all its child pages on standard output 471 */ 472 static int btree_tree_dump( 473 void *NotUsed, 474 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 475 int argc, /* Number of arguments */ 476 const char **argv /* Text of each argument */ 477 ){ 478 Btree *pBt; 479 int iPage; 480 int rc; 481 482 if( argc!=3 ){ 483 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 484 " ID\"", 0); 485 return TCL_ERROR; 486 } 487 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 488 if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR; 489 rc = sqlite3BtreePageDump(pBt, iPage, 1); 490 if( rc!=SQLITE_OK ){ 491 Tcl_AppendResult(interp, errorName(rc), 0); 492 return TCL_ERROR; 493 } 494 return TCL_OK; 495 } 496 497 /* 498 ** Usage: btree_pager_stats ID 499 ** 500 ** Returns pager statistics 501 */ 502 static int btree_pager_stats( 503 void *NotUsed, 504 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 505 int argc, /* Number of arguments */ 506 const char **argv /* Text of each argument */ 507 ){ 508 Btree *pBt; 509 int i; 510 int *a; 511 512 if( argc!=2 ){ 513 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 514 " ID\"", 0); 515 return TCL_ERROR; 516 } 517 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 518 a = sqlite3pager_stats(sqlite3BtreePager(pBt)); 519 for(i=0; i<9; i++){ 520 static char *zName[] = { 521 "ref", "page", "max", "size", "state", "err", 522 "hit", "miss", "ovfl", 523 }; 524 char zBuf[100]; 525 Tcl_AppendElement(interp, zName[i]); 526 sprintf(zBuf,"%d",a[i]); 527 Tcl_AppendElement(interp, zBuf); 528 } 529 return TCL_OK; 530 } 531 532 /* 533 ** Usage: btree_pager_ref_dump ID 534 ** 535 ** Print out all outstanding pages. 536 */ 537 static int btree_pager_ref_dump( 538 void *NotUsed, 539 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 540 int argc, /* Number of arguments */ 541 const char **argv /* Text of each argument */ 542 ){ 543 Btree *pBt; 544 545 if( argc!=2 ){ 546 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 547 " ID\"", 0); 548 return TCL_ERROR; 549 } 550 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 551 sqlite3pager_refdump(sqlite3BtreePager(pBt)); 552 return TCL_OK; 553 } 554 555 /* 556 ** Usage: btree_integrity_check ID ROOT ... 557 ** 558 ** Look through every page of the given BTree file to verify correct 559 ** formatting and linkage. Return a line of text for each problem found. 560 ** Return an empty string if everything worked. 561 */ 562 static int btree_integrity_check( 563 void *NotUsed, 564 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 565 int argc, /* Number of arguments */ 566 const char **argv /* Text of each argument */ 567 ){ 568 Btree *pBt; 569 char *zResult; 570 int nRoot; 571 int *aRoot; 572 int i; 573 574 if( argc<3 ){ 575 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 576 " ID ROOT ...\"", 0); 577 return TCL_ERROR; 578 } 579 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 580 nRoot = argc-2; 581 aRoot = malloc( sizeof(int)*(argc-2) ); 582 for(i=0; i<argc-2; i++){ 583 if( Tcl_GetInt(interp, argv[i+2], &aRoot[i]) ) return TCL_ERROR; 584 } 585 zResult = sqlite3BtreeIntegrityCheck(pBt, aRoot, nRoot); 586 if( zResult ){ 587 Tcl_AppendResult(interp, zResult, 0); 588 sqliteFree(zResult); 589 } 590 return TCL_OK; 591 } 592 593 /* 594 ** Usage: btree_cursor_list ID 595 ** 596 ** Print information about all cursors to standard output for debugging. 597 */ 598 static int btree_cursor_list( 599 void *NotUsed, 600 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 601 int argc, /* Number of arguments */ 602 const char **argv /* Text of each argument */ 603 ){ 604 Btree *pBt; 605 606 if( argc!=2 ){ 607 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 608 " ID\"", 0); 609 return TCL_ERROR; 610 } 611 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 612 sqlite3BtreeCursorList(pBt); 613 return SQLITE_OK; 614 } 615 616 /* 617 ** Usage: btree_cursor ID TABLENUM WRITEABLE 618 ** 619 ** Create a new cursor. Return the ID for the cursor. 620 */ 621 static int btree_cursor( 622 void *NotUsed, 623 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 624 int argc, /* Number of arguments */ 625 const char **argv /* Text of each argument */ 626 ){ 627 Btree *pBt; 628 int iTable; 629 BtCursor *pCur; 630 int rc; 631 int wrFlag; 632 char zBuf[30]; 633 634 if( argc!=4 ){ 635 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 636 " ID TABLENUM WRITEABLE\"", 0); 637 return TCL_ERROR; 638 } 639 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; 640 if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR; 641 if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR; 642 rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, 0, &pCur); 643 if( rc ){ 644 Tcl_AppendResult(interp, errorName(rc), 0); 645 return TCL_ERROR; 646 } 647 sprintf(zBuf,"0x%x", (int)pCur); 648 Tcl_AppendResult(interp, zBuf, 0); 649 return SQLITE_OK; 650 } 651 652 /* 653 ** Usage: btree_close_cursor ID 654 ** 655 ** Close a cursor opened using btree_cursor. 656 */ 657 static int btree_close_cursor( 658 void *NotUsed, 659 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 660 int argc, /* Number of arguments */ 661 const char **argv /* Text of each argument */ 662 ){ 663 BtCursor *pCur; 664 int rc; 665 666 if( argc!=2 ){ 667 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 668 " ID\"", 0); 669 return TCL_ERROR; 670 } 671 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR; 672 rc = sqlite3BtreeCloseCursor(pCur); 673 if( rc ){ 674 Tcl_AppendResult(interp, errorName(rc), 0); 675 return TCL_ERROR; 676 } 677 return SQLITE_OK; 678 } 679 680 /* 681 ** Usage: btree_move_to ID KEY 682 ** 683 ** Move the cursor to the entry with the given key. 684 */ 685 static int btree_move_to( 686 void *NotUsed, 687 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 688 int argc, /* Number of arguments */ 689 const char **argv /* Text of each argument */ 690 ){ 691 BtCursor *pCur; 692 int rc; 693 int res; 694 char zBuf[20]; 695 696 if( argc!=3 ){ 697 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 698 " ID KEY\"", 0); 699 return TCL_ERROR; 700 } 701 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR; 702 if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){ 703 int iKey; 704 if( Tcl_GetInt(interp, argv[2], &iKey) ) return TCL_ERROR; 705 rc = sqlite3BtreeMoveto(pCur, 0, iKey, &res); 706 }else{ 707 rc = sqlite3BtreeMoveto(pCur, argv[2], strlen(argv[2]), &res); 708 } 709 if( rc ){ 710 Tcl_AppendResult(interp, errorName(rc), 0); 711 return TCL_ERROR; 712 } 713 if( res<0 ) res = -1; 714 if( res>0 ) res = 1; 715 sprintf(zBuf,"%d",res); 716 Tcl_AppendResult(interp, zBuf, 0); 717 return SQLITE_OK; 718 } 719 720 /* 721 ** Usage: btree_delete ID 722 ** 723 ** Delete the entry that the cursor is pointing to 724 */ 725 static int btree_delete( 726 void *NotUsed, 727 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 728 int argc, /* Number of arguments */ 729 const char **argv /* Text of each argument */ 730 ){ 731 BtCursor *pCur; 732 int rc; 733 734 if( argc!=2 ){ 735 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 736 " ID\"", 0); 737 return TCL_ERROR; 738 } 739 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR; 740 rc = sqlite3BtreeDelete(pCur); 741 if( rc ){ 742 Tcl_AppendResult(interp, errorName(rc), 0); 743 return TCL_ERROR; 744 } 745 return SQLITE_OK; 746 } 747 748 /* 749 ** Usage: btree_insert ID KEY DATA 750 ** 751 ** Create a new entry with the given key and data. If an entry already 752 ** exists with the same key the old entry is overwritten. 753 */ 754 static int btree_insert( 755 void *NotUsed, 756 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 757 int argc, /* Number of arguments */ 758 const char **argv /* Text of each argument */ 759 ){ 760 BtCursor *pCur; 761 int rc; 762 763 if( argc!=4 ){ 764 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 765 " ID KEY DATA\"", 0); 766 return TCL_ERROR; 767 } 768 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR; 769 if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){ 770 /* 771 int iKey; 772 if( Tcl_GetInt(interp, argv[2], &iKey) ) return TCL_ERROR; 773 */ 774 i64 iKey; 775 Tcl_Obj *obj = Tcl_NewStringObj(argv[2], -1); 776 Tcl_IncrRefCount(obj); 777 if( Tcl_GetWideIntFromObj(interp, obj, &iKey) ) return TCL_ERROR; 778 Tcl_DecrRefCount(obj); 779 780 rc = sqlite3BtreeInsert(pCur, 0, iKey, argv[3], strlen(argv[3])); 781 }else{ 782 rc = sqlite3BtreeInsert(pCur, argv[2], strlen(argv[2]), 783 argv[3], strlen(argv[3])); 784 } 785 if( rc ){ 786 Tcl_AppendResult(interp, errorName(rc), 0); 787 return TCL_ERROR; 788 } 789 return SQLITE_OK; 790 } 791 792 /* 793 ** Usage: btree_next ID 794 ** 795 ** Move the cursor to the next entry in the table. Return 0 on success 796 ** or 1 if the cursor was already on the last entry in the table or if 797 ** the table is empty. 798 */ 799 static int btree_next( 800 void *NotUsed, 801 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 802 int argc, /* Number of arguments */ 803 const char **argv /* Text of each argument */ 804 ){ 805 BtCursor *pCur; 806 int rc; 807 int res = 0; 808 char zBuf[100]; 809 810 if( argc!=2 ){ 811 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 812 " ID\"", 0); 813 return TCL_ERROR; 814 } 815 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR; 816 rc = sqlite3BtreeNext(pCur, &res); 817 if( rc ){ 818 Tcl_AppendResult(interp, errorName(rc), 0); 819 return TCL_ERROR; 820 } 821 sprintf(zBuf,"%d",res); 822 Tcl_AppendResult(interp, zBuf, 0); 823 return SQLITE_OK; 824 } 825 826 /* 827 ** Usage: btree_prev ID 828 ** 829 ** Move the cursor to the previous entry in the table. Return 0 on 830 ** success and 1 if the cursor was already on the first entry in 831 ** the table or if the table was empty. 832 */ 833 static int btree_prev( 834 void *NotUsed, 835 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 836 int argc, /* Number of arguments */ 837 const char **argv /* Text of each argument */ 838 ){ 839 BtCursor *pCur; 840 int rc; 841 int res = 0; 842 char zBuf[100]; 843 844 if( argc!=2 ){ 845 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 846 " ID\"", 0); 847 return TCL_ERROR; 848 } 849 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR; 850 rc = sqlite3BtreePrevious(pCur, &res); 851 if( rc ){ 852 Tcl_AppendResult(interp, errorName(rc), 0); 853 return TCL_ERROR; 854 } 855 sprintf(zBuf,"%d",res); 856 Tcl_AppendResult(interp, zBuf, 0); 857 return SQLITE_OK; 858 } 859 860 /* 861 ** Usage: btree_first ID 862 ** 863 ** Move the cursor to the first entry in the table. Return 0 if the 864 ** cursor was left point to something and 1 if the table is empty. 865 */ 866 static int btree_first( 867 void *NotUsed, 868 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 869 int argc, /* Number of arguments */ 870 const char **argv /* Text of each argument */ 871 ){ 872 BtCursor *pCur; 873 int rc; 874 int res = 0; 875 char zBuf[100]; 876 877 if( argc!=2 ){ 878 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 879 " ID\"", 0); 880 return TCL_ERROR; 881 } 882 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR; 883 rc = sqlite3BtreeFirst(pCur, &res); 884 if( rc ){ 885 Tcl_AppendResult(interp, errorName(rc), 0); 886 return TCL_ERROR; 887 } 888 sprintf(zBuf,"%d",res); 889 Tcl_AppendResult(interp, zBuf, 0); 890 return SQLITE_OK; 891 } 892 893 /* 894 ** Usage: btree_last ID 895 ** 896 ** Move the cursor to the last entry in the table. Return 0 if the 897 ** cursor was left point to something and 1 if the table is empty. 898 */ 899 static int btree_last( 900 void *NotUsed, 901 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 902 int argc, /* Number of arguments */ 903 const char **argv /* Text of each argument */ 904 ){ 905 BtCursor *pCur; 906 int rc; 907 int res = 0; 908 char zBuf[100]; 909 910 if( argc!=2 ){ 911 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 912 " ID\"", 0); 913 return TCL_ERROR; 914 } 915 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR; 916 rc = sqlite3BtreeLast(pCur, &res); 917 if( rc ){ 918 Tcl_AppendResult(interp, errorName(rc), 0); 919 return TCL_ERROR; 920 } 921 sprintf(zBuf,"%d",res); 922 Tcl_AppendResult(interp, zBuf, 0); 923 return SQLITE_OK; 924 } 925 926 /* 927 ** Usage: btree_eof ID 928 ** 929 ** Return TRUE if the given cursor is not pointing at a valid entry. 930 ** Return FALSE if the cursor does point to a valid entry. 931 */ 932 static int btree_eof( 933 void *NotUsed, 934 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 935 int argc, /* Number of arguments */ 936 const char **argv /* Text of each argument */ 937 ){ 938 BtCursor *pCur; 939 char zBuf[50]; 940 941 if( argc!=2 ){ 942 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 943 " ID\"", 0); 944 return TCL_ERROR; 945 } 946 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR; 947 sprintf(zBuf, "%d", sqlite3BtreeEof(pCur)); 948 Tcl_AppendResult(interp, zBuf, 0); 949 return SQLITE_OK; 950 } 951 952 /* 953 ** Usage: btree_keysize ID 954 ** 955 ** Return the number of bytes of key. For an INTKEY table, this 956 ** returns the key itself. 957 */ 958 static int btree_keysize( 959 void *NotUsed, 960 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 961 int argc, /* Number of arguments */ 962 const char **argv /* Text of each argument */ 963 ){ 964 BtCursor *pCur; 965 u64 n; 966 char zBuf[50]; 967 968 if( argc!=2 ){ 969 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 970 " ID\"", 0); 971 return TCL_ERROR; 972 } 973 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR; 974 sqlite3BtreeKeySize(pCur, &n); 975 sprintf(zBuf, "%llu", n); 976 Tcl_AppendResult(interp, zBuf, 0); 977 return SQLITE_OK; 978 } 979 980 /* 981 ** Usage: btree_key ID 982 ** 983 ** Return the key for the entry at which the cursor is pointing. 984 */ 985 static int btree_key( 986 void *NotUsed, 987 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 988 int argc, /* Number of arguments */ 989 const char **argv /* Text of each argument */ 990 ){ 991 BtCursor *pCur; 992 int rc; 993 u64 n; 994 char *zBuf; 995 996 if( argc!=2 ){ 997 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 998 " ID\"", 0); 999 return TCL_ERROR; 1000 } 1001 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR; 1002 sqlite3BtreeKeySize(pCur, &n); 1003 if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){ 1004 char zBuf2[60]; 1005 sprintf(zBuf2, "%llu", n); 1006 Tcl_AppendResult(interp, zBuf2, 0); 1007 }else{ 1008 zBuf = malloc( n+1 ); 1009 rc = sqlite3BtreeKey(pCur, 0, n, zBuf); 1010 if( rc ){ 1011 Tcl_AppendResult(interp, errorName(rc), 0); 1012 return TCL_ERROR; 1013 } 1014 zBuf[n] = 0; 1015 Tcl_AppendResult(interp, zBuf, 0); 1016 free(zBuf); 1017 } 1018 return SQLITE_OK; 1019 } 1020 1021 /* 1022 ** Usage: btree_data ID 1023 ** 1024 ** Return the data for the entry at which the cursor is pointing. 1025 */ 1026 static int btree_data( 1027 void *NotUsed, 1028 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1029 int argc, /* Number of arguments */ 1030 const char **argv /* Text of each argument */ 1031 ){ 1032 BtCursor *pCur; 1033 int rc; 1034 u32 n; 1035 char *zBuf; 1036 1037 if( argc!=2 ){ 1038 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1039 " ID\"", 0); 1040 return TCL_ERROR; 1041 } 1042 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR; 1043 sqlite3BtreeDataSize(pCur, &n); 1044 zBuf = malloc( n+1 ); 1045 rc = sqlite3BtreeData(pCur, 0, n, zBuf); 1046 if( rc ){ 1047 Tcl_AppendResult(interp, errorName(rc), 0); 1048 return TCL_ERROR; 1049 } 1050 zBuf[n] = 0; 1051 Tcl_AppendResult(interp, zBuf, 0); 1052 free(zBuf); 1053 return SQLITE_OK; 1054 } 1055 1056 /* 1057 ** Usage: btree_fetch_key ID AMT 1058 ** 1059 ** Use the sqlite3BtreeKeyFetch() routine to get AMT bytes of the key. 1060 ** If sqlite3BtreeKeyFetch() fails, return an empty string. 1061 */ 1062 static int btree_fetch_key( 1063 void *NotUsed, 1064 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1065 int argc, /* Number of arguments */ 1066 const char **argv /* Text of each argument */ 1067 ){ 1068 BtCursor *pCur; 1069 int n; 1070 int amt; 1071 u64 nKey; 1072 const char *zBuf; 1073 char zStatic[1000]; 1074 1075 if( argc!=3 ){ 1076 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1077 " ID AMT\"", 0); 1078 return TCL_ERROR; 1079 } 1080 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR; 1081 if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; 1082 sqlite3BtreeKeySize(pCur, &nKey); 1083 zBuf = sqlite3BtreeKeyFetch(pCur, &amt); 1084 if( zBuf && amt>=n ){ 1085 assert( nKey<sizeof(zStatic) ); 1086 if( n>0 ) nKey = n; 1087 memcpy(zStatic, zBuf, (int)nKey); 1088 zStatic[nKey] = 0; 1089 Tcl_AppendResult(interp, zStatic, 0); 1090 } 1091 return TCL_OK; 1092 } 1093 1094 /* 1095 ** Usage: btree_fetch_data ID AMT 1096 ** 1097 ** Use the sqlite3BtreeDataFetch() routine to get AMT bytes of the key. 1098 ** If sqlite3BtreeDataFetch() fails, return an empty string. 1099 */ 1100 static int btree_fetch_data( 1101 void *NotUsed, 1102 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1103 int argc, /* Number of arguments */ 1104 const char **argv /* Text of each argument */ 1105 ){ 1106 BtCursor *pCur; 1107 int n; 1108 int amt; 1109 u32 nData; 1110 const char *zBuf; 1111 char zStatic[1000]; 1112 1113 if( argc!=3 ){ 1114 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1115 " ID AMT\"", 0); 1116 return TCL_ERROR; 1117 } 1118 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR; 1119 if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; 1120 sqlite3BtreeDataSize(pCur, &nData); 1121 zBuf = sqlite3BtreeDataFetch(pCur, &amt); 1122 if( zBuf && amt>=n ){ 1123 assert( nData<sizeof(zStatic) ); 1124 if( n>0 ) nData = n; 1125 memcpy(zStatic, zBuf, (int)nData); 1126 zStatic[nData] = 0; 1127 Tcl_AppendResult(interp, zStatic, 0); 1128 } 1129 return TCL_OK; 1130 } 1131 1132 /* 1133 ** Usage: btree_payload_size ID 1134 ** 1135 ** Return the number of bytes of payload 1136 */ 1137 static int btree_payload_size( 1138 void *NotUsed, 1139 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1140 int argc, /* Number of arguments */ 1141 const char **argv /* Text of each argument */ 1142 ){ 1143 BtCursor *pCur; 1144 int n2; 1145 u64 n1; 1146 char zBuf[50]; 1147 1148 if( argc!=2 ){ 1149 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1150 " ID\"", 0); 1151 return TCL_ERROR; 1152 } 1153 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR; 1154 if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){ 1155 n1 = 0; 1156 }else{ 1157 sqlite3BtreeKeySize(pCur, &n1); 1158 } 1159 sqlite3BtreeDataSize(pCur, &n2); 1160 sprintf(zBuf, "%d", (int)(n1+n2)); 1161 Tcl_AppendResult(interp, zBuf, 0); 1162 return SQLITE_OK; 1163 } 1164 1165 /* 1166 ** Usage: btree_cursor_info ID 1167 ** 1168 ** Return eight integers containing information about the entry the 1169 ** cursor is pointing to: 1170 ** 1171 ** aResult[0] = The page number 1172 ** aResult[1] = The entry number 1173 ** aResult[2] = Total number of entries on this page 1174 ** aResult[3] = Size of this entry 1175 ** aResult[4] = Number of free bytes on this page 1176 ** aResult[5] = Number of free blocks on the page 1177 ** aResult[6] = Page number of the left child of this entry 1178 ** aResult[7] = Page number of the right child for the whole page 1179 */ 1180 static int btree_cursor_info( 1181 void *NotUsed, 1182 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1183 int argc, /* Number of arguments */ 1184 const char **argv /* Text of each argument */ 1185 ){ 1186 BtCursor *pCur; 1187 int rc; 1188 int i, j; 1189 int aResult[8]; 1190 char zBuf[400]; 1191 1192 if( argc!=2 ){ 1193 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1194 " ID\"", 0); 1195 return TCL_ERROR; 1196 } 1197 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR; 1198 rc = sqlite3BtreeCursorInfo(pCur, aResult); 1199 if( rc ){ 1200 Tcl_AppendResult(interp, errorName(rc), 0); 1201 return TCL_ERROR; 1202 } 1203 j = 0; 1204 for(i=0; i<sizeof(aResult)/sizeof(aResult[0]); i++){ 1205 sprintf(&zBuf[j]," %d", aResult[i]); 1206 j += strlen(&zBuf[j]); 1207 } 1208 Tcl_AppendResult(interp, &zBuf[1], 0); 1209 return SQLITE_OK; 1210 } 1211 1212 /* 1213 ** The command is provided for the purpose of setting breakpoints. 1214 ** in regression test scripts. 1215 ** 1216 ** By setting a GDB breakpoint on this procedure and executing the 1217 ** btree_breakpoint command in a test script, we can stop GDB at 1218 ** the point in the script where the btree_breakpoint command is 1219 ** inserted. This is useful for debugging. 1220 */ 1221 static int btree_breakpoint( 1222 void *NotUsed, 1223 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1224 int argc, /* Number of arguments */ 1225 const char **argv /* Text of each argument */ 1226 ){ 1227 return TCL_OK; 1228 } 1229 1230 /* 1231 ** usage: varint_test START MULTIPLIER COUNT INCREMENT 1232 ** 1233 ** This command tests the sqlite3PutVarint() and sqlite3GetVarint() 1234 ** routines, both for accuracy and for speed. 1235 ** 1236 ** An integer is written using PutVarint() and read back with 1237 ** GetVarint() and varified to be unchanged. This repeats COUNT 1238 ** times. The first integer is START*MULTIPLIER. Each iteration 1239 ** increases the integer by INCREMENT. 1240 ** 1241 ** This command returns nothing if it works. It returns an error message 1242 ** if something goes wrong. 1243 */ 1244 static int btree_varint_test( 1245 void *NotUsed, 1246 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 1247 int argc, /* Number of arguments */ 1248 const char **argv /* Text of each argument */ 1249 ){ 1250 u32 start, mult, count, incr; 1251 u64 in, out; 1252 int n1, n2, i, j; 1253 unsigned char zBuf[100]; 1254 if( argc!=5 ){ 1255 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 1256 " START MULTIPLIER COUNT INCREMENT\"", 0); 1257 return TCL_ERROR; 1258 } 1259 if( Tcl_GetInt(interp, argv[1], (int*)&start) ) return TCL_ERROR; 1260 if( Tcl_GetInt(interp, argv[2], (int*)&mult) ) return TCL_ERROR; 1261 if( Tcl_GetInt(interp, argv[3], (int*)&count) ) return TCL_ERROR; 1262 if( Tcl_GetInt(interp, argv[4], (int*)&incr) ) return TCL_ERROR; 1263 in = start; 1264 in *= mult; 1265 for(i=0; i<count; i++){ 1266 char zErr[200]; 1267 n1 = sqlite3PutVarint(zBuf, in); 1268 if( n1>9 || n1<1 ){ 1269 sprintf(zErr, "PutVarint returned %d - should be between 1 and 9", n1); 1270 Tcl_AppendResult(interp, zErr, 0); 1271 return TCL_ERROR; 1272 } 1273 n2 = sqlite3GetVarint(zBuf, &out); 1274 if( n1!=n2 ){ 1275 sprintf(zErr, "PutVarint returned %d and GetVarint returned %d", n1, n2); 1276 Tcl_AppendResult(interp, zErr, 0); 1277 return TCL_ERROR; 1278 } 1279 if( in!=out ){ 1280 sprintf(zErr, "Wrote 0x%016llx and got back 0x%016llx", in, out); 1281 Tcl_AppendResult(interp, zErr, 0); 1282 return TCL_ERROR; 1283 } 1284 1285 /* In order to get realistic timings, run getVarint 19 more times. 1286 ** This is because getVarint is called about 20 times more often 1287 ** than putVarint. 1288 */ 1289 for(j=0; j<19; j++){ 1290 sqlite3GetVarint(zBuf, &out); 1291 } 1292 in += incr; 1293 } 1294 return TCL_OK; 1295 } 1296 1297 /* 1298 ** Register commands with the TCL interpreter. 1299 */ 1300 int Sqlitetest3_Init(Tcl_Interp *interp){ 1301 extern int sqlite3_btree_trace; 1302 static struct { 1303 char *zName; 1304 Tcl_CmdProc *xProc; 1305 } aCmd[] = { 1306 { "btree_open", (Tcl_CmdProc*)btree_open }, 1307 { "btree_close", (Tcl_CmdProc*)btree_close }, 1308 { "btree_begin_transaction", (Tcl_CmdProc*)btree_begin_transaction }, 1309 { "btree_commit", (Tcl_CmdProc*)btree_commit }, 1310 { "btree_rollback", (Tcl_CmdProc*)btree_rollback }, 1311 { "btree_create_table", (Tcl_CmdProc*)btree_create_table }, 1312 { "btree_drop_table", (Tcl_CmdProc*)btree_drop_table }, 1313 { "btree_clear_table", (Tcl_CmdProc*)btree_clear_table }, 1314 { "btree_get_meta", (Tcl_CmdProc*)btree_get_meta }, 1315 { "btree_update_meta", (Tcl_CmdProc*)btree_update_meta }, 1316 { "btree_page_dump", (Tcl_CmdProc*)btree_page_dump }, 1317 { "btree_tree_dump", (Tcl_CmdProc*)btree_tree_dump }, 1318 { "btree_pager_stats", (Tcl_CmdProc*)btree_pager_stats }, 1319 { "btree_pager_ref_dump", (Tcl_CmdProc*)btree_pager_ref_dump }, 1320 { "btree_cursor", (Tcl_CmdProc*)btree_cursor }, 1321 { "btree_close_cursor", (Tcl_CmdProc*)btree_close_cursor }, 1322 { "btree_move_to", (Tcl_CmdProc*)btree_move_to }, 1323 { "btree_delete", (Tcl_CmdProc*)btree_delete }, 1324 { "btree_insert", (Tcl_CmdProc*)btree_insert }, 1325 { "btree_next", (Tcl_CmdProc*)btree_next }, 1326 { "btree_prev", (Tcl_CmdProc*)btree_prev }, 1327 { "btree_eof", (Tcl_CmdProc*)btree_eof }, 1328 { "btree_keysize", (Tcl_CmdProc*)btree_keysize }, 1329 { "btree_key", (Tcl_CmdProc*)btree_key }, 1330 { "btree_data", (Tcl_CmdProc*)btree_data }, 1331 { "btree_fetch_key", (Tcl_CmdProc*)btree_fetch_key }, 1332 { "btree_fetch_data", (Tcl_CmdProc*)btree_fetch_data }, 1333 { "btree_payload_size", (Tcl_CmdProc*)btree_payload_size }, 1334 { "btree_first", (Tcl_CmdProc*)btree_first }, 1335 { "btree_last", (Tcl_CmdProc*)btree_last }, 1336 { "btree_cursor_info", (Tcl_CmdProc*)btree_cursor_info }, 1337 { "btree_cursor_list", (Tcl_CmdProc*)btree_cursor_list }, 1338 { "btree_integrity_check", (Tcl_CmdProc*)btree_integrity_check }, 1339 { "btree_breakpoint", (Tcl_CmdProc*)btree_breakpoint }, 1340 { "btree_varint_test", (Tcl_CmdProc*)btree_varint_test }, 1341 { "btree_begin_statement", (Tcl_CmdProc*)btree_begin_statement }, 1342 { "btree_commit_statement", (Tcl_CmdProc*)btree_commit_statement }, 1343 { "btree_rollback_statement", (Tcl_CmdProc*)btree_rollback_statement }, 1344 }; 1345 int i; 1346 1347 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ 1348 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); 1349 } 1350 Tcl_LinkVar(interp, "pager_refinfo_enable", (char*)&pager3_refinfo_enable, 1351 TCL_LINK_INT); 1352 Tcl_LinkVar(interp, "btree_trace", (char*)&sqlite3_btree_trace, 1353 TCL_LINK_INT); 1354 return TCL_OK; 1355 } 1356