| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | 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 |
| | set testprefix rtreedoc3 |
| |
|
| | ifcapable !rtree { |
| | finish_test |
| | return |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | proc rnode_cells {aData} { |
| | set nDim 2 |
| |
|
| | set nData [string length $aData] |
| | set nBytePerCell [expr (8 + 2*$nDim*4)] |
| | binary scan [string range $aData 2 3] S nCell |
| |
|
| | set res [list] |
| | for {set i 0} {$i < $nCell} {incr i} { |
| | set iOff [expr $i*$nBytePerCell+4] |
| | set cell [string range $aData $iOff [expr $iOff+$nBytePerCell-1]] |
| | binary scan $cell WIIII rowid x1 x2 y1 y2 |
| | lappend res [list $rowid $x1 $x2 $y1 $y2] |
| | } |
| |
|
| | return $res |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | proc rnode_height {aData} { |
| | binary scan [string range $aData 0 1] S nHeight |
| | return $nHeight |
| | } |
| |
|
| | |
| | |
| | proc rt_node_get {iNode} { |
| | db one { SELECT data FROM rt_node WHERE nodeno=$iNode } |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | proc pq_init {} { |
| | global Q |
| | set Q(pri_queue) [list] |
| |
|
| | set nHeight [rnode_height [rt_node_get 1]] |
| | set nCell [llength [rnode_cells [rt_node_get 1]]] |
| |
|
| | |
| | |
| | lappend Q(pri_queue) [list 0.0 [list \ |
| | iLevel [expr $nHeight+1] \ |
| | iChild 1 \ |
| | iCurrent 0 \ |
| | ]] |
| | } |
| |
|
| | proc pq_extract {} { |
| | global Q |
| | if {[llength $Q(pri_queue)]==0} { |
| | error "priority queue is empty!" |
| | } |
| |
|
| | |
| | |
| | |
| | set iBest 0 |
| | set rBestScore [lindex $Q(pri_queue) 0 0] |
| | for {set ii 1} {$ii < [llength $Q(pri_queue)]} {incr ii} { |
| | set rScore [expr [lindex $Q(pri_queue) $ii 0]] |
| | if {$rScore<$rBestScore} { |
| | set rBestScore $rScore |
| | set iBest $ii |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | set ret [lindex $Q(pri_queue) $iBest] |
| | set Q(pri_queue) [lreplace $Q(pri_queue) $iBest $iBest] |
| |
|
| | return $ret |
| | } |
| |
|
| | proc pq_new_entry {rScore iLevel cell} { |
| | global Q |
| |
|
| | set rowid_name "iChild" |
| | if {$iLevel==0} { set rowid_name "iRowid" } |
| |
|
| | set kv [list] |
| | lappend kv aCoord [lrange $cell 1 end] |
| | lappend kv iLevel $iLevel |
| |
|
| | if {$iLevel==0} { |
| | lappend kv iRowid [lindex $cell 0] |
| | } else { |
| | lappend kv iChild [lindex $cell 0] |
| | lappend kv iCurrent 0 |
| | } |
| |
|
| | lappend Q(pri_queue) [list $rScore $kv] |
| | } |
| |
|
| | proc pq_test_callback {L res} { |
| | |
| | global Q |
| |
|
| | array set G $L |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | foreach {rParentScore parent} [pq_extract] {} |
| | array set P $parent |
| | if {$P(iLevel)==0} { error "query callback mismatch (1)" } |
| | set child_node [rnode_cells [rt_node_get $P(iChild)]] |
| | set expected_cell [lindex $child_node $P(iCurrent)] |
| | set expected_coords [lrange $expected_cell 1 end] |
| | if {[llength $expected_coords] != [llength $G(aCoord)]} { |
| | puts [array get P] |
| | puts "E: $expected_coords G: $G(aCoord)" |
| | error "coordinate mismatch in query callback (1)" |
| | } |
| | foreach a [lrange $expected_cell 1 end] b $G(aCoord) { |
| | if {$a!=$b} { error "coordinate mismatch in query callback (2)" } |
| | } |
| |
|
| | |
| | |
| | if {$G(iLevel) != $P(iLevel)-1} { |
| | error "iLevel mismatch in query callback (1)" |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | set r [lindex $res 0] |
| | set rScore [lindex $res 1] |
| | if {$r!="fully" && $r!="partly" && $r!="not"} { |
| | error "unknown result: $r - expected \"fully\", \"partly\" or \"not\"" |
| | } |
| | if {$r!="not"} { |
| | pq_new_entry $rScore [expr $P(iLevel)-1] $expected_cell |
| | } |
| |
|
| | |
| | |
| | incr P(iCurrent) |
| | if {$P(iCurrent)<[llength $child_node]} { |
| | lappend Q(pri_queue) [list $rParentScore [array get P]] |
| | } |
| | } |
| |
|
| | proc pq_test_result {id x1 x2 y1 y2} { |
| | |
| | foreach {rScore next} [pq_extract] {} |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | array set N $next |
| | if {$N(iLevel)!=0} { error "result row mismatch (1)" } |
| |
|
| | if {$x1!=[lindex $N(aCoord) 0] || $x2!=[lindex $N(aCoord) 1] |
| | || $y1!=[lindex $N(aCoord) 2] || $y2!=[lindex $N(aCoord) 3] |
| | } { |
| | if {$N(iLevel)!=0} { error "result row mismatch (2)" } |
| | } |
| |
|
| | if {$id!=$N(iRowid)} { error "result row mismatch (3)" } |
| | } |
| |
|
| | proc pq_done {} { |
| | global Q |
| | |
| | |
| | if {[llength $Q(pri_queue)]>0} { |
| | error "priority queue is not empty!" |
| | } |
| | } |
| |
|
| | proc pq_debug {caption} { |
| | global Q |
| |
|
| | puts "**** $caption ****" |
| | set i 0 |
| | foreach q [lsort -real -index 0 $Q(pri_queue)] { |
| | puts "PQ $i: $q" |
| | incr i |
| | } |
| | } |
| |
|
| | |
| |
|
| | proc box_query {a} { |
| | set res [list fully [expr rand()]] |
| | pq_test_callback $a $res |
| | return $res |
| | } |
| |
|
| | register_box_query db box_query |
| |
|
| | do_execsql_test 1.0 { |
| | CREATE VIRTUAL TABLE rt USING rtree_i32(id, x1,x2, y1,y2); |
| | WITH s(i) AS ( |
| | SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<64 |
| | ) |
| | INSERT INTO rt SELECT NULL, a.i, a.i+1, b.i, b.i+1 FROM s a, s b; |
| | } |
| |
|
| | proc box_query {a} { |
| | set res [list fully [expr rand()]] |
| | pq_test_callback $a $res |
| | return $res |
| | } |
| |
|
| | pq_init |
| | db eval { SELECT id, x1,x2, y1,y2 FROM rt WHERE id MATCH qbox() } { |
| | pq_test_result $id $x1 $x2 $y1 $y2 |
| | } |
| | pq_done |
| |
|
| | finish_test |
| |
|
| |
|
| |
|