Fix a bug in rtree that occurs when too many constraints are passed
in on a query. (CVS 5162) FossilOrigin-Name: 54b84a3ddba9d27814c2f613dd197f691ac549a4
This commit is contained in:
parent
9f86ad2354
commit
4b4f780188
@ -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; ii<pIdxInfo->nConstraint; 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; j<iIdx; j+=2){
|
||||
if( zIdxStr[j+1]==cCol && (compatible[zIdxStr[j] & 7] & opmsk)!=0 ){
|
||||
op = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( op ){
|
||||
assert( iIdx<sizeof(zIdxStr)-1 );
|
||||
zIdxStr[iIdx++] = op;
|
||||
zIdxStr[iIdx++] = (char)(p->iColumn-1) + 'a';
|
||||
zIdxStr[iIdx++] = cCol;
|
||||
pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
|
||||
pIdxInfo->aConstraintUsage[ii].omit = 1;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
230
ext/rtree/rtree4.test
Normal file
230
ext/rtree/rtree4.test
Normal file
@ -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<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<2500} {incr i} {
|
||||
# Do a random insert
|
||||
#
|
||||
do_test rtree-$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 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
|
15
manifest
15
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
|
||||
|
@ -1 +1 @@
|
||||
78f4ba974d9b768b62391d8cd2ed407d49584cb8
|
||||
54b84a3ddba9d27814c2f613dd197f691ac549a4
|
Loading…
Reference in New Issue
Block a user