diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index b39ff67c1c..6b37d2c51d 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -12,7 +12,7 @@ ** This file contains code for implementations of the r-tree and r*-tree ** algorithms packaged as an SQLite virtual table module. ** -** $Id: rtree.c,v 1.3 2008/05/26 20:49:03 drh Exp $ +** $Id: rtree.c,v 1.4 2008/05/27 00:06:02 drh Exp $ */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE) @@ -1080,11 +1080,11 @@ static int rtreeFilter( */ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ int rc = SQLITE_OK; - int ii; + int ii, cCol; int iIdx = 0; - char zIdxStr[RTREE_MAX_DIMENSIONS*2+1]; - memset(zIdxStr, 0, RTREE_MAX_DIMENSIONS*2+1); + char zIdxStr[RTREE_MAX_DIMENSIONS*8+1]; + memset(zIdxStr, 0, sizeof(zIdxStr)); assert( pIdxInfo->idxStr==0 ); for(ii=0; iinConstraint; ii++){ @@ -1113,8 +1113,35 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break; } if( op ){ + /* Make sure this particular constraint has not been used before. + ** If it has been used before, ignore it. + ** + ** A <= or < can be used if there is a prior >= or >. + ** A >= or > can be used if there is a prior < or <=. + ** A <= or < is disqualified if there is a prior <=, <, or ==. + ** A >= or > is disqualified if there is a prior >=, >, or ==. + ** A == is disqualifed if there is any prior constraint. + */ + int j, opmsk; + static const unsigned char compatible[] = { 0, 0, 1, 1, 2, 2 }; + assert( compatible[RTREE_EQ & 7]==0 ); + assert( compatible[RTREE_LT & 7]==1 ); + assert( compatible[RTREE_LE & 7]==1 ); + assert( compatible[RTREE_GT & 7]==2 ); + assert( compatible[RTREE_GE & 7]==2 ); + cCol = p->iColumn - 1 + 'a'; + opmsk = compatible[op & 7]; + for(j=0; jiColumn-1) + 'a'; + zIdxStr[iIdx++] = cCol; pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2); pIdxInfo->aConstraintUsage[ii].omit = 1; } diff --git a/ext/rtree/rtree2.test b/ext/rtree/rtree2.test index 43c455f924..e9f395e807 100644 --- a/ext/rtree/rtree2.test +++ b/ext/rtree/rtree2.test @@ -11,7 +11,7 @@ # # The focus of this file is testing the r-tree extension. # -# $Id: rtree2.test,v 1.1 2008/05/26 18:41:54 danielk1977 Exp $ +# $Id: rtree2.test,v 1.2 2008/05/27 00:06:02 drh Exp $ # set testdir [file join [file dirname $argv0] .. .. test] @@ -44,24 +44,24 @@ for {set nDim 1} {$nDim <= 5} {incr nDim} { do_test rtree2-$nDim.2 { db transaction { for {set ii 0} {$ii < $::NROW} {incr ii} { -#puts "Row $ii" + #puts "Row $ii" set values [list] for {set jj 0} {$jj<$nDim*2} {incr jj} { lappend values [expr int(rand()*1000)] } set values [join $values ,] -#puts [rtree_treedump db t1] -#puts "INSERT INTO t2 VALUES($ii, $values)" + #puts [rtree_treedump db t1] + #puts "INSERT INTO t2 VALUES($ii, $values)" set rc [catch {db eval "INSERT INTO t1 VALUES($ii, $values)"}] if {$rc} { incr ii -1 } else { db eval "INSERT INTO t2 VALUES($ii, $values)" } -#if {[rtree_check db t1]} { -#puts [rtree_treedump db t1] -#exit -#} + #if {[rtree_check db t1]} { + #puts [rtree_treedump db t1] + #exit + #} } } @@ -100,13 +100,13 @@ for {set nDim 1} {$nDim <= 5} {incr nDim} { set t2 [execsql "SELECT * FROM t2 WHERE $where ORDER BY ii"] set rc [expr {$t1 eq $t2}] if {$rc != 1} { -puts $where + #puts $where puts $t1 puts $t2 -puts [rtree_treedump db t1] -breakpoint -set t1 [execsql "SELECT * FROM t1 WHERE $where ORDER BY ii"] -exit + #puts [rtree_treedump db t1] + #breakpoint + #set t1 [execsql "SELECT * FROM t1 WHERE $where ORDER BY ii"] + #exit } set rc } {1} @@ -141,4 +141,3 @@ exit } finish_test - diff --git a/ext/rtree/rtree4.test b/ext/rtree/rtree4.test new file mode 100644 index 0000000000..9f584afd2c --- /dev/null +++ b/ext/rtree/rtree4.test @@ -0,0 +1,230 @@ +# 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. +# +# $Id: rtree4.test,v 1.1 2008/05/27 00:06:02 drh Exp $ +# + +set testdir [file join [file dirname $argv0] .. .. test] +source $testdir/tester.tcl + +ifcapable !rtree { + finish_test + return +} + +# 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} + } +} + +# 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=$mn mx$j<=$mx + } + set where "WHERE [join $where { AND }]" + do_test rtree-$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 rtree-$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 rtree-$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 rtree-$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 rtree-$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 rtree-$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 rtree-$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 rtree-$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"]] + + } + +} + +finish_test diff --git a/manifest b/manifest index 4c06f2711b..7edfced992 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Use\s%w\sinstead\sof\s%q\swhen\sconstructing\sshadow\stable\snames\sfor\srtree.\s(CVS\s5161) -D 2008-05-26T20:49:03 +C Fix\sa\sbug\sin\srtree\sthat\soccurs\swhen\stoo\smany\sconstraints\sare\spassed\nin\son\sa\squery.\s(CVS\s5162) +D 2008-05-27T00:06:02 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in 79aeba12300a54903f1b1257c1e7c190234045dd F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -64,12 +64,13 @@ F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 F ext/icu/README.txt 3b130aa66e7a681136f6add198b076a2f90d1e33 F ext/icu/icu.c 12e763d288d23b5a49de37caa30737b971a2f1e2 F ext/rtree/README 64b8300581ba2553a4522ec78812dc940482906b -F ext/rtree/rtree.c 8b849f0460545eca83b23878914aca7891657b4f +F ext/rtree/rtree.c 28b8650cb1594b6a26a47db0b0a3269c8c8d1d43 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree.test ec173a9420ff012e4d29b3063add143583a597a7 F ext/rtree/rtree1.test 7504a4bd3aaad379d2d712bbb05fc75460e8537d -F ext/rtree/rtree2.test 98f3c39b03577330566abf3c7e1e0baf8f9aa521 +F ext/rtree/rtree2.test 3402e9d57cac67651779130bafd4162772d2420e F ext/rtree/rtree3.test 46d1959aa651d3df8b64d93762d3061c62b38105 +F ext/rtree/rtree4.test f285c08f664804558c267dc8e222e7ecd4dfbc6d F ext/rtree/rtree_perf.tcl 0fabb6d5c48cb8024e042ce5d4bb88998b6ec1cb F ext/rtree/rtree_util.tcl ee0a0311eb12175319d78bfb37302320496cee6e F ext/rtree/viewrtree.tcl 09526398dae87a5a87c5aac2b3854dbaf8376869 @@ -589,7 +590,7 @@ F tool/speedtest16.c 6f5bc019dcf8b6537f379bbac0408a9e1a86f0b6 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c e74126bc12178fa29904f711bb100212a5448041 F tool/speedtest8inst1.c 025879132979a5fdec11218472cba6cf8f6ec854 -P aa8eba3360c31182f5238e96b83a382374f40fab -R 6ae55ee931b382f2653693522f39d2a9 +P 78f4ba974d9b768b62391d8cd2ed407d49584cb8 +R 1a1f7b7755f4d5c027e202044942e3ee U drh -Z 38ba8ba8b7fad64dd7f56bc5220bc609 +Z d4c09f4b49e195721c249033176d5e36 diff --git a/manifest.uuid b/manifest.uuid index 85b4a22152..91b11adeee 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -78f4ba974d9b768b62391d8cd2ed407d49584cb8 \ No newline at end of file +54b84a3ddba9d27814c2f613dd197f691ac549a4 \ No newline at end of file