sqlite/test/btree.test
drh f5bf0a78be Fix a bug in DROP TABLE that could cause SQLITE_MASTER table corruption.
The root problem was that the sequence of BTree operations (Delete, Next)
would not always leave the cursor pointing at the first entry after the
entry that was deleted.  A consequence of this error was that a DROP TABLE
on a table with indices would not always remove every index associated
with that table from the SQLITE_MASTER table.  Subsequent attempts to
open the database will fail when the index for the missing table was
parsed.  Changes have also been made to ignore extra indices in the
SQLITE_MASTER table so that a database previously corrupted by this bug
is once again readable. (CVS 316)

FossilOrigin-Name: 8a984667113564f2bac7412165b6ff8b7e3e8f70
2001-11-23 00:24:12 +00:00

1019 lines
22 KiB
Plaintext

# 2001 September 15
#
# 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: btree.test,v 1.11 2001/11/23 00:24:12 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
if {[info commands btree_open]!=""} {
# Basic functionality. Open and close a database.
#
do_test btree-1.1 {
file delete -force test1.bt
file delete -force test1.bt-journal
set rc [catch {btree_open test1.bt} ::b1]
} {0}
# The second element of the list returned by btree_pager_stats is the
# number of pages currently checked out. We'll be checking this value
# frequently during this test script, to make sure the btree library
# is properly releasing the pages it checks out, and thus avoiding
# page leaks.
#
do_test btree-1.1.1 {
lindex [btree_pager_stats $::b1] 1
} {0}
do_test btree-1.2 {
set rc [catch {btree_open test1.bt} ::b2]
} {0}
do_test btree-1.3 {
set rc [catch {btree_close $::b2} msg]
lappend rc $msg
} {0 {}}
# Do an insert and verify that the database file grows in size.
#
do_test btree-1.4 {
set rc [catch {btree_begin_transaction $::b1} msg]
lappend rc $msg
} {0 {}}
do_test btree-1.4.1 {
lindex [btree_pager_stats $::b1] 1
} {1}
do_test btree-1.5 {
set rc [catch {btree_cursor $::b1 2 1} ::c1]
if {$rc} {lappend rc $::c1}
set rc
} {0}
do_test btree-1.6 {
set rc [catch {btree_insert $::c1 one 1.00} msg]
lappend rc $msg
} {0 {}}
do_test btree-1.7 {
btree_key $::c1
} {one}
do_test btree-1.8 {
btree_data $::c1
} {1.00}
do_test btree-1.9 {
set rc [catch {btree_close_cursor $::c1} msg]
lappend rc $msg
} {0 {}}
do_test btree-1.10 {
set rc [catch {btree_commit $::b1} msg]
lappend rc $msg
} {0 {}}
do_test btree-1.11 {
file size test1.bt
} {2048}
do_test btree-1.12 {
lindex [btree_pager_stats $::b1] 1
} {0}
# Reopen the database and attempt to read the record that we wrote.
#
do_test btree-2.1 {
set rc [catch {btree_cursor $::b1 2 1} ::c1]
if {$rc} {lappend rc $::c1}
set rc
} {0}
do_test btree-2.2 {
btree_move_to $::c1 abc
} {1}
do_test btree-2.3 {
btree_move_to $::c1 xyz
} {-1}
do_test btree-2.4 {
btree_move_to $::c1 one
} {0}
do_test btree-2.5 {
btree_key $::c1
} {one}
do_test btree-2.6 {
btree_data $::c1
} {1.00}
do_test btree-2.7 {
lindex [btree_pager_stats $::b1] 1
} {2}
# Do some additional inserts
#
do_test btree-3.1 {
btree_begin_transaction $::b1
btree_insert $::c1 two 2.00
btree_key $::c1
} {two}
do_test btree-3.1.1 {
lindex [btree_pager_stats $::b1] 1
} {2}
do_test btree-3.2 {
btree_insert $::c1 three 3.00
btree_key $::c1
} {three}
do_test btree-3.4 {
btree_insert $::c1 four 4.00
btree_key $::c1
} {four}
do_test btree-3.5 {
btree_insert $::c1 five 5.00
btree_key $::c1
} {five}
do_test btree-3.6 {
btree_insert $::c1 six 6.00
btree_key $::c1
} {six}
#btree_page_dump $::b1 2
do_test btree-3.7 {
set rc [btree_move_to $::c1 {}]
expr {$rc>0}
} {1}
do_test btree-3.8 {
btree_key $::c1
} {five}
do_test btree-3.9 {
btree_data $::c1
} {5.00}
do_test btree-3.10 {
btree_next $::c1
btree_key $::c1
} {four}
do_test btree-3.11 {
btree_data $::c1
} {4.00}
do_test btree-3.12 {
btree_next $::c1
btree_key $::c1
} {one}
do_test btree-3.13 {
btree_data $::c1
} {1.00}
do_test btree-3.14 {
btree_next $::c1
btree_key $::c1
} {six}
do_test btree-3.15 {
btree_data $::c1
} {6.00}
do_test btree-3.16 {
btree_next $::c1
btree_key $::c1
} {three}
do_test btree-3.17 {
btree_data $::c1
} {3.00}
do_test btree-3.18 {
btree_next $::c1
btree_key $::c1
} {two}
do_test btree-3.19 {
btree_data $::c1
} {2.00}
do_test btree-3.20 {
btree_next $::c1
btree_key $::c1
} {}
do_test btree-3.21 {
btree_data $::c1
} {}
# Commit the changes, reopen and reread the data
#
do_test btree-3.22 {
set rc [catch {btree_close_cursor $::c1} msg]
lappend rc $msg
} {0 {}}
do_test btree-3.22.1 {
lindex [btree_pager_stats $::b1] 1
} {1}
do_test btree-3.23 {
set rc [catch {btree_commit $::b1} msg]
lappend rc $msg
} {0 {}}
do_test btree-3.23.1 {
lindex [btree_pager_stats $::b1] 1
} {0}
do_test btree-3.24 {
file size test1.bt
} {2048}
do_test btree-3.25 {
set rc [catch {btree_cursor $::b1 2 1} ::c1]
if {$rc} {lappend rc $::c1}
set rc
} {0}
do_test btree-3.25.1 {
lindex [btree_pager_stats $::b1] 1
} {2}
do_test btree-3.26 {
set rc [btree_move_to $::c1 {}]
expr {$rc>0}
} {1}
do_test btree-3.27 {
btree_key $::c1
} {five}
do_test btree-3.28 {
btree_data $::c1
} {5.00}
do_test btree-3.29 {
btree_next $::c1
btree_key $::c1
} {four}
do_test btree-3.30 {
btree_data $::c1
} {4.00}
do_test btree-3.31 {
btree_next $::c1
btree_key $::c1
} {one}
do_test btree-3.32 {
btree_data $::c1
} {1.00}
do_test btree-3.33 {
btree_next $::c1
btree_key $::c1
} {six}
do_test btree-3.34 {
btree_data $::c1
} {6.00}
do_test btree-3.35 {
btree_next $::c1
btree_key $::c1
} {three}
do_test btree-3.36 {
btree_data $::c1
} {3.00}
do_test btree-3.37 {
btree_next $::c1
btree_key $::c1
} {two}
do_test btree-3.38 {
btree_data $::c1
} {2.00}
do_test btree-3.39 {
btree_next $::c1
btree_key $::c1
} {}
do_test btree-3.40 {
btree_data $::c1
} {}
do_test btree-3.41 {
lindex [btree_pager_stats $::b1] 1
} {2}
# Now try a delete
#
do_test btree-4.1 {
btree_begin_transaction $::b1
btree_move_to $::c1 one
btree_key $::c1
} {one}
do_test btree-4.1.1 {
lindex [btree_pager_stats $::b1] 1
} {2}
do_test btree-4.2 {
btree_delete $::c1
} {}
do_test btree-4.3 {
btree_key $::c1
} {six}
do_test btree-4.4 {
btree_next $::c1
btree_key $::c1
} {six}
do_test btree-4.5 {
btree_next $::c1
btree_key $::c1
} {three}
do_test btree-4.4 {
btree_move_to $::c1 {}
set r {}
while 1 {
set key [btree_key $::c1]
if {$key==""} break
lappend r $key
lappend r [btree_data $::c1]
btree_next $::c1
}
set r
} {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00}
# Commit and make sure the delete is still there.
#
do_test btree-4.5 {
btree_commit $::b1
btree_move_to $::c1 {}
set r {}
while 1 {
set key [btree_key $::c1]
if {$key==""} break
lappend r $key
lappend r [btree_data $::c1]
btree_next $::c1
}
set r
} {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00}
# Completely close the database and reopen it. Then check
# the data again.
#
do_test btree-4.6 {
lindex [btree_pager_stats $::b1] 1
} {2}
do_test btree-4.7 {
btree_close_cursor $::c1
lindex [btree_pager_stats $::b1] 1
} {0}
do_test btree-4.8 {
btree_close $::b1
set ::b1 [btree_open test1.bt]
set ::c1 [btree_cursor $::b1 2 1]
lindex [btree_pager_stats $::b1] 1
} {2}
do_test btree-4.9 {
set r {}
while 1 {
set key [btree_key $::c1]
if {$key==""} break
lappend r $key
lappend r [btree_data $::c1]
btree_next $::c1
}
set r
} {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00}
# Try to read and write meta data
#
do_test btree-5.1 {
btree_get_meta $::b1
} {0 0 0 0}
do_test btree-5.2 {
set rc [catch {btree_update_meta $::b1 1 2 3 4} msg]
lappend rc $msg
} {1 SQLITE_ERROR}
do_test btree-5.3 {
btree_begin_transaction $::b1
set rc [catch {btree_update_meta $::b1 1 2 3 4} msg]
lappend rc $msg
} {0 {}}
do_test btree-5.4 {
btree_get_meta $::b1
} {0 2 3 4}
do_test btree-5.5 {
btree_close_cursor $::c1
btree_rollback $::b1
btree_get_meta $::b1
} {0 0 0 0}
do_test btree-5.6 {
btree_begin_transaction $::b1
btree_update_meta $::b1 999 10 20 30
btree_commit $::b1
btree_get_meta $::b1
} {0 10 20 30}
proc select_all {cursor} {
set r {}
btree_move_to $cursor {}
while 1 {
set key [btree_key $cursor]
if {$key==""} break
lappend r $key
lappend r [btree_data $cursor]
btree_next $cursor
}
return $r
}
proc select_keys {cursor} {
set r {}
btree_move_to $cursor {}
while 1 {
set key [btree_key $cursor]
if {$key==""} break
lappend r $key
btree_next $cursor
}
return $r
}
# Try to create a new table in the database file
#
do_test btree-6.1 {
set rc [catch {btree_create_table $::b1} msg]
lappend rc $msg
} {1 SQLITE_ERROR}
do_test btree-6.2 {
btree_begin_transaction $::b1
set ::t2 [btree_create_table $::b1]
} {3}
do_test btree-6.2.1 {
lindex [btree_pager_stats $::b1] 1
} {1}
do_test btree-6.2.2 {
set ::c2 [btree_cursor $::b1 $::t2 1]
lindex [btree_pager_stats $::b1] 1
} {2}
do_test btree-6.2.3 {
btree_insert $::c2 ten 10
btree_key $::c2
} {ten}
do_test btree-6.3 {
btree_commit $::b1
set ::c1 [btree_cursor $::b1 2 1]
lindex [btree_pager_stats $::b1] 1
} {3}
do_test btree-6.3.1 {
select_all $::c1
} {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00}
#btree_page_dump $::b1 3
do_test btree-6.4 {
select_all $::c2
} {ten 10}
# Drop the new table, then create it again anew.
#
do_test btree-6.5 {
btree_begin_transaction $::b1
} {}
do_test btree-6.6 {
btree_close_cursor $::c2
} {}
do_test btree-6.6.1 {
lindex [btree_pager_stats $::b1] 1
} {2}
do_test btree-6.7 {
btree_drop_table $::b1 $::t2
} {}
do_test btree-6.7.1 {
lindex [btree_get_meta $::b1] 0
} {1}
do_test btree-6.8 {
set ::t2 [btree_create_table $::b1]
} {3}
do_test btree-6.8.1 {
lindex [btree_get_meta $::b1] 0
} {0}
do_test btree-6.9 {
set ::c2 [btree_cursor $::b1 $::t2 1]
lindex [btree_pager_stats $::b1] 1
} {3}
do_test btree-6.9.1 {
btree_move_to $::c2 {}
btree_key $::c2
} {}
# If we drop table 2 it just clears the table. Table 2 always exists.
#
do_test btree-6.10 {
btree_close_cursor $::c1
btree_drop_table $::b1 2
set ::c1 [btree_cursor $::b1 2 1]
btree_move_to $::c1 {}
btree_key $::c1
} {}
do_test btree-6.11 {
btree_commit $::b1
select_all $::c1
} {}
do_test btree-6.12 {
select_all $::c2
} {}
do_test btree-6.13 {
btree_close_cursor $::c2
lindex [btree_pager_stats $::b1] 1
} {2}
# Check to see that pages defragment properly. To do this test we will
#
# 1. Fill the first page table 2 with data.
# 2. Delete every other entry of table 2.
# 3. Insert a single entry that requires more contiguous
# space than is available.
#
do_test btree-7.1 {
btree_begin_transaction $::b1
} {}
catch {unset key}
catch {unset data}
do_test btree-7.2 {
for {set i 0} {$i<36} {incr i} {
set key [format %03d $i]
set data "*** $key ***"
btree_insert $::c1 $key $data
}
lrange [btree_cursor_dump $::c1] 4 5
} {8 1}
do_test btree-7.3 {
btree_move_to $::c1 000
while {[btree_key $::c1]!=""} {
btree_delete $::c1
btree_next $::c1
btree_next $::c1
}
lrange [btree_cursor_dump $::c1] 4 5
} {512 19}
#btree_page_dump $::b1 2
do_test btree-7.4 {
btree_insert $::c1 018 {*** 018 ***+++}
btree_key $::c1
} {018}
do_test btree-7.5 {
lrange [btree_cursor_dump $::c1] 4 5
} {480 1}
#btree_page_dump $::b1 2
# Delete an entry to make a hole of a known size, then immediately recreate
# that entry. This tests the path into allocateSpace where the hole exactly
# matches the size of the desired space.
#
do_test btree-7.6 {
btree_move_to $::c1 007
btree_delete $::c1
btree_move_to $::c1 011
btree_delete $::c1
} {}
do_test btree-7.7 {
lindex [btree_cursor_dump $::c1] 5
} {3}
#btree_page_dump $::b1 2
do_test btree-7.8 {
btree_insert $::c1 007 {*** 007 ***}
lindex [btree_cursor_dump $::c1] 5
} {2}
#btree_page_dump $::b1 2
# Make sure the freeSpace() routine properly coaleses adjacent memory blocks
#
do_test btree-7.9 {
btree_move_to $::c1 013
btree_delete $::c1
lrange [btree_cursor_dump $::c1] 4 5
} {536 2}
do_test btree-7.10 {
btree_move_to $::c1 009
btree_delete $::c1
lrange [btree_cursor_dump $::c1] 4 5
} {564 2}
do_test btree-7.11 {
btree_move_to $::c1 018
btree_delete $::c1
lrange [btree_cursor_dump $::c1] 4 5
} {596 2}
do_test btree-7.13 {
btree_move_to $::c1 033
btree_delete $::c1
lrange [btree_cursor_dump $::c1] 4 5
} {624 3}
do_test btree-7.14 {
btree_move_to $::c1 035
btree_delete $::c1
lrange [btree_cursor_dump $::c1] 4 5
} {652 2}
#btree_page_dump $::b1 2
do_test btree-7.15 {
lindex [btree_pager_stats $::b1] 1
} {2}
# Check to see that data on overflow pages work correctly.
#
do_test btree-8.1 {
set data "*** This is a very long key "
while {[string length $data]<256} {append data $data}
set ::data $data
btree_insert $::c1 020 $data
} {}
#btree_page_dump $::b1 2
do_test btree-8.1.1 {
lindex [btree_pager_stats $::b1] 1
} {2}
#btree_pager_ref_dump $::b1
do_test btree-8.2 {
string length [btree_data $::c1]
} [string length $::data]
do_test btree-8.3 {
btree_data $::c1
} $::data
do_test btree-8.4 {
btree_delete $::c1
} {}
do_test btree-8.4.1 {
lindex [btree_get_meta $::b1] 0
} [expr {int(([string length $::data]-238+1019)/1020)}]
do_test btree-8.5 {
set data "*** This is an even longer key"
while {[string length $data]<2000} {append data $data}
set ::data $data
btree_insert $::c1 020 $data
} {}
do_test btree-8.6 {
string length [btree_data $::c1]
} [string length $::data]
do_test btree-8.7 {
btree_data $::c1
} $::data
do_test btree-8.8 {
btree_commit $::b1
btree_data $::c1
} $::data
do_test btree-8.9 {
btree_close_cursor $::c1
btree_close $::b1
set ::b1 [btree_open test1.bt]
set ::c1 [btree_cursor $::b1 2 1]
btree_move_to $::c1 020
btree_data $::c1
} $::data
do_test btree-8.10 {
btree_begin_transaction $::b1
btree_delete $::c1
} {}
do_test btree-8.11 {
lindex [btree_get_meta $::b1] 0
} [expr {int(([string length $::data]-238+1019)/1020)}]
# Now check out keys on overflow pages.
#
do_test btree-8.12 {
set ::keyprefix "This is a long prefix to a key "
while {[string length $::keyprefix]<256} {append ::keyprefix $::keyprefix}
btree_close_cursor $::c1
btree_drop_table $::b1 2
lindex [btree_get_meta $::b1] 0
} {4}
do_test btree-8.12.1 {
set ::c1 [btree_cursor $::b1 2 1]
btree_insert $::c1 ${::keyprefix}1 1
btree_data $::c1
} {1}
do_test btree-8.13 {
btree_key $::c1
} ${keyprefix}1
do_test btree-8.14 {
btree_insert $::c1 ${::keyprefix}2 2
btree_insert $::c1 ${::keyprefix}3 3
btree_key $::c1
} ${keyprefix}3
do_test btree-8.15 {
btree_move_to $::c1 ${::keyprefix}2
btree_data $::c1
} {2}
do_test btree-8.16 {
btree_move_to $::c1 ${::keyprefix}1
btree_data $::c1
} {1}
do_test btree-8.17 {
btree_move_to $::c1 ${::keyprefix}3
btree_data $::c1
} {3}
do_test btree-8.18 {
lindex [btree_get_meta $::b1] 0
} {1}
do_test btree-8.19 {
btree_move_to $::c1 ${::keyprefix}2
btree_key $::c1
} ${::keyprefix}2
#btree_page_dump $::b1 2
do_test btree-8.20 {
btree_delete $::c1
btree_next $::c1
btree_key $::c1
} ${::keyprefix}3
#btree_page_dump $::b1 2
do_test btree-8.21 {
lindex [btree_get_meta $::b1] 0
} {2}
do_test btree-8.22 {
lindex [btree_pager_stats $::b1] 1
} {2}
do_test btree-8.23 {
btree_close_cursor $::c1
btree_drop_table $::b1 2
set ::c1 [btree_cursor $::b1 2 1]
lindex [btree_get_meta $::b1] 0
} {4}
do_test btree-8.24 {
lindex [btree_pager_stats $::b1] 1
} {2}
#btree_pager_ref_dump $::b1
# Check page splitting logic
#
do_test btree-9.1 {
for {set i 1} {$i<=19} {incr i} {
set key [format %03d $i]
set data "*** $key *** $key *** $key *** $key ***"
btree_insert $::c1 $key $data
}
} {}
#btree_tree_dump $::b1 2
#btree_pager_ref_dump $::b1
#set pager_refinfo_enable 1
do_test btree-9.2 {
btree_insert $::c1 020 {*** 020 *** 020 *** 020 *** 020 ***}
select_keys $::c1
} {001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020}
#btree_page_dump $::b1 5
#btree_page_dump $::b1 2
#btree_page_dump $::b1 7
#btree_pager_ref_dump $::b1
#set pager_refinfo_enable 0
# The previous "select_keys" command left the cursor pointing at the root
# page. So there should only be two pages checked out. 2 (the root) and
# page 1.
do_test btree-9.2.1 {
lindex [btree_pager_stats $::b1] 1
} {2}
for {set i 1} {$i<=20} {incr i} {
do_test btree-9.3.$i.1 [subst {
btree_move_to $::c1 [format %03d $i]
btree_key $::c1
}] [format %03d $i]
do_test btree-9.3.$i.2 [subst {
btree_move_to $::c1 [format %03d $i]
string range \[btree_data $::c1\] 0 10
}] "*** [format %03d $i] ***"
}
do_test btree-9.4.1 {
lindex [btree_pager_stats $::b1] 1
} {3}
# Check the page joining logic.
#
#btree_page_dump $::b1 2
#btree_pager_ref_dump $::b1
do_test btree-9.4.2 {
btree_move_to $::c1 005
btree_delete $::c1
} {}
#btree_page_dump $::b1 2
for {set i 1} {$i<=19} {incr i} {
if {$i==5} continue
do_test btree-9.5.$i.1 [subst {
btree_move_to $::c1 [format %03d $i]
btree_key $::c1
}] [format %03d $i]
do_test btree-9.5.$i.2 [subst {
btree_move_to $::c1 [format %03d $i]
string range \[btree_data $::c1\] 0 10
}] "*** [format %03d $i] ***"
}
#btree_pager_ref_dump $::b1
do_test btree-9.6 {
btree_close_cursor $::c1
lindex [btree_pager_stats $::b1] 1
} {1}
do_test btree-9.7 {
btree_rollback $::b1
lindex [btree_pager_stats $::b1] 1
} {0}
# Create a tree of depth two. That is, there is a single divider entry
# on the root pages and two leaf pages. Then delete the divider entry
# see what happens.
#
do_test btree-10.1 {
btree_begin_transaction $::b1
btree_drop_table $::b1 2
lindex [btree_pager_stats $::b1] 1
} {1}
do_test btree-10.2 {
set ::c1 [btree_cursor $::b1 2 1]
lindex [btree_pager_stats $::b1] 1
} {2}
do_test btree-10.3 {
for {set i 1} {$i<=20} {incr i} {
set key [format %03d $i]
set data "*** $key *** $key *** $key *** $key ***"
btree_insert $::c1 $key $data
}
select_keys $::c1
} {001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020}
#btree_page_dump $::b1 7
#btree_page_dump $::b1 2
#btree_page_dump $::b1 6
do_test btree-10.4 {
btree_move_to $::c1 011
btree_delete $::c1
select_keys $::c1
} {001 002 003 004 005 006 007 008 009 010 012 013 014 015 016 017 018 019 020}
#btree_tree_dump $::b1 2
#btree_pager_ref_dump $::b1
for {set i 1} {$i<=20} {incr i} {
do_test btree-10.5.$i {
btree_move_to $::c1 [format %03d $i]
lindex [btree_pager_stats $::b1] 1
} {2}
#btree_pager_ref_dump $::b1
#btree_tree_dump $::b1 2
}
# Create a tree with lots more pages
#
catch {unset ::data}
catch {unset ::key}
for {set i 21} {$i<=1000} {incr i} {
do_test btree-11.1.$i.1 {
set key [format %03d $i]
set ::data "*** $key *** $key *** $key *** $key ***"
btree_insert $::c1 $key $data
btree_key $::c1
} [format %03d $i]
do_test btree-11.1.$i.2 {
btree_data $::c1
} $::data
set ::key [format %03d [expr {$i/2}]]
if {$::key=="011"} {set ::key 010}
do_test btree-11.1.$i.3 {
btree_move_to $::c1 $::key
btree_key $::c1
} $::key
}
catch {unset ::data}
catch {unset ::key}
# Make sure our reference count is still correct.
#
do_test btree-11.2 {
btree_close_cursor $::c1
lindex [btree_pager_stats $::b1] 1
} {1}
do_test btree-11.3 {
set ::c1 [btree_cursor $::b1 2 1]
lindex [btree_pager_stats $::b1] 1
} {2}
#btree_page_dump $::b1 2
# Delete the dividers on the root page
#
do_test btree-11.4 {
btree_move_to $::c1 257
btree_delete $::c1
btree_next $::c1
btree_key $::c1
} {258}
do_test btree-11.4.1 {
btree_move_to $::c1 256
btree_key $::c1
} {256}
do_test btree-11.4.2 {
btree_move_to $::c1 258
btree_key $::c1
} {258}
do_test btree-11.4.3 {
btree_move_to $::c1 259
btree_key $::c1
} {259}
do_test btree-11.4.4 {
btree_move_to $::c1 257
set n [btree_key $::c1]
expr {$n==256||$n==258}
} {1}
do_test btree-11.5 {
btree_move_to $::c1 513
btree_delete $::c1
btree_next $::c1
btree_key $::c1
} {514}
do_test btree-11.5.1 {
btree_move_to $::c1 512
btree_key $::c1
} {512}
do_test btree-11.5.2 {
btree_move_to $::c1 514
btree_key $::c1
} {514}
do_test btree-11.5.3 {
btree_move_to $::c1 515
btree_key $::c1
} {515}
do_test btree-11.5.4 {
btree_move_to $::c1 513
set n [btree_key $::c1]
expr {$n==512||$n==514}
} {1}
do_test btree-11.6 {
btree_move_to $::c1 769
btree_delete $::c1
btree_next $::c1
btree_key $::c1
} {770}
do_test btree-11.6.1 {
btree_move_to $::c1 768
btree_key $::c1
} {768}
do_test btree-11.6.2 {
btree_move_to $::c1 771
btree_key $::c1
} {771}
do_test btree-11.6.3 {
btree_move_to $::c1 770
btree_key $::c1
} {770}
do_test btree-11.6.4 {
btree_move_to $::c1 769
set n [btree_key $::c1]
expr {$n==768||$n==770}
} {1}
#btree_page_dump $::b1 2
#btree_page_dump $::b1 25
# Change the data on an intermediate node such that the node becomes overfull
# and has to split. We happen to know that intermediate nodes exist on
# 337, 401 and 465 by the btree_page_dumps above
#
catch {unset ::data}
set ::data {This is going to be a very long data segment}
append ::data $::data
append ::data $::data
do_test btree-12.1 {
btree_insert $::c1 337 $::data
btree_data $::c1
} $::data
do_test btree-12.2 {
btree_insert $::c1 401 $::data
btree_data $::c1
} $::data
do_test btree-12.3 {
btree_insert $::c1 465 $::data
btree_data $::c1
} $::data
do_test btree-12.4 {
btree_move_to $::c1 337
btree_key $::c1
} {337}
do_test btree-12.5 {
btree_data $::c1
} $::data
do_test btree-12.6 {
btree_next $::c1
btree_key $::c1
} {338}
do_test btree-12.7 {
btree_move_to $::c1 464
btree_key $::c1
} {464}
do_test btree-12.8 {
btree_next $::c1
btree_data $::c1
} $::data
do_test btree-12.9 {
btree_next $::c1
btree_key $::c1
} {466}
do_test btree-12.10 {
btree_move_to $::c1 400
btree_key $::c1
} {400}
do_test btree-12.11 {
btree_next $::c1
btree_data $::c1
} $::data
do_test btree-12.12 {
btree_next $::c1
btree_key $::c1
} {402}
do_test btree-13.1 {
btree_sanity_check $::b1 2 3
} {}
# To Do:
#
# 1. Do some deletes from the 3-layer tree
# 2. Commit and reopen the database
# 3. Read every 15th entry and make sure it works
# 4. Implement btree_sanity and put it throughout this script
#
do_test btree-15.98 {
btree_close_cursor $::c1
lindex [btree_pager_stats $::b1] 1
} {1}
do_test btree-15.99 {
btree_rollback $::b1
lindex [btree_pager_stats $::b1] 1
} {0}
btree_pager_ref_dump $::b1
do_test btree-99.1 {
btree_close $::b1
} {}
catch {unset data}
catch {unset key}
} ;# end if( not mem: and has pager_open command );
finish_test