1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 1999-2009 Oracle. All rights reserved. 4# 5# $Id$ 6# 7# TEST test067 8# TEST Test of DB_CURRENT partial puts onto almost empty duplicate 9# TEST pages, with and without DB_DUP_SORT. 10# TEST 11# TEST Test of DB_CURRENT partial puts on almost-empty duplicate pages. 12# TEST This test was written to address the following issue, #2 in the 13# TEST list of issues relating to bug #0820: 14# TEST 15# TEST 2. DBcursor->put, DB_CURRENT flag, off-page duplicates, hash and btree: 16# TEST In Btree, the DB_CURRENT overwrite of off-page duplicate records 17# TEST first deletes the record and then puts the new one -- this could 18# TEST be a problem if the removal of the record causes a reverse split. 19# TEST Suggested solution is to acquire a cursor to lock down the current 20# TEST record, put a new record after that record, and then delete using 21# TEST the held cursor. 22# TEST 23# TEST It also tests the following, #5 in the same list of issues: 24# TEST 5. DBcursor->put, DB_AFTER/DB_BEFORE/DB_CURRENT flags, DB_DBT_PARTIAL 25# TEST set, duplicate comparison routine specified. 26# TEST The partial change does not change how data items sort, but the 27# TEST record to be put isn't built yet, and that record supplied is the 28# TEST one that's checked for ordering compatibility. 29proc test067 { method {ndups 1000} {tnum "067"} args } { 30 source ./include.tcl 31 global alphabet 32 global errorCode 33 global is_je_test 34 35 set args [convert_args $method $args] 36 set omethod [convert_method $method] 37 38 set txn "" 39 set txnenv 0 40 set eindex [lsearch -exact $args "-env"] 41 42 # If we are using an env, then testfile should just be the db name. 43 # Otherwise it is the test directory and the name. 44 if { $eindex == -1 } { 45 set testfile $testdir/test$tnum.db 46 set env NULL 47 } else { 48 set testfile test$tnum.db 49 incr eindex 50 set env [lindex $args $eindex] 51 set txnenv [is_txnenv $env] 52 if { $txnenv == 1 } { 53 append args " -auto_commit " 54 if { $ndups == 1000 } { 55 set ndups 100 56 } 57 } 58 set testdir [get_home $env] 59 } 60 61 cleanup $testdir $env 62 if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } { 63 puts "\tTest$tnum: skipping for method $method." 64 return 65 } 66 67 puts "Test$tnum:\ 68 $method ($args) Partial puts on near-empty duplicate pages." 69 70 foreach dupopt { "-dup" "-dup -dupsort" } { 71 if { $is_je_test || [is_compressed $args] } { 72 if { $dupopt == "-dup" } { 73 continue 74 } 75 } 76 77 # 78 # Testdir might get reset from the env's home dir back 79 # to the default if this calls something that sources 80 # include.tcl, since testdir is a global. Set it correctly 81 # here each time through the loop. 82 # 83 if { $env != "NULL" } { 84 set testdir [get_home $env] 85 } 86 cleanup $testdir $env 87 set db [eval {berkdb_open -create -mode 0644 \ 88 $omethod} $args $dupopt {$testfile}] 89 error_check_good db_open [is_valid_db $db] TRUE 90 91 puts "\tTest$tnum.a ($dupopt): Put $ndups duplicates." 92 93 set key "key_test$tnum" 94 95 for { set ndx 0 } { $ndx < $ndups } { incr ndx } { 96 set data $alphabet$ndx 97 98 if { $txnenv == 1 } { 99 set t [$env txn] 100 error_check_good txn [is_valid_txn $t $env] TRUE 101 set txn "-txn $t" 102 } 103 # No need for pad_data since we're skipping recno. 104 set ret [eval {$db put} $txn {$key $data}] 105 error_check_good put($key,$data) $ret 0 106 if { $txnenv == 1 } { 107 error_check_good txn [$t commit] 0 108 } 109 } 110 111 # Sync so we can inspect database if the next section bombs. 112 error_check_good db_sync [$db sync] 0 113 puts "\tTest$tnum.b ($dupopt):\ 114 Deleting dups (last first), overwriting each." 115 116 if { $txnenv == 1 } { 117 set t [$env txn] 118 error_check_good txn [is_valid_txn $t $env] TRUE 119 set txn "-txn $t" 120 } 121 set dbc [eval {$db cursor} $txn] 122 error_check_good cursor_create [is_valid_cursor $dbc $db] TRUE 123 124 set count 0 125 while { $count < $ndups - 1 } { 126 # set cursor to last item in db 127 set ret [$dbc get -last] 128 error_check_good \ 129 verify_key [lindex [lindex $ret 0] 0] $key 130 131 # for error reporting 132 set currdatum [lindex [lindex $ret 0] 1] 133 134 # partial-overwrite it 135 # (overwrite offsets 1-4 with "bcde"--which they 136 # already are) 137 138 # Even though we expect success, we catch this 139 # since it might return EINVAL, and we want that 140 # to FAIL. 141 set errorCode NONE 142 set ret [catch {eval $dbc put -current \ 143 {-partial [list 1 4]} "bcde"} \ 144 res] 145 error_check_good \ 146 partial_put_valid($currdatum) $errorCode NONE 147 error_check_good partial_put($currdatum) $res 0 148 149 # delete it 150 error_check_good dbc_del [$dbc del] 0 151 152 #puts $currdatum 153 154 incr count 155 } 156 157 error_check_good dbc_close [$dbc close] 0 158 if { $txnenv == 1 } { 159 error_check_good txn [$t commit] 0 160 } 161 error_check_good db_close [$db close] 0 162 } 163} 164