From e36d23a85ebff914d74bb541558c2b6082b78edb Mon Sep 17 00:00:00 2001 From: dan miller Date: Sat, 20 Oct 2007 02:49:29 +0000 Subject: sqlite source (unix build) added to libraries --- libraries/sqlite/unix/sqlite-3.5.1/test/btree.test | 1072 ++++++++++++++++++++ 1 file changed, 1072 insertions(+) create mode 100644 libraries/sqlite/unix/sqlite-3.5.1/test/btree.test (limited to 'libraries/sqlite/unix/sqlite-3.5.1/test/btree.test') diff --git a/libraries/sqlite/unix/sqlite-3.5.1/test/btree.test b/libraries/sqlite/unix/sqlite-3.5.1/test/btree.test new file mode 100644 index 0000000..d8575d06 --- /dev/null +++ b/libraries/sqlite/unix/sqlite-3.5.1/test/btree.test @@ -0,0 +1,1072 @@ +# 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.41 2007/09/06 22:19:15 drh Exp $ + + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +ifcapable default_autovacuum { + finish_test + return +} + +# 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 2000 0} ::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 2000 0} ::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 1 1} ::c1] + if {$rc} {lappend rc $::c1} + set rc +} {0} +do_test btree-1.6 { + set rc [catch {btree_insert $::c1 100 1.00} msg] + lappend rc $msg +} {0 {}} +do_test btree-1.7 { + btree_move_to $::c1 100 + btree_key $::c1 +} {100} +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 +} {1024} +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 1 1} ::c1] + if {$rc} {lappend rc $::c1} + set rc +} {0} +do_test btree-2.1.1 { + btree_cursor_list $::b1 +} {} +do_test btree-2.2 { + btree_move_to $::c1 99 +} {1} +do_test btree-2.3 { + btree_move_to $::c1 101 +} {-1} +do_test btree-2.4 { + btree_move_to $::c1 100 +} {0} +do_test btree-2.5 { + btree_key $::c1 +} {100} +do_test btree-2.6 { + btree_data $::c1 +} {1.00} +do_test btree-2.7 { + lindex [btree_pager_stats $::b1] 1 +} {1} + +# Do some additional inserts +# +do_test btree-3.1 { + btree_begin_transaction $::b1 + btree_insert $::c1 200 2.00 + btree_move_to $::c1 200 + btree_key $::c1 +} {200} +do_test btree-3.1.1 { + lindex [btree_pager_stats $::b1] 1 +} {1} +do_test btree-3.2 { + btree_insert $::c1 300 3.00 + btree_move_to $::c1 300 + btree_key $::c1 +} {300} +do_test btree-3.4 { + btree_insert $::c1 400 4.00 + btree_move_to $::c1 400 + btree_key $::c1 +} {400} +do_test btree-3.5 { + btree_insert $::c1 500 5.00 + btree_move_to $::c1 500 + btree_key $::c1 +} {500} +do_test btree-3.6 { + btree_insert $::c1 600 6.00 + btree_move_to $::c1 600 + btree_key $::c1 +} {600} +#btree_page_dump $::b1 2 +do_test btree-3.7 { + set rc [btree_move_to $::c1 0] + expr {$rc>0} +} {1} +do_test btree-3.8 { + btree_key $::c1 +} {100} +do_test btree-3.9 { + btree_data $::c1 +} {1.00} +do_test btree-3.10 { + btree_next $::c1 + btree_key $::c1 +} {200} +do_test btree-3.11 { + btree_data $::c1 +} {2.00} +do_test btree-3.12 { + btree_next $::c1 + btree_key $::c1 +} {300} +do_test btree-3.13 { + btree_data $::c1 +} {3.00} +do_test btree-3.14 { + btree_next $::c1 + btree_key $::c1 +} {400} +do_test btree-3.15 { + btree_data $::c1 +} {4.00} +do_test btree-3.16 { + btree_next $::c1 + btree_key $::c1 +} {500} +do_test btree-3.17 { + btree_data $::c1 +} {5.00} +do_test btree-3.18 { + btree_next $::c1 + btree_key $::c1 +} {600} +do_test btree-3.19 { + btree_data $::c1 +} {6.00} +do_test btree-3.20.1 { + btree_next $::c1 + btree_key $::c1 +} {0} +do_test btree-3.20.2 { + btree_eof $::c1 +} {1} +# This test case used to test that one couldn't request data from an +# invalid cursor. That is now an assert()ed condition. +# +# do_test btree-3.21 { +# set rc [catch {btree_data $::c1} res] +# lappend rc $res +# } {1 SQLITE_INTERNAL} + +# 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 +} {1024} +do_test btree-3.25 { + set rc [catch {btree_cursor $::b1 1 1} ::c1] + if {$rc} {lappend rc $::c1} + set rc +} {0} +do_test btree-3.25.1 { + lindex [btree_pager_stats $::b1] 1 +} {1} +do_test btree-3.26 { + set rc [btree_move_to $::c1 0] + expr {$rc>0} +} {1} +do_test btree-3.27 { + btree_key $::c1 +} {100} +do_test btree-3.28 { + btree_data $::c1 +} {1.00} +do_test btree-3.29 { + btree_next $::c1 + btree_key $::c1 +} {200} +do_test btree-3.30 { + btree_data $::c1 +} {2.00} +do_test btree-3.31 { + btree_next $::c1 + btree_key $::c1 +} {300} +do_test btree-3.32 { + btree_data $::c1 +} {3.00} +do_test btree-3.33 { + btree_next $::c1 + btree_key $::c1 +} {400} +do_test btree-3.34 { + btree_data $::c1 +} {4.00} +do_test btree-3.35 { + btree_next $::c1 + btree_key $::c1 +} {500} +do_test btree-3.36 { + btree_data $::c1 +} {5.00} +do_test btree-3.37 { + btree_next $::c1 + btree_key $::c1 +} {600} +do_test btree-3.38 { + btree_data $::c1 +} {6.00} +do_test btree-3.39 { + btree_next $::c1 + btree_key $::c1 +} {0} +# This test case used to test that requesting data from an invalid cursor +# returned SQLITE_INTERNAL. That is now an assert()ed condition. +# +# do_test btree-3.40 { +# set rc [catch {btree_data $::c1} res] +# lappend rc $res +# } {1 SQLITE_INTERNAL} +do_test btree-3.41 { + lindex [btree_pager_stats $::b1] 1 +} {1} + + +# Now try a delete +# +do_test btree-4.1 { + btree_begin_transaction $::b1 + btree_move_to $::c1 100 + btree_key $::c1 +} {100} +do_test btree-4.1.1 { + lindex [btree_pager_stats $::b1] 1 +} {1} +do_test btree-4.2 { + btree_delete $::c1 +} {} +do_test btree-4.3 { + btree_move_to $::c1 100 + btree_key $::c1 +} {200} +do_test btree-4.4 { + btree_next $::c1 + btree_key $::c1 +} {300} +do_test btree-4.5 { + btree_next $::c1 + btree_key $::c1 +} {400} +do_test btree-4.4 { + btree_move_to $::c1 0 + set r {} + while 1 { + set key [btree_key $::c1] + if {[btree_eof $::c1]} break + lappend r $key + lappend r [btree_data $::c1] + btree_next $::c1 + } + set r +} {200 2.00 300 3.00 400 4.00 500 5.00 600 6.00} + +# Commit and make sure the delete is still there. +# +do_test btree-4.5 { + btree_commit $::b1 + btree_move_to $::c1 0 + set r {} + while 1 { + set key [btree_key $::c1] + if {[btree_eof $::c1]} break + lappend r $key + lappend r [btree_data $::c1] + btree_next $::c1 + } + set r +} {200 2.00 300 3.00 400 4.00 500 5.00 600 6.00} + +# Completely close the database and reopen it. Then check +# the data again. +# +do_test btree-4.6 { + lindex [btree_pager_stats $::b1] 1 +} {1} +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 2000 0] + set ::c1 [btree_cursor $::b1 1 1] + lindex [btree_pager_stats $::b1] 1 +} {1} +do_test btree-4.9 { + set r {} + btree_first $::c1 + while 1 { + set key [btree_key $::c1] + if {[btree_eof $::c1]} break + lappend r $key + lappend r [btree_data $::c1] + btree_next $::c1 + } + set r +} {200 2.00 300 3.00 400 4.00 500 5.00 600 6.00} + +# Try to read and write meta data +# +do_test btree-5.1 { + btree_get_meta $::b1 +} {0 0 0 0 0 0 0 0 0 0} +do_test btree-5.2 { + set rc [catch { + btree_update_meta $::b1 0 1 2 3 4 5 6 7 8 9 + } msg] + lappend rc $msg +} {1 SQLITE_ERROR} +do_test btree-5.3 { + btree_begin_transaction $::b1 + set rc [catch { + btree_update_meta $::b1 0 1 2 3 0 5 6 0 8 9 + } msg] + lappend rc $msg +} {0 {}} +do_test btree-5.4 { + btree_get_meta $::b1 +} {0 1 2 3 0 5 6 0 8 9} +do_test btree-5.5 { + btree_close_cursor $::c1 + btree_rollback $::b1 + btree_get_meta $::b1 +} {0 0 0 0 0 0 0 0 0 0} +do_test btree-5.6 { + btree_begin_transaction $::b1 + btree_update_meta $::b1 0 10 20 30 0 50 60 0 80 90 + btree_commit $::b1 + btree_get_meta $::b1 +} {0 10 20 30 0 50 60 0 80 90} + +proc select_all {cursor} { + set r {} + btree_first $cursor + while {![btree_eof $cursor]} { + set key [btree_key $cursor] + lappend r $key + lappend r [btree_data $cursor] + btree_next $cursor + } + return $r +} +proc select_keys {cursor} { + set r {} + btree_first $cursor + while {![btree_eof $cursor]} { + set key [btree_key $cursor] + 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 0} msg] + lappend rc $msg +} {1 SQLITE_ERROR} +do_test btree-6.2 { + btree_begin_transaction $::b1 + set ::t2 [btree_create_table $::b1 0] +} {2} +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_move_to $::c2 ten + btree_key $::c2 +} {ten} +do_test btree-6.3 { + btree_commit $::b1 + set ::c1 [btree_cursor $::b1 1 1] + lindex [btree_pager_stats $::b1] 1 +} {2} +do_test btree-6.3.1 { + select_all $::c1 +} {200 2.00 300 3.00 400 4.00 500 5.00 600 6.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 +} {1} +do_test btree-6.7 { + btree_close_cursor $::c1 + 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 0] +} {2} +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 +} {2} + +# This test case used to test that requesting the key from an invalid cursor +# returned an empty string. But that is now an assert()ed condition. +# +# do_test btree-6.9.1 { +# btree_move_to $::c2 {} +# btree_key $::c2 +# } {} + +# If we drop table 1 it just clears the table. Table 1 always exists. +# +do_test btree-6.10 { + btree_close_cursor $::c2 + btree_drop_table $::b1 1 + set ::c2 [btree_cursor $::b1 $::t2 1] + set ::c1 [btree_cursor $::b1 1 1] + btree_first $::c1 + btree_eof $::c1 +} {1} +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 +} {1} + +# Check to see that pages defragment properly. To do this test we will +# +# 1. Fill the first page of table 1 with data. +# 2. Delete every other entry of table 1. +# 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} + +# 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]<1234} {append data $data} + set ::data $data + btree_insert $::c1 2020 $data +} {} +btree_page_dump $::b1 1 +btree_page_dump $::b1 2 +do_test btree-8.1.1 { + lindex [btree_pager_stats $::b1] 1 +} {1} +#btree_pager_ref_dump $::b1 +do_test btree-8.2 { + btree_move_to $::c1 2020 + 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.4.2 { + btree_integrity_check $::b1 1 2 +} {} +do_test btree-8.5 { + set data "*** This is an even longer key " + while {[string length $data]<2000} {append data $data} + append data END + set ::data $data + btree_insert $::c1 2030 $data +} {} +do_test btree-8.6 { + btree_move_to $::c1 2030 + 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.1 { + btree_close_cursor $::c1 + btree_close $::b1 + set ::b1 [btree_open test1.bt 2000 0] + set ::c1 [btree_cursor $::b1 1 1] + btree_move_to $::c1 2030 + btree_data $::c1 +} $::data +do_test btree-8.9.2 { + btree_integrity_check $::b1 1 2 +} {} +do_test btree-8.10 { + btree_begin_transaction $::b1 + btree_delete $::c1 +} {} +do_test btree-8.11 { + lindex [btree_get_meta $::b1] 0 +} {4} + +# Now check out keys on overflow pages. +# +do_test btree-8.12.1 { + set ::keyprefix "This is a long prefix to a key " + while {[string length $::keyprefix]<256} {append ::keyprefix $::keyprefix} + btree_close_cursor $::c1 + btree_clear_table $::b1 2 + lindex [btree_get_meta $::b1] 0 +} {4} +do_test btree-8.12.2 { + btree_integrity_check $::b1 1 2 +} {} +do_test btree-8.12.3 { + set ::c1 [btree_cursor $::b1 2 1] + btree_insert $::c1 ${::keyprefix}1 1 + btree_first $::c1 + 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_last $::c1 + 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.1 { + btree_close_cursor $::c1 + btree_drop_table $::b1 2 + btree_integrity_check $::b1 1 +} {} +do_test btree-8.23.2 { + btree_create_table $::b1 0 +} {2} +do_test btree-8.23.3 { + 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 +do_test btree-8.25 { + btree_integrity_check $::b1 1 2 +} {} + +# 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 2 +#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 +} {2} + +# 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_integrity_check $::b1 1 2 +} {} +do_test btree-9.8 { + btree_rollback $::b1 + lindex [btree_pager_stats $::b1] 1 +} {0} +do_test btree-9.9 { + btree_integrity_check $::b1 1 2 +} {} +do_test btree-9.10 { + btree_close $::b1 + set ::b1 [btree_open test1.bt 2000 0] + btree_integrity_check $::b1 1 2 +} {} + +# 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_clear_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 { +btree_breakpoint + for {set i 1} {$i<=30} {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 021 022 023 024 025 026 027 028 029 030} +#btree_tree_dump $::b1 2 +do_test btree-10.4 { + # The divider entry is 012. This is found by uncommenting the + # btree_tree_dump call above and looking at the tree. If the page size + # changes, this test will no longer work. + btree_move_to $::c1 012 + btree_delete $::c1 + select_keys $::c1 +} {001 002 003 004 005 006 007 008 009 010 011 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030} +#btree_pager_ref_dump $::b1 +#btree_tree_dump $::b1 2 +for {set i 1} {$i<=30} {incr i} { + # Check the number of unreference pages. This should be 3 in most cases, + # but 2 when the cursor is pointing to the divider entry which is now 013. + do_test btree-10.5.$i { + btree_move_to $::c1 [format %03d $i] + lindex [btree_pager_stats $::b1] 1 + } [expr {$i==13?2:3}] + #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 31} {$i<=2000} {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_move_to $::c1 $key + 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=="012"} {set ::key 013} + 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} + +# Delete the dividers on the root page +# +#btree_page_dump $::b1 2 +do_test btree-11.4 { + btree_move_to $::c1 1667 + btree_delete $::c1 + btree_move_to $::c1 1667 + set k [btree_key $::c1] + if {$k==1666} { + set k [btree_next $::c1] + } + btree_key $::c1 +} {1668} +#btree_page_dump $::b1 2 + +# 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_move_to $::c1 337 + btree_data $::c1 +} $::data +do_test btree-12.2 { + btree_insert $::c1 401 $::data + btree_move_to $::c1 401 + btree_data $::c1 +} $::data +do_test btree-12.3 { + btree_insert $::c1 465 $::data + btree_move_to $::c1 465 + 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} +# btree_commit $::b1 +# btree_tree_dump $::b1 1 +do_test btree-13.1 { + btree_integrity_check $::b1 1 2 +} {} + +# 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 + +# Miscellaneous tests. +# +# btree-16.1 - Check that a statement cannot be started if a transaction +# is not active. +# btree-16.2 - Check that it is an error to request more payload from a +# btree entry than the entry contains. +do_test btree-16.1 { + catch {btree_begin_statement $::b1} msg + set msg +} SQLITE_ERROR + +do_test btree-16.2 { + btree_begin_transaction $::b1 + set ::c1 [btree_cursor $::b1 2 1] + btree_insert $::c1 1 helloworld + btree_close_cursor $::c1 + btree_commit $::b1 +} {} +do_test btree-16.3 { + set ::c1 [btree_cursor $::b1 2 1] + btree_first $::c1 +} 0 +do_test btree-16.4 { + catch {btree_data $::c1 [expr [btree_payload_size $::c1] + 10]} msg + set msg +} SQLITE_ERROR + +if {$tcl_platform(platform)=="unix"} { + do_test btree-16.5 { + btree_close $::b1 + set ::origperm [file attributes test1.bt -permissions] + file attributes test1.bt -permissions o-w,g-w,a-w + set ::b1 [btree_open test1.bt 2000 0] + catch {btree_cursor $::b1 2 1} msg + file attributes test1.bt -permissions $::origperm + btree_close $::b1 + set ::b1 [btree_open test1.bt 2000 0] + set msg + } {SQLITE_READONLY} +} + +do_test btree-16.6 { + set ::c1 [btree_cursor $::b1 2 1] + set ::c2 [btree_cursor $::b1 2 1] + btree_begin_transaction $::b1 + for {set i 0} {$i<100} {incr i} { + btree_insert $::c1 $i [string repeat helloworld 10] + } + btree_last $::c2 + btree_insert $::c1 100 [string repeat helloworld 10] +} {} + +do_test btree-16.7 { + btree_close_cursor $::c1 + btree_close_cursor $::c2 + btree_commit $::b1 + set ::c1 [btree_cursor $::b1 2 1] + catch {btree_insert $::c1 101 helloworld} msg + set msg +} {SQLITE_ERROR} +do_test btree-16.8 { + btree_first $::c1 + catch {btree_delete $::c1} msg + set msg +} {SQLITE_ERROR} +do_test btree-16.9 { + btree_close_cursor $::c1 + btree_begin_transaction $::b1 + set ::c1 [btree_cursor $::b1 2 0] + catch {btree_insert $::c1 101 helloworld} msg + set msg +} {SQLITE_PERM} +do_test btree-16.10 { + catch {btree_delete $::c1} msg + set msg +} {SQLITE_PERM} + +# As of 2006-08-16 (version 3.3.7+) a read cursor will no +# longer block a write cursor from the same database +# connectiin. The following three tests uses to return +# the SQLITE_LOCK error, but no more. +# +do_test btree-16.11 { + btree_close_cursor $::c1 + set ::c2 [btree_cursor $::b1 2 1] + set ::c1 [btree_cursor $::b1 2 0] + catch {btree_insert $::c2 101 helloworld} msg + set msg +} {} +do_test btree-16.12 { + btree_first $::c2 + catch {btree_delete $::c2} msg + set msg +} {} +do_test btree-16.13 { + catch {btree_clear_table $::b1 2} msg + set msg +} {} + + +do_test btree-16.14 { + btree_close_cursor $::c1 + btree_close_cursor $::c2 + btree_commit $::b1 + catch {btree_clear_table $::b1 2} msg + set msg +} {SQLITE_ERROR} +do_test btree-16.15 { + catch {btree_drop_table $::b1 2} msg + set msg +} {SQLITE_ERROR} +do_test btree-16.16 { + btree_begin_transaction $::b1 + set ::c1 [btree_cursor $::b1 2 0] + catch {btree_drop_table $::b1 2} msg + set msg +} {SQLITE_LOCKED} + +do_test btree-99.1 { + btree_close $::b1 +} {} +catch {unset data} +catch {unset key} + +finish_test -- cgit v1.1