1 # See the file LICENSE for redistribution information.
3 # Copyright (c) 2010, 2012 Oracle and/or its affiliates. All rights reserved.
8 # TEST Test database bulk update for non-duplicate databases.
10 # TEST Put with -multiple, then with -multiple_key,
11 # TEST and make sure the items in database are what we put.
12 # TEST Later, delete some items with -multiple, then with -multiple_key,
13 # TEST and make sure if the correct items are deleted.
15 proc test126 {method { nentries 10000 } { tnum "126" } {callback 1}
16 {subdb 0} {secondary 0} {sort_multiple 0} args } {
19 # For rrecno, when keys are deleted, the ones after will move forward,
20 # and the keys change, which is not good to verify after delete.
21 # So, we skip rrecno temporarily.
22 if {[is_rrecno $method] } {
23 puts "Skipping test$tnum for $method test."
27 # It is only makes sense for btree database to sort bulk buffer.
28 if {$sort_multiple && ![is_btree $method]} {
29 puts "Skipping test$tnum for $method with -sort_multiple."
33 # For compressed databases, we need to sort the items in
34 # the bulk buffer before doing the bulk put/delete operations.
35 if {[is_compressed $args] && !$sort_multiple} {
36 puts "Skipping test$tnum for compressed databases\
37 without -sort_multiple."
44 # Check if we use sub database.
46 if {[is_queue $method] || [is_heap $method]} {
47 puts "Skipping test$tnum with sub database for $method."
50 if {[is_partitioned $args]} {
51 puts "Skipping test$tnum with sub database\
52 for partitioned $method test."
56 set sub_msg "using sub databases"
60 # Check if we use secondary database.
62 set sec_msg "with secondary databases"
65 # If we are using an env, then testfile should just be the db name.
66 # Otherwise it is the test directory and the name.
67 set eindex [lsearch -exact $args "-env"]
70 if { $eindex == -1 } {
71 set testfile $testdir/test$tnum.db
73 if {$subdb && $secondary } {
74 puts "Skipping test$tnum $sub_msg $sec_msg for non-env test."
78 set testfile test$tnum.db
80 set env [lindex $args $eindex]
81 set txnenv [is_txnenv $env]
83 append args " -auto_commit "
85 set testdir [get_home $env]
91 set args [convert_args $method $args]
92 set omethod [convert_method $method]
96 set extra_op "-sort_multiple"
99 puts "Test$tnum: $method ($args)\
100 Database bulk update $sub_msg $sec_msg."
102 set db [eval {berkdb_open_noerr -create -mode 0644} \
103 $args $omethod $testfile $subname]
104 error_check_good dbopen [is_valid_db $db] TRUE
106 # Open the secondary database and do association.
107 # This is the test for [#18878].
110 set sec_subname "subdb-secondary"
111 set sec_testfile $testfile
114 if { $eindex == -1 } {
115 set sec_testfile $testdir/test$tnum-secondary.db
117 set sec_testfile test$tnum-secondary.db
120 # Open a simple dupsort btree database.
121 # In order to be consistent, we need to use all the passed-in
122 # am-unrelated flags.
123 set sec_args [convert_args "btree" $sec_args]
124 set sec_db [eval {berkdb_open_noerr -create -mode 0644} $sec_args \
125 -dup -dupsort -btree $sec_testfile $sec_subname]
126 error_check_good secdb_open [is_valid_db $sec_db] TRUE
127 set ret [$db associate -create [callback_n $callback] $sec_db]
128 error_check_good db_associate $ret 0
131 if { $txnenv == 1 } {
133 error_check_good txn [is_valid_txn $t $env] TRUE
142 # First, we put half the entries using put -multiple.
143 # Then, we put the rest half using put -multiple_key.
145 puts "\tTest$tnum.a: Bulk put data using -multiple $extra_op."
148 while { [gets $did str] != -1 && $count < $nentries / 2 } {
149 if { [is_record_based $method] == 1 } {
150 set key [expr $count + 1]
153 set str [reverse $str]
155 set data [make_fixed_length $method $str]
156 lappend key_list1 $key
157 lappend data_list1 $data
159 if { [is_heap $method] } {
160 set ret [eval {$db put} $txn {$key $data}]
164 if { [is_heap $method] == 0 } {
165 set ret [eval {$db put} $txn -multiple $extra_op \
166 {$key_list1 $data_list1}]
167 error_check_good "put(-multiple $extra_op)" $ret 0
170 # Put again, should succeed
171 set ret [eval {$db put} $txn -multiple $extra_op \
172 {$key_list1 $data_list1}]
173 error_check_good "put_again(-multiple $extra_op)" $ret 0
175 puts "\tTest$tnum.b: Bulk put data using -multiple_key $extra_op."
177 while { [gets $did str] != -1 && $count < $nentries } {
178 if { [is_record_based $method] == 1 } {
179 set key [expr $count + 1]
182 set str [reverse $str]
184 set data [make_fixed_length $method $str]
185 lappend pair_list1 $key $data
187 if { [is_heap $method] } {
188 set ret [eval {$db put} $txn $key $data]
192 if { [is_heap $method] == 0 } {
193 set ret [eval {$db put} $txn -multiple_key $extra_op \
195 error_check_good "put(-multiple_key $extra_op)" $ret 0
198 # Put again, should succeed
199 set ret [eval {$db put} $txn -multiple_key $extra_op \
201 error_check_good "put_again(-multiple_key $extra_op)" $ret 0
205 puts "\tTest$tnum.c: Verify the data after bulk put."
206 set len [llength $pair_list1]
207 for {set indx1 0; set indx2 1} {$indx2 < $len} \
208 {incr indx1 2; incr indx2 2} {
209 lappend key_list1 [lindex $pair_list1 $indx1]
210 lappend data_list1 [lindex $pair_list1 $indx2]
213 test126_check_prirecords $db $key_list1 $data_list1 $txn
216 puts "\tTest$tnum.c.2: Verify the data in secondary database."
218 foreach key $key_list1 data $data_list1 {
219 lappend sec_key_list \
220 [[callback_n $callback] $key $data]
222 test126_check_secrecords $sec_db $sec_key_list \
223 $key_list1 $data_list1 $txn
226 puts "\tTest$tnum.d: Bulk delete data using -multiple $extra_op."
228 for { set i 0 } { $i < $nentries} { incr i 3 } {
229 lappend key_list2 [lindex $key_list1 $i]
231 set ret [eval {$db del} $txn -multiple $extra_op {$key_list2}]
232 error_check_good "del(-multiple $extra_op)" $ret 0
234 # Delete again, should return DB_NOTFOUND/DB_KEYEMPTY.
235 set ret [catch {eval {$db del} $txn -multiple $extra_op \
237 error_check_good {Check DB_NOTFOUND/DB_KEYEMPTY} \
238 [expr [is_substr $res DB_NOTFOUND] || \
239 [is_substr $res DB_KEYEMPTY]] 1
241 puts "\tTest$tnum.e: Bulk delete data using -multiple_key $extra_op."
243 for { set i 1 } { $i < $nentries} { incr i 3} {
244 lappend pair_list2 [lindex $key_list1 $i] \
245 [lindex $data_list1 $i]
248 set ret [eval {$db del} $txn -multiple_key $extra_op {$pair_list2}]
249 error_check_good "del(-multiple_key $extra_op)" $ret 0
251 # Delete again, should return DB_NOTFOUND/DB_KEYEMPTY.
252 set ret [catch {eval {$db del} $txn -multiple_key $extra_op \
254 error_check_good {Check DB_NOTFOUND/DB_KEYEMPTY} \
255 [expr [is_substr $res DB_NOTFOUND] || \
256 [is_substr $res DB_KEYEMPTY]] 1
259 puts "\tTest$tnum.f: Verify the data after bulk delete."
261 # Check if the specified items are deleted
262 set dbc [eval $db cursor $txn]
263 error_check_good $dbc [is_valid_cursor $dbc $db] TRUE
264 set len [llength $key_list2]
265 for {set i 0} {$i < $len} {incr i} {
266 set key [lindex $key_list2 $i]
267 set pair [$dbc get -set $key]
268 error_check_good pair [llength $pair] 0
271 set len [llength $pair_list2]
272 for {set indx1 0; set indx2 1} {$indx2 < $len} \
273 {incr indx1 2; incr indx2 2} {
274 set key [lindex $pair_list2 $indx1]
275 set data [lindex $pair_list2 $indx2]
276 set pair [$dbc get -get_both $key $data]
277 error_check_good pair [llength $pair] 0
280 error_check_good $dbc.close [$dbc close] 0
282 # Remove the deleted items from the original key-data lists.
283 # Since the primary database is non-duplicate, it is enough
284 # for us to just compare using keys.
285 set orig_key_list $key_list1
286 set orig_data_list $data_list1
292 while {$i < $nentries} {
293 set key1 [lindex $orig_key_list $i]
294 set key2 [lindex $key_list2 $j]
295 set key3 [lindex $pair_list2 $k]
296 if {$key1 == $key2} {
299 } elseif {$key1 == $key3} {
303 lappend key_list1 $key1
304 lappend data_list1 [lindex $orig_data_list $i]
309 test126_check_prirecords $db $key_list1 $data_list1 $txn
312 puts "\tTest$tnum.f.2: Verify the data in secondary database."
314 foreach key $key_list1 data $data_list1 {
315 lappend sec_key_list \
316 [[callback_n $callback] $key $data]
318 test126_check_secrecords $sec_db $sec_key_list \
319 $key_list1 $data_list1 $txn
322 if { $txnenv == 1 } {
323 error_check_good txn_commit [$t commit] 0
325 error_check_good db_close [$db close] 0
327 error_check_good secdb_close [$sec_db close] 0
331 proc test126_check_prirecords {db key_list data_list txnarg} {
333 set dbc [eval $db cursor $txnarg]
334 error_check_good $dbc [is_valid_cursor $dbc $db] TRUE
336 # Check if all the records are in key_list(key) and data_list(data).
337 for {set pair [$dbc get -first]} {[llength $pair] > 0} \
338 {set pair [$dbc get -next]} {
339 set key [lindex [lindex $pair 0] 0]
340 set data [lindex [lindex $pair 0] 1]
341 set index [lsearch -exact $key_list $key]
342 error_check_bad key_index $index -1
343 error_check_good data $data [lindex $data_list $index]
346 # Check if all the items in the lists are in the database.
347 set len [llength $key_list]
348 for {set i 0} {$i < $len} {incr i} {
349 set pair [$dbc get -get_both [lindex $key_list $i] \
350 [lindex $data_list $i]]
351 error_check_bad pair [llength $pair] 0
354 error_check_good $dbc.close [$dbc close] 0
357 proc test126_check_secrecords {db sec_key_list pri_key_list data_list txnarg} {
359 set dbc [eval $db cursor $txnarg]
360 error_check_good $dbc [is_valid_cursor $dbc $db] TRUE
362 # Check if all the records are in the lists
363 for {set pair [$dbc pget -first]} {[llength $pair] > 0} \
364 {set pair [$dbc pget -next]} {
365 set sec_key [lindex [lindex $pair 0] 0]
366 set pri_key [lindex [lindex $pair 0] 1]
367 set data [lindex [lindex $pair 0] 2]
368 set index [lsearch -exact $pri_key_list $pri_key]
369 error_check_bad key_index $index -1
370 error_check_good seckey $sec_key [lindex $sec_key_list $index]
371 error_check_good data1 $data [lindex $data_list $index]
374 # Check if all the items in the lists are in the secondary database.
375 set len [llength $sec_key_list]
376 for {set i 0} {$i < $len} {incr i} {
377 set pair [$dbc pget -get_both [lindex $sec_key_list $i] \
378 [lindex $pri_key_list $i]]
379 error_check_bad pair [llength $pair] 0
380 error_check_good data2 [lindex $data_list $i] \
381 [lindex [lindex $pair 0] 2]
384 error_check_good $dbc.close [$dbc close] 0