1# 2008 May 23 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# 12# Randomized test cases for the rtree extension. 13# 14# $Id: rtree4.test,v 1.3 2008/06/23 15:55:52 danielk1977 Exp $ 15# 16 17if {![info exists testdir]} { 18 set testdir [file join [file dirname $argv0] .. .. test] 19} 20source $testdir/tester.tcl 21 22ifcapable !rtree { 23 finish_test 24 return 25} 26 27set ::NROW 2500 28if {[info exists ISQUICK] && $ISQUICK} { 29 set ::NROW 250 30} 31 32# Return a floating point number between -X and X. 33# 34proc rand {X} { 35 return [expr {int((rand()-0.5)*1024.0*$X)/512.0}] 36} 37 38# Return a positive floating point number less than or equal to X 39# 40proc randincr {X} { 41 while 1 { 42 set r [expr {int(rand()*$X*32.0)/32.0}] 43 if {$r>0.0} {return $r} 44 } 45} 46 47# Scramble the $inlist into a random order. 48# 49proc scramble {inlist} { 50 set y {} 51 foreach x $inlist { 52 lappend y [list [expr {rand()}] $x] 53 } 54 set y [lsort $y] 55 set outlist {} 56 foreach x $y { 57 lappend outlist [lindex $x 1] 58 } 59 return $outlist 60} 61 62# Always use the same random seed so that the sequence of tests 63# is repeatable. 64# 65expr {srand(1234)} 66 67# Run these tests for all number of dimensions between 1 and 5. 68# 69for {set nDim 1} {$nDim<=5} {incr nDim} { 70 71 # Construct an rtree virtual table and an ordinary btree table 72 # to mirror it. The ordinary table should be much slower (since 73 # it has to do a full table scan) but should give the exact same 74 # answers. 75 # 76 do_test rtree4-$nDim.1 { 77 set clist {} 78 set cklist {} 79 for {set i 0} {$i<$nDim} {incr i} { 80 lappend clist mn$i mx$i 81 lappend cklist "mn$i<mx$i" 82 } 83 db eval "DROP TABLE IF EXISTS rx" 84 db eval "DROP TABLE IF EXISTS bx" 85 db eval "CREATE VIRTUAL TABLE rx USING rtree(id, [join $clist ,])" 86 db eval "CREATE TABLE bx(id INTEGER PRIMARY KEY,\ 87 [join $clist ,], CHECK( [join $cklist { AND }] ))" 88 } {} 89 90 # Do many insertions of small objects. Do both overlapping and 91 # contained-within queries after each insert to verify that all 92 # is well. 93 # 94 unset -nocomplain where 95 for {set i 1} {$i<$::NROW} {incr i} { 96 # Do a random insert 97 # 98 do_test rtree-$nDim.2.$i.1 { 99 set vlist {} 100 for {set j 0} {$j<$nDim} {incr j} { 101 set mn [rand 10000] 102 set mx [expr {$mn+[randincr 50]}] 103 lappend vlist $mn $mx 104 } 105 db eval "INSERT INTO rx VALUES(NULL, [join $vlist ,])" 106 db eval "INSERT INTO bx VALUES(NULL, [join $vlist ,])" 107 } {} 108 109 # Do a contained-in query on all dimensions 110 # 111 set where {} 112 for {set j 0} {$j<$nDim} {incr j} { 113 set mn [rand 10000] 114 set mx [expr {$mn+[randincr 500]}] 115 lappend where mn$j>=$mn mx$j<=$mx 116 } 117 set where "WHERE [join $where { AND }]" 118 do_test rtree-$nDim.2.$i.2 { 119 list $where [db eval "SELECT id FROM rx $where ORDER BY id"] 120 } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] 121 122 # Do an overlaps query on all dimensions 123 # 124 set where {} 125 for {set j 0} {$j<$nDim} {incr j} { 126 set mn [rand 10000] 127 set mx [expr {$mn+[randincr 500]}] 128 lappend where mx$j>=$mn mn$j<=$mx 129 } 130 set where "WHERE [join $where { AND }]" 131 do_test rtree-$nDim.2.$i.3 { 132 list $where [db eval "SELECT id FROM rx $where ORDER BY id"] 133 } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] 134 135 # Do a contained-in query with surplus contraints at the beginning. 136 # This should force a full-table scan on the rtree. 137 # 138 set where {} 139 for {set j 0} {$j<$nDim} {incr j} { 140 lappend where mn$j>-10000 mx$j<10000 141 } 142 for {set j 0} {$j<$nDim} {incr j} { 143 set mn [rand 10000] 144 set mx [expr {$mn+[randincr 500]}] 145 lappend where mn$j>=$mn mx$j<=$mx 146 } 147 set where "WHERE [join $where { AND }]" 148 do_test rtree-$nDim.2.$i.3 { 149 list $where [db eval "SELECT id FROM rx $where ORDER BY id"] 150 } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] 151 152 # Do an overlaps query with surplus contraints at the beginning. 153 # This should force a full-table scan on the rtree. 154 # 155 set where {} 156 for {set j 0} {$j<$nDim} {incr j} { 157 lappend where mn$j>=-10000 mx$j<=10000 158 } 159 for {set j 0} {$j<$nDim} {incr j} { 160 set mn [rand 10000] 161 set mx [expr {$mn+[randincr 500]}] 162 lappend where mx$j>$mn mn$j<$mx 163 } 164 set where "WHERE [join $where { AND }]" 165 do_test rtree-$nDim.2.$i.4 { 166 list $where [db eval "SELECT id FROM rx $where ORDER BY id"] 167 } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] 168 169 # Do a contained-in query with surplus contraints at the end 170 # 171 set where {} 172 for {set j 0} {$j<$nDim} {incr j} { 173 set mn [rand 10000] 174 set mx [expr {$mn+[randincr 500]}] 175 lappend where mn$j>=$mn mx$j<$mx 176 } 177 for {set j [expr {$nDim-1}]} {$j>=0} {incr j -1} { 178 lappend where mn$j>=-10000 mx$j<10000 179 } 180 set where "WHERE [join $where { AND }]" 181 do_test rtree-$nDim.2.$i.5 { 182 list $where [db eval "SELECT id FROM rx $where ORDER BY id"] 183 } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] 184 185 # Do an overlaps query with surplus contraints at the end 186 # 187 set where {} 188 for {set j [expr {$nDim-1}]} {$j>=0} {incr j -1} { 189 set mn [rand 10000] 190 set mx [expr {$mn+[randincr 500]}] 191 lappend where mx$j>$mn mn$j<=$mx 192 } 193 for {set j 0} {$j<$nDim} {incr j} { 194 lappend where mx$j>-10000 mn$j<=10000 195 } 196 set where "WHERE [join $where { AND }]" 197 do_test rtree-$nDim.2.$i.6 { 198 list $where [db eval "SELECT id FROM rx $where ORDER BY id"] 199 } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] 200 201 # Do a contained-in query with surplus contraints where the 202 # constraints appear in a random order. 203 # 204 set where {} 205 for {set j 0} {$j<$nDim} {incr j} { 206 set mn1 [rand 10000] 207 set mn2 [expr {$mn1+[randincr 100]}] 208 set mx1 [expr {$mn2+[randincr 400]}] 209 set mx2 [expr {$mx1+[randincr 100]}] 210 lappend where mn$j>=$mn1 mn$j>$mn2 mx$j<$mx1 mx$j<=$mx2 211 } 212 set where "WHERE [join [scramble $where] { AND }]" 213 do_test rtree-$nDim.2.$i.7 { 214 list $where [db eval "SELECT id FROM rx $where ORDER BY id"] 215 } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] 216 217 # Do an overlaps query with surplus contraints where the 218 # constraints appear in a random order. 219 # 220 set where {} 221 for {set j 0} {$j<$nDim} {incr j} { 222 set mn1 [rand 10000] 223 set mn2 [expr {$mn1+[randincr 100]}] 224 set mx1 [expr {$mn2+[randincr 400]}] 225 set mx2 [expr {$mx1+[randincr 100]}] 226 lappend where mx$j>=$mn1 mx$j>$mn2 mn$j<$mx1 mn$j<=$mx2 227 } 228 set where "WHERE [join [scramble $where] { AND }]" 229 do_test rtree-$nDim.2.$i.8 { 230 list $where [db eval "SELECT id FROM rx $where ORDER BY id"] 231 } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] 232 } 233 234} 235 236finish_test 237