2
# See the file LICENSE for redistribution information.
5
# Sleepycat Software. All rights reserved.
7
# $Id: si005.tcl,v 1.1.2.1 2001/07/23 20:40:23 jbj Exp $
9
# Sindex005: Secondary index and join test.
10
proc sindex005 { methods {nitems 1000} {tnum 5} args } {
13
# Primary method/args.
14
set pmethod [lindex $methods 0]
15
set pargs [convert_args $pmethod $args]
16
set pomethod [convert_method $pmethod]
18
# Sindex005 does a join within a simulated database schema
19
# in which the primary index maps a record ID to a ZIP code and
20
# name in the form "XXXXXname", and there are two secondaries:
21
# one mapping ZIP to ID, the other mapping name to ID.
22
# The primary may be of any database type; the two secondaries
23
# must be either btree or hash.
25
# Method/args for all the secondaries. If only one method
26
# was specified, assume the same method for the two secondaries.
27
set methods [lrange $methods 1 end]
28
if { [llength $methods] == 0 } {
29
for { set i 0 } { $i < 2 } { incr i } {
30
lappend methods $pmethod
32
} elseif { [llength $methods] != 2 } {
33
puts "FAIL: Sindex00$tnum requires exactly two secondaries."
37
set argses [convert_argses $methods $args]
38
set omethods [convert_methods $methods]
40
puts "Sindex00$tnum ($pmethod/$methods) Secondary index join test."
43
set pname "sindex00$tnum-primary.db"
44
set zipname "sindex00$tnum-zip.db"
45
set namename "sindex00$tnum-name.db"
48
# XXX if one is not supplied!
49
set env [berkdb env -create -home $testdir]
50
error_check_good env_open [is_valid_env $env] TRUE
53
set pdb [eval {berkdb_open -create -env} $env $pomethod $pargs $pname]
54
error_check_good primary_open [is_valid_db $pdb] TRUE
56
set zipdb [eval {berkdb_open -create -dup -env} $env \
57
[lindex $omethods 0] [lindex $argses 0] $zipname]
58
error_check_good zip_open [is_valid_db $zipdb] TRUE
59
error_check_good zip_associate [$pdb associate s5_getzip $zipdb] 0
61
set namedb [eval {berkdb_open -create -dup -env} $env \
62
[lindex $omethods 1] [lindex $argses 1] $namename]
63
error_check_good name_open [is_valid_db $namedb] TRUE
64
error_check_good name_associate [$pdb associate s5_getname $namedb] 0
66
puts "\tSindex00$tnum.a: Populate database with $nitems \"names\""
67
s5_populate $pdb $nitems
68
puts "\tSindex00$tnum.b: Perform a join on each \"name\" and \"ZIP\""
69
s5_jointest $pdb $zipdb $namedb
71
error_check_good name_close [$namedb close] 0
72
error_check_good zip_close [$zipdb close] 0
73
error_check_good primary_close [$pdb close] 0
74
error_check_good env_close [$env close] 0
77
proc s5_jointest { pdb zipdb namedb } {
78
set pdbc [$pdb cursor]
79
error_check_good pdb_cursor [is_valid_cursor $pdbc $pdb] TRUE
80
for { set dbt [$pdbc get -first] } { [llength $dbt] > 0 } \
81
{ set dbt [$pdbc get -next] } {
82
set item [lindex [lindex $dbt 0] 1]
83
set retlist [s5_dojoin $item $pdb $zipdb $namedb]
87
proc s5_dojoin { item pdb zipdb namedb } {
88
set name [s5_getname "" $item]
89
set zip [s5_getzip "" $item]
91
set zipc [$zipdb cursor]
92
error_check_good zipc($item) [is_valid_cursor $zipc $zipdb] TRUE
94
set namec [$namedb cursor]
95
error_check_good namec($item) [is_valid_cursor $namec $namedb] TRUE
98
error_check_good pc($item) [is_valid_cursor $pc $pdb] TRUE
100
set ret [$zipc get -set $zip]
101
set zd [lindex [lindex $ret 0] 1]
102
error_check_good zipset($zip) [s5_getzip "" $zd] $zip
104
set ret [$namec get -set $name]
105
set nd [lindex [lindex $ret 0] 1]
106
error_check_good nameset($name) [s5_getname "" $nd] $name
108
set joinc [$pdb join $zipc $namec]
111
for { set dbt [$joinc get] } { [llength $dbt] > 0 } \
112
{ set dbt [$joinc get] } {
113
set ritem [lindex [lindex $dbt 0] 1]
114
error_check_good returned_item($item) $ritem $item
117
error_check_bad anyreturned($item) $anyreturned 0
119
error_check_good joinc_close($item) [$joinc close] 0
120
error_check_good pc_close($item) [$pc close] 0
121
error_check_good namec_close($item) [$namec close] 0
122
error_check_good zipc_close($item) [$zipc close] 0
125
proc s5_populate { db nitems } {
129
for { set i 1 } { $i <= $nitems } { incr i } {
131
if { [string length $word] < 3 } {
133
if { [string length $word] < 3 } {
135
unexpected pair of words < 3 chars long"
138
set datalist [s5_name2zips $word]
139
foreach data $datalist {
140
error_check_good db_put($data) [$db put $i $data$word] 0
146
proc s5_getzip { key data } { return [string range $data 0 4] }
147
proc s5_getname { key data } { return [string range $data 5 end] }
149
# The dirty secret of this test is that the ZIP code is a function of the
150
# name, so we can generate a database and then verify join results easily
151
# without having to consult actual data.
153
# Any word passed into this function will generate from 1 to 26 ZIP
154
# entries, out of the set {00000, 01000 ... 99000}. The number of entries
155
# is just the position in the alphabet of the word's first letter; the
156
# entries are then hashed to the set {00, 01 ... 99} N different ways.
157
proc s5_name2zips { name } {
160
set n [expr [string first [string index $name 0] $alphabet] + 1]
161
error_check_bad starts_with_abc($name) $n -1
164
for { set i 0 } { $i < $n } { incr i } {
166
for { set j 1 } { $j < [string length $name] } \
168
set b [s5_nhash $name $i $j $b]
170
lappend ret [format %05u [expr $b % 100]000]
174
proc s5_nhash { name i j b } {
177
set c [string first [string index $name $j] $alphabet']
178
return [expr (($b * 991) + ($i * 997) + $c) % 10000000]