3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
12 # This file contains Tcl code that may be useful for testing or
13 # analyzing r-tree structures created with this module. It is
14 # used by both test procedures and the r-tree viewer application.
18 #--------------------------------------------------------------------------
30 proc rtree_depth
{db zTab
} {
31 $db one
"SELECT rtreedepth(data) FROM ${zTab}_node WHERE nodeno=1"
34 proc rtree_nodedepth
{db zTab iNode
} {
35 set iDepth
[rtree_depth
$db $zTab]
39 set sql
"SELECT parentnode FROM ${zTab}_parent WHERE nodeno = $ii"
47 # Return the number of dimensions of the rtree.
49 proc rtree_ndim
{db zTab
} {
50 set nDim
[expr {(([llength [$db eval "pragma table_info($zTab)"]]/6)-1)/2}]
53 # Return the contents of rtree node $iNode.
55 proc rtree_node
{db zTab iNode
{iPrec
6}} {
56 set nDim
[rtree_ndim
$db $zTab]
58 SELECT rtreenode($nDim, data) FROM ${zTab}_node WHERE nodeno = $iNode
60 set node
[db one
$sql]
62 set nCell
[llength $node]
63 set nCoord
[expr $nDim*2]
64 for {set ii
0} {$ii < $nCell} {incr ii
} {
65 for {set jj
1} {$jj <= $nCoord} {incr jj
} {
66 set newval
[format "%.${iPrec}f" [lindex $node $ii $jj]]
67 lset node
$ii $jj $newval
73 proc rtree_mincells
{db zTab
} {
74 set n
[$db one
"select length(data) FROM ${zTab}_node LIMIT 1"]
75 set nMax
[expr {int
(($n-4)/(8+[rtree_ndim
$db $zTab]*2*4))}]
76 return [expr {int
($nMax/3)}]
79 # An integrity check for the rtree $zTab accessible via database
82 proc rtree_check
{db zTab
} {
85 # Check each r-tree node.
87 rtree_node_check
$db $zTab 1 [rtree_depth
$db $zTab]
89 if {$rc && $msg ne
""} { error $msg }
91 # Check that the _rowid and _parent tables have the right
93 set nNode
[$db one
"SELECT count(*) FROM ${zTab}_node"]
94 set nRow
[$db one
"SELECT count(*) FROM ${zTab}"]
95 set nRowid
[$db one
"SELECT count(*) FROM ${zTab}_rowid"]
96 set nParent
[$db one
"SELECT count(*) FROM ${zTab}_parent"]
98 if {$nNode != ($nParent+1)} {
99 error "Wrong number of entries in ${zTab}_parent"
101 if {$nRow != $nRowid} {
102 error "Wrong number of entries in ${zTab}_rowid"
108 proc rtree_node_check
{db zTab iNode iDepth
} {
109 if {[info exists
::checked($iNode)]} { error "Second ref to $iNode" }
110 set ::checked($iNode) 1
112 set node
[rtree_node
$db $zTab $iNode]
113 if {$iNode!=1 && [llength $node]==0} { error "No such node: $iNode" }
115 if {$iNode != 1 && [llength $node]<[rtree_mincells
$db $zTab]} {
116 puts "Node $iNode: Has only [llength $node] cells"
119 if {$iNode == 1 && [llength $node]==1 && [rtree_depth
$db $zTab]>0} {
120 set depth
[rtree_depth
$db $zTab]
121 puts "Node $iNode: Has only 1 child (tree depth is $depth)"
125 set nDim
[expr {([llength [lindex $node 0]]-1)/2}]
128 set d
[expr $iDepth-1]
130 set shouldbe
[rtree_node_check
$db $zTab [lindex $cell 0] $d]
131 if {$cell ne
$shouldbe} {
132 puts "Node $iNode: Cell is: {$cell}, should be {$shouldbe}"
138 set mapping_table
"${zTab}_parent"
139 set mapping_sql
"SELECT parentnode FROM $mapping_table WHERE rowid = \$rowid"
141 set mapping_table
"${zTab}_rowid"
142 set mapping_sql
"SELECT nodeno FROM $mapping_table WHERE rowid = \$rowid"
145 set rowid
[lindex $cell 0]
146 set mapping
[db one
$mapping_sql]
147 if {$mapping != $iNode} {
148 puts "Node $iNode: $mapping_table entry for cell $rowid is $mapping"
153 set ret
[list $iNode]
154 for {set ii
1} {$ii <= $nDim*2} {incr ii
} {
155 set f
[lindex $node 0 $ii]
157 set f2
[lindex $cell $ii]
158 if {($ii%2)==1 && $f2<$f} {set f
$f2}
159 if {($ii%2)==0 && $f2>$f} {set f
$f2}
166 proc rtree_dump
{db zTab
} {
168 set nDim
[expr {(([llength [$db eval "pragma table_info($zTab)"]]/6)-1)/2}]
169 set sql
"SELECT nodeno, rtreenode($nDim, data) AS node FROM ${zTab}_node"
171 append zRet
[format "% -10s %s\n" $nodeno $node]
176 proc rtree_nodetreedump
{db zTab zIndent iDepth iNode
} {
178 set node
[rtree_node
$db $zTab $iNode 1]
179 append ret
[format "%-3d %s%s\n" $iNode $zIndent $node]
182 set i
[lindex $cell 0]
183 append ret
[rtree_nodetreedump
$db $zTab "$zIndent " [expr $iDepth-1] $i]
189 proc rtree_treedump
{db zTab
} {
190 set d
[rtree_depth
$db $zTab]
191 rtree_nodetreedump
$db $zTab "" $d 1
194 proc do_rtree_integrity_test
{tn tbl
} {
195 uplevel [list do_execsql_test
$tn "SELECT rtreecheck('$tbl')" ok
]