# new in 2.3: object oriented view interface source defs_mk.tcl proc fill {v prop args} { foreach x $args { $v insert end $prop $x } } proc dump {v} { set n [$v size] set r {} for {set i 0} {$i < $n} {incr i} { set l {} foreach {x y} [$v get $i] { lappend l $y } lappend r $l } return $r } T 1 {basic view operations} { mk::file open db [F].mk mk::view layout db.a {s i:I} set v [mk::view open db.a v] C $v v C [v info] {s i:I} for {set i 0} {$i < 100} {incr i} { v insert end s s$i/$i i $i } C [v size] 100 C [v get 0] {s s0/0 i 0} C [v get 1] {s s1/1 i 1} C [v get 99] {s s99/99 i 99} C [v get 9] {s s9/9 i 9} C [v get 9 s] s9/9 C [v get 9 i] 9 C [v find s s12/12] 12 catch {v find s blah} e C $e {not found} C [v find i 23] 23 C [catch {v find i -1}] 1 # views opened more than once are shared set w [mk::view open db.a] C [$w size] 100 $w insert end s wow i -1 C [v size] 101 C [v get end] {s wow i -1} $w close v close } T 2 {view modifications} { mk::file open db [F].mk mk::view layout db.a i:I mk::view open db.a v v insert end i 1 v insert end i 2 v insert 1 i 3 v insert end i 4 C [v size] 4 foreach {x y} {0 1 1 3 2 2 3 4} { C [v get $x i] $y } v delete 1 v delete [expr {[v size]-1}] C [v size] 2 foreach {x y} {0 1 1 2} { C [v get $x i] $y } v set end i 5 v set 0 i 6 foreach {x y} {0 6 1 5} { C [v get $x i] $y } v close } T 3 {view operators} { mk::file open db [F].mk mk::view layout db.a i:I mk::view layout db.b i:I mk::view layout db.c j:I mk::view layout db.d k:I mk::view open db.a v1 mk::view open db.b v2 mk::view open db.c v3 mk::view open db.d v4 fill v1 i 1 2 3 4 5 fill v2 i 3 4 5 6 7 fill v3 j 3 4 5 6 7 fill v4 k 1 2 1 set v [v1 view clone] C [$v size] 0 C [$v info] i:I $v close set v [v1 view copy] C [dump $v] {1 2 3 4 5} $v close set v [v1 view concat v2] C [dump $v] {1 2 3 4 5 3 4 5 6 7} $v close set v [v1 view different v2] C [dump $v] {1 2 6 7} $v close set v [v1 view minus v2] C [dump $v] {1 2} $v close set v [v1 view intersect v2] C [dump $v] {3 4 5} $v close set v [v1 view union v2] C [dump $v] {1 2 3 4 5 6 7} $v close set v [v1 view pair v3] C [dump $v] {{1 3} {2 4} {3 5} {4 6} {5 7}} $v close set v [v2 view range 2 3] C [dump $v] {5 6} $v close set v [v2 view range 3 end] C [dump $v] {6 7} $v close set v [v2 view range 2 4 -1] C [dump $v] {7 6 5} $v close set v [v2 view map v4] C [dump $v] {4 5 4} $v close set v [v4 view unique] C [dump $v] {1 2} $v close v1 close v2 close v3 close v4 close } T 4 {hash view} { mk::file open db [F].mk mk::view layout db.data {k:I v:S} mk::view layout db.map {_H:I _R:I} mk::view open db.data v1 mk::view open db.map v2 rename [v1 view hash v2 1] v3 v3 insert end k 1 v one v3 insert end k 2 v two v3 insert 1 k 3 v three v3 insert 1 k 4 v four v3 insert 1 k 5 v five C [dump v3] {{1 one} {5 five} {4 four} {3 three} {2 two}} C [v3 find k 3] 3 C [v3 find v three] 3 v3 delete 1 C [v3 find k 3] 2 C [v3 find v three] 2 v3 delete 2 C [catch {v3 find k 3}] 1 C [catch {v3 find v three}] 1 C [dump v3] {{1 one} {4 four} {2 two}} C [v3 find k 1] 0 C [v3 find k 4] 1 C [v3 find k 2] 2 v3 set 1 v nine C [dump v3] {{1 one} {4 nine} {2 two}} v3 set 1 k 9 C [dump v3] {{1 one} {9 nine} {2 two}} C [v3 find k 1] 0 C [v3 find k 9] 1 C [v3 find k 2] 2 C [catch {v3 find k 4}] 1 v3 set 1 k 1 v clobber C [dump v3] {{1 nine} {2 clobber}} # WARNING, the above is a bug, the result *should* have been: # C [dump v3] {{1 clobber} {2 two}} # but due to a nasty problem, a different row gets clobbered # # There are more such problems, i.e. with a 2-column key, when # changing the key, the intermediate state will be stored and # can delete an unrelated row due to the above deleting effect # # The advice for now is: DO NOT change keys, or ONLY the key # property in a single-prop hash mapping. In the above case, # "v3 set 1 k 1" would've worked fine (deleting the other row). v3 close v2 close v1 close } T 5 {blocked view} { mk::file open db [F].mk mk::view layout db.data {{_B {k:I v:D}}} mk::view open db.data v1 rename [v1 view blocked] v2 set n 2500 set nb 4 ;# number of buckets, depends on blocking algorithm for {set i 0} {$i < $n} {incr i} { v2 insert end k $i v $i.$i } C [v2 size] $n C [v1 size] $nb # check that all blocks combined have the same number of rows set t 0 for {set j 0} {$j < $nb} {incr j} { #puts [mk::view size db.data!$j._B] incr t [mk::view size db.data!$j._B] } C $t $n C [v2 find k 3] 3 C [v2 find v 3.3] 3 v2 delete 1 C [v2 find k 3] 2 C [v2 find v 3.3] 2 v2 delete 2 C [catch {v2 find k 3}] 1 C [catch {v2 find v 3.3}] 1 set w [v2 view range 0 3] C [dump $w] {{0 0.0} {2 2.2} {4 4.4} {5 5.5}} $w close v2 insert 2 k 3 v 3.3 v2 insert 1 k 1 v 1.1 for {set i 0} {$i < [v2 size]} {incr i} { v2 delete $i } for {set i 0} {$i < [v2 size]} {incr i} { C [v2 get $i k] [expr {2*$i+1}] } A {[v1 size] < $nb} set t 0 for {set j 0} {$j < [v1 size]} {incr j} { #puts [mk::view size db.data!$j._B] incr t [mk::view size db.data!$j._B] } C $t [v2 size] v2 close v1 close } T 6 {ordered view} { mk::file open db [F].mk mk::view layout db.data {k:I v:S} mk::view open db.data v1 rename [v1 view ordered 1] v2 v2 insert end k 1 v one v2 insert end k 5 v five v2 insert end k 4 v four v2 insert end k 3 v three v2 insert end k 2 v two C [dump v2] {{1 one} {2 two} {3 three} {4 four} {5 five}} C [v2 find k 3] 2 C [v2 find v three] 2 v2 delete 1 C [v2 find k 3] 1 C [v2 find v three] 1 v2 delete 1 C [catch {v2 find k 3}] 1 C [catch {v2 find v three}] 1 C [dump v2] {{1 one} {4 four} {5 five}} C [v2 find k 1] 0 C [v2 find k 4] 1 C [v2 find k 5] 2 v2 set 1 v nine C [dump v2] {{1 one} {4 nine} {5 five}} v2 set 1 k 9 C [dump v2] {{1 one} {5 five} {9 nine}} C [v2 find k 1] 0 C [v2 find k 5] 1 C [v2 find k 9] 2 C [catch {v2 find k 4}] 1 v2 set 1 k 1 v clobber C [dump v2] {{1 five} {9 clobber}} # WARNING, same problem as described above, should have been: # C [dump v2] {{1 clobber} {9 nine}} v2 close v1 close } T 7 {blocked hash view} { mk::file open db [F].mk mk::view layout db.data {k:I v:S} mk::view layout db.map {{_B {_H:I _R:I}}} mk::view open db.data v1 mk::view open db.map v2 rename [v2 view blocked] v3 rename [v1 view hash v3 1] v4 v4 insert end k 1 v one v4 insert end k 2 v two v4 insert 1 k 3 v three v4 insert 1 k 4 v four v4 insert 1 k 5 v five C [dump v4] {{1 one} {5 five} {4 four} {3 three} {2 two}} C [dump v1] {{1 one} {5 five} {4 four} {3 three} {2 two}} C [v2 size] 2 C [v3 size] 9 C [v4 find k 3] 3 C [v4 find v three] 3 v4 delete 1 C [v4 find k 3] 2 C [v4 find v three] 2 v4 delete 2 C [catch {v4 find k 3}] 1 C [catch {v4 find v three}] 1 C [dump v4] {{1 one} {4 four} {2 two}} C [v4 find k 1] 0 C [v4 find k 4] 1 C [v4 find k 2] 2 v4 set 1 v nine C [dump v4] {{1 one} {4 nine} {2 two}} v4 set 1 k 9 C [dump v4] {{1 one} {9 nine} {2 two}} C [v4 find k 1] 0 C [v4 find k 9] 1 C [v4 find k 2] 2 C [catch {v4 find k 4}] 1 v4 set 1 k 1 v clobber C [dump v4] {{1 nine} {2 clobber}} # WARNING, same problem as described above, should have been: # C [dump v4] {{1 clobber} {2 two}} for {set x 100} {$x <= 999} {incr x} { v4 insert end k $x v v$x } # check that the entries all get found for {set x 100} {$x <= 999} {incr x} { C [expr {$x-98}] [v4 find k $x] } C [v2 size] 4 C [v3 size] 2049 v4 close v3 close v2 close v1 close } Q 8