# 2008 May 23 # # 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. # #*********************************************************************** # # Randomized test cases for the rtree extension. # if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source [file join [file dirname [info script]] rtree_util.tcl] source $testdir/tester.tcl ifcapable !rtree { finish_test return } set ::NROW 2500 if {[info exists G(isquick)] && $G(isquick)} { set ::NROW 250 } ifcapable !rtree_int_only { # Return a floating point number between -X and X. # proc rand {X} { return [expr {int((rand()-0.5)*1024.0*$X)/512.0}] } # Return a positive floating point number less than or equal to X # proc randincr {X} { while 1 { set r [expr {int(rand()*$X*32.0)/32.0}] if {$r>0.0} {return $r} } } } else { # For rtree_int_only, return an number between -X and X. # proc rand {X} { return [expr {int((rand()-0.5)*2*$X)}] } # Return a positive integer less than or equal to X # proc randincr {X} { while 1 { set r [expr {int(rand()*$X)+1}] if {$r>0} {return $r} } } } # Scramble the $inlist into a random order. # proc scramble {inlist} { set y {} foreach x $inlist { lappend y [list [expr {rand()}] $x] } set y [lsort $y] set outlist {} foreach x $y { lappend outlist [lindex $x 1] } return $outlist } # Always use the same random seed so that the sequence of tests # is repeatable. # expr {srand(1234)} # Run these tests for all number of dimensions between 1 and 5. # for {set nDim 1} {$nDim<=5} {incr nDim} { # Construct an rtree virtual table and an ordinary btree table # to mirror it. The ordinary table should be much slower (since # it has to do a full table scan) but should give the exact same # answers. # do_test rtree4-$nDim.1 { set clist {} set cklist {} for {set i 0} {$i<$nDim} {incr i} { lappend clist mn$i mx$i lappend cklist "mn$i<mx$i" } db eval "DROP TABLE IF EXISTS rx" db eval "DROP TABLE IF EXISTS bx" db eval "CREATE VIRTUAL TABLE rx USING rtree(id, [join $clist ,])" db eval "CREATE TABLE bx(id INTEGER PRIMARY KEY,\ [join $clist ,], CHECK( [join $cklist { AND }] ))" } {} # Do many insertions of small objects. Do both overlapping and # contained-within queries after each insert to verify that all # is well. # unset -nocomplain where for {set i 1} {$i<$::NROW} {incr i} { # Do a random insert # do_test rtree4-$nDim.2.$i.1 { set vlist {} for {set j 0} {$j<$nDim} {incr j} { set mn [rand 10000] set mx [expr {$mn+[randincr 50]}] lappend vlist $mn $mx } db eval "INSERT INTO rx VALUES(NULL, [join $vlist ,])" db eval "INSERT INTO bx VALUES(NULL, [join $vlist ,])" } {} # Do a contained-in query on all dimensions # set where {} for {set j 0} {$j<$nDim} {incr j} { set mn [rand 10000] set mx [expr {$mn+[randincr 500]}] lappend where mn$j>=$mn mx$j<=$mx } set where "WHERE [join $where { AND }]" do_test rtree4-$nDim.2.$i.2 { list $where [db eval "SELECT id FROM rx $where ORDER BY id"] } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] # Do an overlaps query on all dimensions # set where {} for {set j 0} {$j<$nDim} {incr j} { set mn [rand 10000] set mx [expr {$mn+[randincr 500]}] lappend where mx$j>=$mn mn$j<=$mx } set where "WHERE [join $where { AND }]" do_test rtree4-$nDim.2.$i.3 { list $where [db eval "SELECT id FROM rx $where ORDER BY id"] } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] # Do a contained-in query with surplus contraints at the beginning. # This should force a full-table scan on the rtree. # set where {} for {set j 0} {$j<$nDim} {incr j} { lappend where mn$j>-10000 mx$j<10000 } for {set j 0} {$j<$nDim} {incr j} { set mn [rand 10000] set mx [expr {$mn+[randincr 500]}] lappend where mn$j>=$mn mx$j<=$mx } set where "WHERE [join $where { AND }]" do_test rtree4-$nDim.2.$i.3 { list $where [db eval "SELECT id FROM rx $where ORDER BY id"] } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] # Do an overlaps query with surplus contraints at the beginning. # This should force a full-table scan on the rtree. # set where {} for {set j 0} {$j<$nDim} {incr j} { lappend where mn$j>=-10000 mx$j<=10000 } for {set j 0} {$j<$nDim} {incr j} { set mn [rand 10000] set mx [expr {$mn+[randincr 500]}] lappend where mx$j>$mn mn$j<$mx } set where "WHERE [join $where { AND }]" do_test rtree4-$nDim.2.$i.4 { list $where [db eval "SELECT id FROM rx $where ORDER BY id"] } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] # Do a contained-in query with surplus contraints at the end # set where {} for {set j 0} {$j<$nDim} {incr j} { set mn [rand 10000] set mx [expr {$mn+[randincr 500]}] lappend where mn$j>=$mn mx$j<$mx } for {set j [expr {$nDim-1}]} {$j>=0} {incr j -1} { lappend where mn$j>=-10000 mx$j<10000 } set where "WHERE [join $where { AND }]" do_test rtree4-$nDim.2.$i.5 { list $where [db eval "SELECT id FROM rx $where ORDER BY id"] } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] # Do an overlaps query with surplus contraints at the end # set where {} for {set j [expr {$nDim-1}]} {$j>=0} {incr j -1} { set mn [rand 10000] set mx [expr {$mn+[randincr 500]}] lappend where mx$j>$mn mn$j<=$mx } for {set j 0} {$j<$nDim} {incr j} { lappend where mx$j>-10000 mn$j<=10000 } set where "WHERE [join $where { AND }]" do_test rtree4-$nDim.2.$i.6 { list $where [db eval "SELECT id FROM rx $where ORDER BY id"] } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] # Do a contained-in query with surplus contraints where the # constraints appear in a random order. # set where {} for {set j 0} {$j<$nDim} {incr j} { set mn1 [rand 10000] set mn2 [expr {$mn1+[randincr 100]}] set mx1 [expr {$mn2+[randincr 400]}] set mx2 [expr {$mx1+[randincr 100]}] lappend where mn$j>=$mn1 mn$j>$mn2 mx$j<$mx1 mx$j<=$mx2 } set where "WHERE [join [scramble $where] { AND }]" do_test rtree4-$nDim.2.$i.7 { list $where [db eval "SELECT id FROM rx $where ORDER BY id"] } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] # Do an overlaps query with surplus contraints where the # constraints appear in a random order. # set where {} for {set j 0} {$j<$nDim} {incr j} { set mn1 [rand 10000] set mn2 [expr {$mn1+[randincr 100]}] set mx1 [expr {$mn2+[randincr 400]}] set mx2 [expr {$mx1+[randincr 100]}] lappend where mx$j>=$mn1 mx$j>$mn2 mn$j<$mx1 mn$j<=$mx2 } set where "WHERE [join [scramble $where] { AND }]" do_test rtree4-$nDim.2.$i.8 { list $where [db eval "SELECT id FROM rx $where ORDER BY id"] } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] } do_rtree_integrity_test rtree4-$nDim.3 rx } expand_all_sql db finish_test