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