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