diff --git a/manifest b/manifest index 3dc04121ff..c39854955f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sbtree.c\smodule\snow\spasses\sall\sthe\shistorical\sregression\stests.\s\sNew\stests\nfor\snew\sfunctionality\sstill\sneed\sto\sbe\sadded.\s(CVS\s1342) -D 2004-05-10T16:18:48 +C The\sbtree.c\smodule\spasses\sall\stests\sand\sis\sready\sfor\sintegration.\nStill\sneed\sto\sgo\sback\sand\sdo\scoverage\stesting.\s(CVS\s1343) +D 2004-05-10T18:45:10 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -23,7 +23,7 @@ F sqlite.def fc4f5734786fe4743cfe2aa98eb2da4b089edb5f F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2 F src/attach.c fa9a58234406d84eeb900517d0c0adc4b2da051a F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79 -F src/btree.c 1b29a6915b2ac5d5c9919e1a461a09bc1e7b8a76 +F src/btree.c 3904c06f69df10a29b49bb3f5c651eb4813980ac F src/btree.h 7c3939a2e5f782c1ebac3bf43c02a16febad6df1 F src/btree_rb.c 9d7973e266ee6f9c61ce592f68742ce9cd5b10e5 F src/build.c 8d9965b3ce5dcc1bd4dac60bd0f14524fea269cb @@ -78,6 +78,7 @@ F test/bind.test 56a57043b42c4664ca705f6050e56717a8a6699a F test/btree.test ed5781db83b6c1de02e62781d44915a9abe3450a F test/btree2.test aa4a6d05b1ea90b1acaf83ba89039dd302a88635 F test/btree4.test 3797b4305694c7af6828675b0f4b1424b8ca30e4 +F test/btree5.test a677d181b3995dc07a6da12c2abdcd4c37ab7a3d F test/capi2.test ec96e0e235d87b53cbaef3d8e3e0f8ccf32c71ca F test/conflict.test 0911bb2f079046914a6e9c3341b36658c4e2103e F test/copy.test f07ea8d60878da7a67416ab62f78e9706b9d3c45 @@ -187,7 +188,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P 3af283f483f75795d5b03dc8fd886aaf326d50b7 -R 6546c34bdaf9d2a72d3829b11104409d +P 433ae0d327e5d5b0761e88418ed57fc4cbf4966b +R 2c4d2a423e133f1d66dbfff76eb51821 U drh -Z 3dbc1d278bc85c72de8f6c60be466152 +Z 4381466dc0ffb9f0d1943a642446ce5b diff --git a/manifest.uuid b/manifest.uuid index a907a7e232..8f5ddd7dbf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -433ae0d327e5d5b0761e88418ed57fc4cbf4966b \ No newline at end of file +84506b23365933383397e02a8ec5a980c57c80fc \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 0e65010165..9947e0e0d1 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.122 2004/05/10 16:18:48 drh Exp $ +** $Id: btree.c,v 1.123 2004/05/10 18:45:10 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -1762,6 +1762,7 @@ static int moveToRoot(BtCursor *pCur){ assert( pRoot->pgno==1 ); subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+6]); assert( subpage>0 ); + pCur->isValid = 1; rc = moveToChild(pCur, subpage); } pCur->isValid = pCur->pPage->nCell>0; @@ -3497,7 +3498,7 @@ int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){ printf("ERROR: next cell index out of range: %d\n", idx); } if( !pPage->leaf ){ - printf("right_child: %d\n", get4byte(&data[6])); + printf("right_child: %d\n", get4byte(&data[hdr+6])); } nFree = 0; i = 0; @@ -3524,6 +3525,7 @@ int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){ sqlite3BtreePageDump(pBt, get4byte(&data[hdr+6]), 1); } sqlite3pager_unref(data); + fflush(stdout); return SQLITE_OK; } #endif diff --git a/test/btree5.test b/test/btree5.test new file mode 100644 index 0000000000..9c3310990b --- /dev/null +++ b/test/btree5.test @@ -0,0 +1,275 @@ +# 2004 May 10 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. The +# focus of this script is btree database backend +# +# $Id: btree5.test,v 1.1 2004/05/10 18:45:10 drh Exp $ + + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# Attempting to read table 1 of an empty file gives an SQLITE_EMPTY +# error. +# +do_test btree5-1.1 { + file delete -force test1.bt + file delete -force test1.bt-journal + set rc [catch {btree_open test1.bt 2000 0} ::b1] +} {0} +do_test btree5-1.2 { + set rc [catch {btree_cursor $::b1 1 0} ::c1] +} {1} +do_test btree5-1.3 { + set ::c1 +} {SQLITE_EMPTY} +do_test btree5-1.4 { + set rc [catch {btree_cursor $::b1 1 1} ::c1] +} {1} +do_test btree5-1.5 { + set ::c1 +} {SQLITE_EMPTY} + +# Starting a transaction initializes the first page of the database +# and the error goes away. +# +do_test btree5-1.6 { + btree_begin_transaction $b1 + set rc [catch {btree_cursor $b1 1 0} c1] +} {0} +do_test btree5-1.7 { + btree_first $c1 +} {1} +do_test btree5-1.8 { + btree_close_cursor $c1 + btree_rollback $b1 + set rc [catch {btree_cursor $b1 1 0} c1] +} {1} +do_test btree5-1.9 { + set c1 +} {SQLITE_EMPTY} +do_test btree5-1.10 { + btree_begin_transaction $b1 + set rc [catch {btree_cursor $b1 1 0} c1] +} {0} +do_test btree5-1.11 { + btree_first $c1 +} {1} +do_test btree5-1.12 { + btree_close_cursor $c1 + btree_commit $b1 + set rc [catch {btree_cursor $b1 1 0} c1] +} {0} +do_test btree5-1.13 { + btree_first $c1 +} {1} +do_test btree5-1.14 { + btree_close_cursor $c1 + btree_integrity_check $b1 1 +} {} + +# Insert many entries into table 1. This is designed to test the +# virtual-root logic that comes into play for page one. It is also +# a good test of INTKEY tables. +# +# Stagger the inserts. After the inserts complete, go back and do +# deletes. Stagger the deletes too. Repeat this several times. +# + +# Do N inserts into table 1 using random keys between 0 and 1000000 +# +proc random_inserts {N} { + global c1 + while {$N>0} { + set k [expr {int(rand()*1000000)}] + if {[btree_move_to $c1 $k]==0} continue; # entry already exists + btree_insert $c1 $k data-for-$k + incr N -1 + } +} + +# Do N delete from table 1 +# +proc random_deletes {N} { + global c1 + while {$N>0} { + set k [expr {int(rand()*1000000)}] + btree_move_to $c1 $k + btree_delete $c1 + incr N -1 + } +} + +# Make sure the table has exactly N entries. Make sure the data for +# each entry agrees with its key. +# +proc check_table {N} { + global c1 + btree_first $c1 + set cnt 0 + while {![btree_eof $c1]} { + if {[btree_data $c1] ne "data-for-[btree_key $c1]"} { + return "wrong data for entry $cnt" + } + incr cnt + btree_next $c1 + } + if {$cnt!=$N} { + return "wrong number of entries" + } + return {} +} + +# Initialize the database +# +btree_begin_transaction $b1 +set c1 [btree_cursor $b1 1 1] +set btree_trace 0 + +# Do the tests. +# +set cnt 0 +for {set i 1} {$i<=100} {incr i} { + do_test test5-2.$i.1 { + random_inserts 200 + incr cnt 200 + check_table $cnt + } {} + do_test test5-2.$i.2 { + btree_integrity_check $b1 1 + } {} + do_test test5-2.$i.3 { + random_deletes 190 + incr cnt -190 + check_table $cnt + } {} + do_test test5-2.$i.4 { + btree_integrity_check $b1 1 + } {} +} + +btree_close_cursor $c1 +btree_commit $b1 +btree_begin_transaction $b1 + +# This procedure converts an integer into a variable-length text key. +# The conversion is reversible. +# +# The first two characters of the string are alphabetics derived from +# the least significant bits of the number. Because they are derived +# from least significant bits, the sort order of the resulting string +# is different from numeric order. After the alphabetic prefix comes +# the original number. A variable-length suffix follows. The length +# of the suffix is based on a hash of the original number. +# +proc num_to_key {n} { + global charset ncharset suffix + set c1 [string index $charset [expr {$n%$ncharset}]] + set c2 [string index $charset [expr {($n/$ncharset)%$ncharset}]] + set nsuf [expr {($n*211)%593}] + return $c1$c2-$n-[string range $suffix 0 $nsuf] +} +set charset {abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ} +set ncharset [string length $charset] +set suffix $charset$charset +while {[string length $suffix]<1000} {append suffix $suffix} + +# This procedures extracts the original integer used to create +# a key by num_to_key +# +proc key_to_num {key} { + regexp {^..-([0-9]+)} $key all n + return $n +} + +# Insert into table $tab keys corresponding to all values between +# $start and $end, inclusive. +# +proc insert_range {tab start end} { + for {set i $start} {$i<=$end} {incr i} { + btree_insert $tab [num_to_key $i] {} + } +} + +# Delete from table $tab keys corresponding to all values between +# $start and $end, inclusive. +# +proc delete_range {tab start end} { + for {set i $start} {$i<=$end} {incr i} { + if {[btree_move_to $tab [num_to_key $i]]==0} { + btree_delete $tab + } + } +} + +# Make sure table $tab contains exactly those keys corresponding +# to values between $start and $end +# +proc check_range {tab start end} { + btree_first $tab + while {![btree_eof $tab]} { + set key [btree_key $tab] + set i [key_to_num $key] + if {[num_to_key $i] ne $key} { + return "malformed key: $key" + } + set got($i) 1 + btree_next $tab + } + set all [lsort -integer [array names got]] + if {[llength $all]!=$end+1-$start} { + return "table contains wrong number of values" + } + if {[lindex $all 0]!=$start} { + return "wrong starting value" + } + if {[lindex $all end]!=$end} { + return "wrong ending value" + } + return {} +} + +# Create a zero-data table and test it out. +# +do_test btree5-3.1 { + set rc [catch {btree_create_table $b1 2} t2] +} {0} +do_test btree5-3.2 { + set rc [catch {btree_cursor $b1 $t2 1} c2] +} {0} +set start 1 +set end 100 +for {set i 1} {$i<=100} {incr i} { + do_test btree5-3.3.$i.1 { + insert_range $c2 $start $end + btree_integrity_check $b1 1 $t2 + } {} + do_test btree5-3.3.$i.2 { + check_range $c2 $start $end + } {} + set nstart $start + incr nstart 89 + do_test btree5-3.3.$i.3 { + delete_range $c2 $start $nstart + btree_integrity_check $b1 1 $t2 + } {} + incr start 90 + do_test btree5-3.3.$i.4 { + check_range $c2 $start $end + } {} + incr end 100 +} + +btree_close_cursor $c2 +btree_commit $b1 + + +finish_test