1# 2001 September 15 2# 3# The author disclaims copyright to this source code. In place of 4# a legal notice, here is a blessing: 5# 6# May you do good and not evil. 7# May you find forgiveness for yourself and forgive others. 8# May you share freely, never taking more than you give. 9# 10#*********************************************************************** 11# This file implements regression tests for SQLite library. The 12# focus of this script is btree database backend 13# 14# $Id: btree.test,v 1.15 2004/02/10 01:54:28 drh Exp $ 15 16 17set testdir [file dirname $argv0] 18source $testdir/tester.tcl 19 20if {[info commands btree_open]!="" && $SQLITE_PAGE_SIZE==1024 21 && $SQLITE_USABLE_SIZE==1024} { 22 23# Basic functionality. Open and close a database. 24# 25do_test btree-1.1 { 26 file delete -force test1.bt 27 file delete -force test1.bt-journal 28 set rc [catch {btree_open test1.bt} ::b1] 29} {0} 30 31# The second element of the list returned by btree_pager_stats is the 32# number of pages currently checked out. We'll be checking this value 33# frequently during this test script, to make sure the btree library 34# is properly releasing the pages it checks out, and thus avoiding 35# page leaks. 36# 37do_test btree-1.1.1 { 38 lindex [btree_pager_stats $::b1] 1 39} {0} 40do_test btree-1.2 { 41 set rc [catch {btree_open test1.bt} ::b2] 42} {0} 43do_test btree-1.3 { 44 set rc [catch {btree_close $::b2} msg] 45 lappend rc $msg 46} {0 {}} 47 48# Do an insert and verify that the database file grows in size. 49# 50do_test btree-1.4 { 51 set rc [catch {btree_begin_transaction $::b1} msg] 52 lappend rc $msg 53} {0 {}} 54do_test btree-1.4.1 { 55 lindex [btree_pager_stats $::b1] 1 56} {1} 57do_test btree-1.5 { 58 set rc [catch {btree_cursor $::b1 2 1} ::c1] 59 if {$rc} {lappend rc $::c1} 60 set rc 61} {0} 62do_test btree-1.6 { 63 set rc [catch {btree_insert $::c1 one 1.00} msg] 64 lappend rc $msg 65} {0 {}} 66do_test btree-1.7 { 67 btree_key $::c1 68} {one} 69do_test btree-1.8 { 70 btree_data $::c1 71} {1.00} 72do_test btree-1.9 { 73 set rc [catch {btree_close_cursor $::c1} msg] 74 lappend rc $msg 75} {0 {}} 76do_test btree-1.10 { 77 set rc [catch {btree_commit $::b1} msg] 78 lappend rc $msg 79} {0 {}} 80do_test btree-1.11 { 81 file size test1.bt 82} {2048} 83do_test btree-1.12 { 84 lindex [btree_pager_stats $::b1] 1 85} {0} 86 87# Reopen the database and attempt to read the record that we wrote. 88# 89do_test btree-2.1 { 90 set rc [catch {btree_cursor $::b1 2 1} ::c1] 91 if {$rc} {lappend rc $::c1} 92 set rc 93} {0} 94do_test btree-2.2 { 95 btree_move_to $::c1 abc 96} {1} 97do_test btree-2.3 { 98 btree_move_to $::c1 xyz 99} {-1} 100do_test btree-2.4 { 101 btree_move_to $::c1 one 102} {0} 103do_test btree-2.5 { 104 btree_key $::c1 105} {one} 106do_test btree-2.6 { 107 btree_data $::c1 108} {1.00} 109do_test btree-2.7 { 110 lindex [btree_pager_stats $::b1] 1 111} {2} 112 113# Do some additional inserts 114# 115do_test btree-3.1 { 116 btree_begin_transaction $::b1 117 btree_insert $::c1 two 2.00 118 btree_key $::c1 119} {two} 120do_test btree-3.1.1 { 121 lindex [btree_pager_stats $::b1] 1 122} {2} 123do_test btree-3.2 { 124 btree_insert $::c1 three 3.00 125 btree_key $::c1 126} {three} 127do_test btree-3.4 { 128 btree_insert $::c1 four 4.00 129 btree_key $::c1 130} {four} 131do_test btree-3.5 { 132 btree_insert $::c1 five 5.00 133 btree_key $::c1 134} {five} 135do_test btree-3.6 { 136 btree_insert $::c1 six 6.00 137 btree_key $::c1 138} {six} 139#btree_page_dump $::b1 2 140do_test btree-3.7 { 141 set rc [btree_move_to $::c1 {}] 142 expr {$rc>0} 143} {1} 144do_test btree-3.8 { 145 btree_key $::c1 146} {five} 147do_test btree-3.9 { 148 btree_data $::c1 149} {5.00} 150do_test btree-3.10 { 151 btree_next $::c1 152 btree_key $::c1 153} {four} 154do_test btree-3.11 { 155 btree_data $::c1 156} {4.00} 157do_test btree-3.12 { 158 btree_next $::c1 159 btree_key $::c1 160} {one} 161do_test btree-3.13 { 162 btree_data $::c1 163} {1.00} 164do_test btree-3.14 { 165 btree_next $::c1 166 btree_key $::c1 167} {six} 168do_test btree-3.15 { 169 btree_data $::c1 170} {6.00} 171do_test btree-3.16 { 172 btree_next $::c1 173 btree_key $::c1 174} {three} 175do_test btree-3.17 { 176 btree_data $::c1 177} {3.00} 178do_test btree-3.18 { 179 btree_next $::c1 180 btree_key $::c1 181} {two} 182do_test btree-3.19 { 183 btree_data $::c1 184} {2.00} 185do_test btree-3.20 { 186 btree_next $::c1 187 btree_key $::c1 188} {} 189do_test btree-3.21 { 190 btree_data $::c1 191} {} 192 193# Commit the changes, reopen and reread the data 194# 195do_test btree-3.22 { 196 set rc [catch {btree_close_cursor $::c1} msg] 197 lappend rc $msg 198} {0 {}} 199do_test btree-3.22.1 { 200 lindex [btree_pager_stats $::b1] 1 201} {1} 202do_test btree-3.23 { 203 set rc [catch {btree_commit $::b1} msg] 204 lappend rc $msg 205} {0 {}} 206do_test btree-3.23.1 { 207 lindex [btree_pager_stats $::b1] 1 208} {0} 209do_test btree-3.24 { 210 file size test1.bt 211} {2048} 212do_test btree-3.25 { 213 set rc [catch {btree_cursor $::b1 2 1} ::c1] 214 if {$rc} {lappend rc $::c1} 215 set rc 216} {0} 217do_test btree-3.25.1 { 218 lindex [btree_pager_stats $::b1] 1 219} {2} 220do_test btree-3.26 { 221 set rc [btree_move_to $::c1 {}] 222 expr {$rc>0} 223} {1} 224do_test btree-3.27 { 225 btree_key $::c1 226} {five} 227do_test btree-3.28 { 228 btree_data $::c1 229} {5.00} 230do_test btree-3.29 { 231 btree_next $::c1 232 btree_key $::c1 233} {four} 234do_test btree-3.30 { 235 btree_data $::c1 236} {4.00} 237do_test btree-3.31 { 238 btree_next $::c1 239 btree_key $::c1 240} {one} 241do_test btree-3.32 { 242 btree_data $::c1 243} {1.00} 244do_test btree-3.33 { 245 btree_next $::c1 246 btree_key $::c1 247} {six} 248do_test btree-3.34 { 249 btree_data $::c1 250} {6.00} 251do_test btree-3.35 { 252 btree_next $::c1 253 btree_key $::c1 254} {three} 255do_test btree-3.36 { 256 btree_data $::c1 257} {3.00} 258do_test btree-3.37 { 259 btree_next $::c1 260 btree_key $::c1 261} {two} 262do_test btree-3.38 { 263 btree_data $::c1 264} {2.00} 265do_test btree-3.39 { 266 btree_next $::c1 267 btree_key $::c1 268} {} 269do_test btree-3.40 { 270 btree_data $::c1 271} {} 272do_test btree-3.41 { 273 lindex [btree_pager_stats $::b1] 1 274} {2} 275 276 277# Now try a delete 278# 279do_test btree-4.1 { 280 btree_begin_transaction $::b1 281 btree_move_to $::c1 one 282 btree_key $::c1 283} {one} 284do_test btree-4.1.1 { 285 lindex [btree_pager_stats $::b1] 1 286} {2} 287do_test btree-4.2 { 288 btree_delete $::c1 289} {} 290do_test btree-4.3 { 291 btree_key $::c1 292} {six} 293do_test btree-4.4 { 294 btree_next $::c1 295 btree_key $::c1 296} {six} 297do_test btree-4.5 { 298 btree_next $::c1 299 btree_key $::c1 300} {three} 301do_test btree-4.4 { 302 btree_move_to $::c1 {} 303 set r {} 304 while 1 { 305 set key [btree_key $::c1] 306 if {$key==""} break 307 lappend r $key 308 lappend r [btree_data $::c1] 309 btree_next $::c1 310 } 311 set r 312} {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00} 313 314# Commit and make sure the delete is still there. 315# 316do_test btree-4.5 { 317 btree_commit $::b1 318 btree_move_to $::c1 {} 319 set r {} 320 while 1 { 321 set key [btree_key $::c1] 322 if {$key==""} break 323 lappend r $key 324 lappend r [btree_data $::c1] 325 btree_next $::c1 326 } 327 set r 328} {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00} 329 330# Completely close the database and reopen it. Then check 331# the data again. 332# 333do_test btree-4.6 { 334 lindex [btree_pager_stats $::b1] 1 335} {2} 336do_test btree-4.7 { 337 btree_close_cursor $::c1 338 lindex [btree_pager_stats $::b1] 1 339} {0} 340do_test btree-4.8 { 341 btree_close $::b1 342 set ::b1 [btree_open test1.bt] 343 set ::c1 [btree_cursor $::b1 2 1] 344 lindex [btree_pager_stats $::b1] 1 345} {2} 346do_test btree-4.9 { 347 set r {} 348 btree_first $::c1 349 while 1 { 350 set key [btree_key $::c1] 351 if {$key==""} break 352 lappend r $key 353 lappend r [btree_data $::c1] 354 btree_next $::c1 355 } 356 set r 357} {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00} 358 359# Try to read and write meta data 360# 361do_test btree-5.1 { 362 btree_get_meta $::b1 363} {0 0 0 0 0 0 0 0 0 0} 364do_test btree-5.2 { 365 set rc [catch {btree_update_meta $::b1 1 2 3 4 5 6 7 8 9 10} msg] 366 lappend rc $msg 367} {1 SQLITE_ERROR} 368do_test btree-5.3 { 369 btree_begin_transaction $::b1 370 set rc [catch {btree_update_meta $::b1 1 2 3 4 5 6 7 8 9 10} msg] 371 lappend rc $msg 372} {0 {}} 373do_test btree-5.4 { 374 btree_get_meta $::b1 375} {0 2 3 4 5 6 7 8 9 10} 376do_test btree-5.5 { 377 btree_close_cursor $::c1 378 btree_rollback $::b1 379 btree_get_meta $::b1 380} {0 0 0 0 0 0 0 0 0 0} 381do_test btree-5.6 { 382 btree_begin_transaction $::b1 383 btree_update_meta $::b1 999 10 20 30 40 50 60 70 80 90 384 btree_commit $::b1 385 btree_get_meta $::b1 386} {0 10 20 30 40 50 60 70 80 90} 387 388proc select_all {cursor} { 389 set r {} 390 btree_move_to $cursor {} 391 while 1 { 392 set key [btree_key $cursor] 393 if {$key==""} break 394 lappend r $key 395 lappend r [btree_data $cursor] 396 btree_next $cursor 397 } 398 return $r 399} 400proc select_keys {cursor} { 401 set r {} 402 btree_move_to $cursor {} 403 while 1 { 404 set key [btree_key $cursor] 405 if {$key==""} break 406 lappend r $key 407 btree_next $cursor 408 } 409 return $r 410} 411 412# Try to create a new table in the database file 413# 414do_test btree-6.1 { 415 set rc [catch {btree_create_table $::b1} msg] 416 lappend rc $msg 417} {1 SQLITE_ERROR} 418do_test btree-6.2 { 419 btree_begin_transaction $::b1 420 set ::t2 [btree_create_table $::b1] 421} {3} 422do_test btree-6.2.1 { 423 lindex [btree_pager_stats $::b1] 1 424} {1} 425do_test btree-6.2.2 { 426 set ::c2 [btree_cursor $::b1 $::t2 1] 427 lindex [btree_pager_stats $::b1] 1 428} {2} 429do_test btree-6.2.3 { 430 btree_insert $::c2 ten 10 431 btree_key $::c2 432} {ten} 433do_test btree-6.3 { 434 btree_commit $::b1 435 set ::c1 [btree_cursor $::b1 2 1] 436 lindex [btree_pager_stats $::b1] 1 437} {3} 438do_test btree-6.3.1 { 439 select_all $::c1 440} {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00} 441#btree_page_dump $::b1 3 442do_test btree-6.4 { 443 select_all $::c2 444} {ten 10} 445 446# Drop the new table, then create it again anew. 447# 448do_test btree-6.5 { 449 btree_begin_transaction $::b1 450} {} 451do_test btree-6.6 { 452 btree_close_cursor $::c2 453} {} 454do_test btree-6.6.1 { 455 lindex [btree_pager_stats $::b1] 1 456} {2} 457do_test btree-6.7 { 458 btree_drop_table $::b1 $::t2 459} {} 460do_test btree-6.7.1 { 461 lindex [btree_get_meta $::b1] 0 462} {1} 463do_test btree-6.8 { 464 set ::t2 [btree_create_table $::b1] 465} {3} 466do_test btree-6.8.1 { 467 lindex [btree_get_meta $::b1] 0 468} {0} 469do_test btree-6.9 { 470 set ::c2 [btree_cursor $::b1 $::t2 1] 471 lindex [btree_pager_stats $::b1] 1 472} {3} 473 474do_test btree-6.9.1 { 475 btree_move_to $::c2 {} 476 btree_key $::c2 477} {} 478 479# If we drop table 2 it just clears the table. Table 2 always exists. 480# 481do_test btree-6.10 { 482 btree_close_cursor $::c1 483 btree_drop_table $::b1 2 484 set ::c1 [btree_cursor $::b1 2 1] 485 btree_move_to $::c1 {} 486 btree_key $::c1 487} {} 488do_test btree-6.11 { 489 btree_commit $::b1 490 select_all $::c1 491} {} 492do_test btree-6.12 { 493 select_all $::c2 494} {} 495do_test btree-6.13 { 496 btree_close_cursor $::c2 497 lindex [btree_pager_stats $::b1] 1 498} {2} 499 500# Check to see that pages defragment properly. To do this test we will 501# 502# 1. Fill the first page table 2 with data. 503# 2. Delete every other entry of table 2. 504# 3. Insert a single entry that requires more contiguous 505# space than is available. 506# 507do_test btree-7.1 { 508 btree_begin_transaction $::b1 509} {} 510catch {unset key} 511catch {unset data} 512do_test btree-7.2 { 513 for {set i 0} {$i<36} {incr i} { 514 set key [format %03d $i] 515 set data "*** $key ***" 516 btree_insert $::c1 $key $data 517 } 518 lrange [btree_cursor_dump $::c1] 4 5 519} {8 1} 520do_test btree-7.3 { 521 btree_move_to $::c1 000 522 while {[btree_key $::c1]!=""} { 523 btree_delete $::c1 524 btree_next $::c1 525 btree_next $::c1 526 } 527 lrange [btree_cursor_dump $::c1] 4 5 528} {512 19} 529#btree_page_dump $::b1 2 530do_test btree-7.4 { 531 btree_insert $::c1 018 {*** 018 ***+++} 532 btree_key $::c1 533} {018} 534do_test btree-7.5 { 535 lrange [btree_cursor_dump $::c1] 4 5 536} {480 1} 537#btree_page_dump $::b1 2 538 539# Delete an entry to make a hole of a known size, then immediately recreate 540# that entry. This tests the path into allocateSpace where the hole exactly 541# matches the size of the desired space. 542# 543do_test btree-7.6 { 544 btree_move_to $::c1 007 545 btree_delete $::c1 546 btree_move_to $::c1 011 547 btree_delete $::c1 548} {} 549do_test btree-7.7 { 550 lindex [btree_cursor_dump $::c1] 5 551} {3} 552#btree_page_dump $::b1 2 553do_test btree-7.8 { 554 btree_insert $::c1 007 {*** 007 ***} 555 lindex [btree_cursor_dump $::c1] 5 556} {2} 557#btree_page_dump $::b1 2 558 559# Make sure the freeSpace() routine properly coaleses adjacent memory blocks 560# 561do_test btree-7.9 { 562 btree_move_to $::c1 013 563 btree_delete $::c1 564 lrange [btree_cursor_dump $::c1] 4 5 565} {536 2} 566do_test btree-7.10 { 567 btree_move_to $::c1 009 568 btree_delete $::c1 569 lrange [btree_cursor_dump $::c1] 4 5 570} {564 2} 571do_test btree-7.11 { 572 btree_move_to $::c1 018 573 btree_delete $::c1 574 lrange [btree_cursor_dump $::c1] 4 5 575} {596 2} 576do_test btree-7.13 { 577 btree_move_to $::c1 033 578 btree_delete $::c1 579 lrange [btree_cursor_dump $::c1] 4 5 580} {624 3} 581do_test btree-7.14 { 582 btree_move_to $::c1 035 583 btree_delete $::c1 584 lrange [btree_cursor_dump $::c1] 4 5 585} {652 2} 586#btree_page_dump $::b1 2 587do_test btree-7.15 { 588 lindex [btree_pager_stats $::b1] 1 589} {2} 590 591# Check to see that data on overflow pages work correctly. 592# 593do_test btree-8.1 { 594 set data "*** This is a very long key " 595 while {[string length $data]<256} {append data $data} 596 set ::data $data 597 btree_insert $::c1 020 $data 598} {} 599#btree_page_dump $::b1 2 600do_test btree-8.1.1 { 601 lindex [btree_pager_stats $::b1] 1 602} {2} 603#btree_pager_ref_dump $::b1 604do_test btree-8.2 { 605 string length [btree_data $::c1] 606} [string length $::data] 607do_test btree-8.3 { 608 btree_data $::c1 609} $::data 610do_test btree-8.4 { 611 btree_delete $::c1 612} {} 613do_test btree-8.4.1 { 614 lindex [btree_get_meta $::b1] 0 615} [expr {int(([string length $::data]-238+1019)/1020)}] 616do_test btree-8.5 { 617 set data "*** This is an even longer key" 618 while {[string length $data]<2000} {append data $data} 619 set ::data $data 620 btree_insert $::c1 020 $data 621} {} 622do_test btree-8.6 { 623 string length [btree_data $::c1] 624} [string length $::data] 625do_test btree-8.7 { 626 btree_data $::c1 627} $::data 628do_test btree-8.8 { 629 btree_commit $::b1 630 btree_data $::c1 631} $::data 632do_test btree-8.9 { 633 btree_close_cursor $::c1 634 btree_close $::b1 635 set ::b1 [btree_open test1.bt] 636 set ::c1 [btree_cursor $::b1 2 1] 637 btree_move_to $::c1 020 638 btree_data $::c1 639} $::data 640do_test btree-8.10 { 641 btree_begin_transaction $::b1 642 btree_delete $::c1 643} {} 644do_test btree-8.11 { 645 lindex [btree_get_meta $::b1] 0 646} [expr {int(([string length $::data]-238+1019)/1020)}] 647 648# Now check out keys on overflow pages. 649# 650do_test btree-8.12 { 651 set ::keyprefix "This is a long prefix to a key " 652 while {[string length $::keyprefix]<256} {append ::keyprefix $::keyprefix} 653 btree_close_cursor $::c1 654 btree_drop_table $::b1 2 655 lindex [btree_get_meta $::b1] 0 656} {4} 657do_test btree-8.12.1 { 658 set ::c1 [btree_cursor $::b1 2 1] 659 btree_insert $::c1 ${::keyprefix}1 1 660 btree_data $::c1 661} {1} 662do_test btree-8.13 { 663 btree_key $::c1 664} ${keyprefix}1 665do_test btree-8.14 { 666 btree_insert $::c1 ${::keyprefix}2 2 667 btree_insert $::c1 ${::keyprefix}3 3 668 btree_key $::c1 669} ${keyprefix}3 670do_test btree-8.15 { 671 btree_move_to $::c1 ${::keyprefix}2 672 btree_data $::c1 673} {2} 674do_test btree-8.16 { 675 btree_move_to $::c1 ${::keyprefix}1 676 btree_data $::c1 677} {1} 678do_test btree-8.17 { 679 btree_move_to $::c1 ${::keyprefix}3 680 btree_data $::c1 681} {3} 682do_test btree-8.18 { 683 lindex [btree_get_meta $::b1] 0 684} {1} 685do_test btree-8.19 { 686 btree_move_to $::c1 ${::keyprefix}2 687 btree_key $::c1 688} ${::keyprefix}2 689#btree_page_dump $::b1 2 690do_test btree-8.20 { 691 btree_delete $::c1 692 btree_next $::c1 693 btree_key $::c1 694} ${::keyprefix}3 695#btree_page_dump $::b1 2 696do_test btree-8.21 { 697 lindex [btree_get_meta $::b1] 0 698} {2} 699do_test btree-8.22 { 700 lindex [btree_pager_stats $::b1] 1 701} {2} 702do_test btree-8.23 { 703 btree_close_cursor $::c1 704 btree_drop_table $::b1 2 705 set ::c1 [btree_cursor $::b1 2 1] 706 lindex [btree_get_meta $::b1] 0 707} {4} 708do_test btree-8.24 { 709 lindex [btree_pager_stats $::b1] 1 710} {2} 711#btree_pager_ref_dump $::b1 712 713# Check page splitting logic 714# 715do_test btree-9.1 { 716 for {set i 1} {$i<=19} {incr i} { 717 set key [format %03d $i] 718 set data "*** $key *** $key *** $key *** $key ***" 719 btree_insert $::c1 $key $data 720 } 721} {} 722#btree_tree_dump $::b1 2 723#btree_pager_ref_dump $::b1 724#set pager_refinfo_enable 1 725do_test btree-9.2 { 726 btree_insert $::c1 020 {*** 020 *** 020 *** 020 *** 020 ***} 727 select_keys $::c1 728} {001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020} 729#btree_page_dump $::b1 5 730#btree_page_dump $::b1 2 731#btree_page_dump $::b1 7 732#btree_pager_ref_dump $::b1 733#set pager_refinfo_enable 0 734 735# The previous "select_keys" command left the cursor pointing at the root 736# page. So there should only be two pages checked out. 2 (the root) and 737# page 1. 738do_test btree-9.2.1 { 739 lindex [btree_pager_stats $::b1] 1 740} {2} 741for {set i 1} {$i<=20} {incr i} { 742 do_test btree-9.3.$i.1 [subst { 743 btree_move_to $::c1 [format %03d $i] 744 btree_key $::c1 745 }] [format %03d $i] 746 do_test btree-9.3.$i.2 [subst { 747 btree_move_to $::c1 [format %03d $i] 748 string range \[btree_data $::c1\] 0 10 749 }] "*** [format %03d $i] ***" 750} 751do_test btree-9.4.1 { 752 lindex [btree_pager_stats $::b1] 1 753} {3} 754 755# Check the page joining logic. 756# 757#btree_page_dump $::b1 2 758#btree_pager_ref_dump $::b1 759do_test btree-9.4.2 { 760 btree_move_to $::c1 005 761 btree_delete $::c1 762} {} 763#btree_page_dump $::b1 2 764for {set i 1} {$i<=19} {incr i} { 765 if {$i==5} continue 766 do_test btree-9.5.$i.1 [subst { 767 btree_move_to $::c1 [format %03d $i] 768 btree_key $::c1 769 }] [format %03d $i] 770 do_test btree-9.5.$i.2 [subst { 771 btree_move_to $::c1 [format %03d $i] 772 string range \[btree_data $::c1\] 0 10 773 }] "*** [format %03d $i] ***" 774} 775#btree_pager_ref_dump $::b1 776do_test btree-9.6 { 777 btree_close_cursor $::c1 778 lindex [btree_pager_stats $::b1] 1 779} {1} 780do_test btree-9.7 { 781 btree_rollback $::b1 782 lindex [btree_pager_stats $::b1] 1 783} {0} 784 785# Create a tree of depth two. That is, there is a single divider entry 786# on the root pages and two leaf pages. Then delete the divider entry 787# see what happens. 788# 789do_test btree-10.1 { 790 btree_begin_transaction $::b1 791 btree_drop_table $::b1 2 792 lindex [btree_pager_stats $::b1] 1 793} {1} 794do_test btree-10.2 { 795 set ::c1 [btree_cursor $::b1 2 1] 796 lindex [btree_pager_stats $::b1] 1 797} {2} 798do_test btree-10.3 { 799 for {set i 1} {$i<=20} {incr i} { 800 set key [format %03d $i] 801 set data "*** $key *** $key *** $key *** $key ***" 802 btree_insert $::c1 $key $data 803 } 804 select_keys $::c1 805} {001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020} 806#btree_page_dump $::b1 7 807#btree_page_dump $::b1 2 808#btree_page_dump $::b1 6 809do_test btree-10.4 { 810 btree_move_to $::c1 011 811 btree_delete $::c1 812 select_keys $::c1 813} {001 002 003 004 005 006 007 008 009 010 012 013 014 015 016 017 018 019 020} 814#btree_tree_dump $::b1 2 815#btree_pager_ref_dump $::b1 816for {set i 1} {$i<=20} {incr i} { 817 do_test btree-10.5.$i { 818 btree_move_to $::c1 [format %03d $i] 819 lindex [btree_pager_stats $::b1] 1 820 } {2} 821 #btree_pager_ref_dump $::b1 822 #btree_tree_dump $::b1 2 823} 824 825# Create a tree with lots more pages 826# 827catch {unset ::data} 828catch {unset ::key} 829for {set i 21} {$i<=1000} {incr i} { 830 do_test btree-11.1.$i.1 { 831 set key [format %03d $i] 832 set ::data "*** $key *** $key *** $key *** $key ***" 833 btree_insert $::c1 $key $data 834 btree_key $::c1 835 } [format %03d $i] 836 do_test btree-11.1.$i.2 { 837 btree_data $::c1 838 } $::data 839 set ::key [format %03d [expr {$i/2}]] 840 if {$::key=="011"} {set ::key 010} 841 do_test btree-11.1.$i.3 { 842 btree_move_to $::c1 $::key 843 btree_key $::c1 844 } $::key 845} 846catch {unset ::data} 847catch {unset ::key} 848 849# Make sure our reference count is still correct. 850# 851do_test btree-11.2 { 852 btree_close_cursor $::c1 853 lindex [btree_pager_stats $::b1] 1 854} {1} 855do_test btree-11.3 { 856 set ::c1 [btree_cursor $::b1 2 1] 857 lindex [btree_pager_stats $::b1] 1 858} {2} 859#btree_page_dump $::b1 2 860 861# Delete the dividers on the root page 862# 863do_test btree-11.4 { 864 btree_move_to $::c1 257 865 btree_delete $::c1 866 btree_next $::c1 867 btree_key $::c1 868} {258} 869do_test btree-11.4.1 { 870 btree_move_to $::c1 256 871 btree_key $::c1 872} {256} 873do_test btree-11.4.2 { 874 btree_move_to $::c1 258 875 btree_key $::c1 876} {258} 877do_test btree-11.4.3 { 878 btree_move_to $::c1 259 879 btree_key $::c1 880} {259} 881do_test btree-11.4.4 { 882 btree_move_to $::c1 257 883 set n [btree_key $::c1] 884 expr {$n==256||$n==258} 885} {1} 886do_test btree-11.5 { 887 btree_move_to $::c1 513 888 btree_delete $::c1 889 btree_next $::c1 890 btree_key $::c1 891} {514} 892do_test btree-11.5.1 { 893 btree_move_to $::c1 512 894 btree_key $::c1 895} {512} 896do_test btree-11.5.2 { 897 btree_move_to $::c1 514 898 btree_key $::c1 899} {514} 900do_test btree-11.5.3 { 901 btree_move_to $::c1 515 902 btree_key $::c1 903} {515} 904do_test btree-11.5.4 { 905 btree_move_to $::c1 513 906 set n [btree_key $::c1] 907 expr {$n==512||$n==514} 908} {1} 909do_test btree-11.6 { 910 btree_move_to $::c1 769 911 btree_delete $::c1 912 btree_next $::c1 913 btree_key $::c1 914} {770} 915do_test btree-11.6.1 { 916 btree_move_to $::c1 768 917 btree_key $::c1 918} {768} 919do_test btree-11.6.2 { 920 btree_move_to $::c1 771 921 btree_key $::c1 922} {771} 923do_test btree-11.6.3 { 924 btree_move_to $::c1 770 925 btree_key $::c1 926} {770} 927do_test btree-11.6.4 { 928 btree_move_to $::c1 769 929 set n [btree_key $::c1] 930 expr {$n==768||$n==770} 931} {1} 932#btree_page_dump $::b1 2 933#btree_page_dump $::b1 25 934 935# Change the data on an intermediate node such that the node becomes overfull 936# and has to split. We happen to know that intermediate nodes exist on 937# 337, 401 and 465 by the btree_page_dumps above 938# 939catch {unset ::data} 940set ::data {This is going to be a very long data segment} 941append ::data $::data 942append ::data $::data 943do_test btree-12.1 { 944 btree_insert $::c1 337 $::data 945 btree_data $::c1 946} $::data 947do_test btree-12.2 { 948 btree_insert $::c1 401 $::data 949 btree_data $::c1 950} $::data 951do_test btree-12.3 { 952 btree_insert $::c1 465 $::data 953 btree_data $::c1 954} $::data 955do_test btree-12.4 { 956 btree_move_to $::c1 337 957 btree_key $::c1 958} {337} 959do_test btree-12.5 { 960 btree_data $::c1 961} $::data 962do_test btree-12.6 { 963 btree_next $::c1 964 btree_key $::c1 965} {338} 966do_test btree-12.7 { 967 btree_move_to $::c1 464 968 btree_key $::c1 969} {464} 970do_test btree-12.8 { 971 btree_next $::c1 972 btree_data $::c1 973} $::data 974do_test btree-12.9 { 975 btree_next $::c1 976 btree_key $::c1 977} {466} 978do_test btree-12.10 { 979 btree_move_to $::c1 400 980 btree_key $::c1 981} {400} 982do_test btree-12.11 { 983 btree_next $::c1 984 btree_data $::c1 985} $::data 986do_test btree-12.12 { 987 btree_next $::c1 988 btree_key $::c1 989} {402} 990do_test btree-13.1 { 991 btree_integrity_check $::b1 2 3 992} {} 993 994# To Do: 995# 996# 1. Do some deletes from the 3-layer tree 997# 2. Commit and reopen the database 998# 3. Read every 15th entry and make sure it works 999# 4. Implement btree_sanity and put it throughout this script 1000# 1001 1002do_test btree-15.98 { 1003 btree_close_cursor $::c1 1004 lindex [btree_pager_stats $::b1] 1 1005} {1} 1006do_test btree-15.99 { 1007 btree_rollback $::b1 1008 lindex [btree_pager_stats $::b1] 1 1009} {0} 1010btree_pager_ref_dump $::b1 1011 1012do_test btree-99.1 { 1013 btree_close $::b1 1014} {} 1015catch {unset data} 1016catch {unset key} 1017 1018} ;# end if( not mem: and has pager_open command ); 1019 1020finish_test 1021