1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 1996,2008 Oracle. All rights reserved. 4# 5# $Id: test057.tcl,v 12.6 2008/01/08 20:58:53 bostic Exp $ 6# 7# TEST test057 8# TEST Cursor maintenance during key deletes. 9# TEST 1. Delete a key with a cursor. Add the key back with a regular 10# TEST put. Make sure the cursor can't get the new item. 11# TEST 2. Put two cursors on one item. Delete through one cursor, 12# TEST check that the other sees the change. 13# TEST 3. Same as 2, with the two cursors on a duplicate. 14 15proc test057 { method args } { 16 global errorInfo 17 source ./include.tcl 18 19 set args [convert_args $method $args] 20 set omethod [convert_method $method] 21 22 append args " -create -mode 0644 -dup " 23 if { [is_record_based $method] == 1 || [is_rbtree $method] == 1 } { 24 puts "Test057: skipping for method $method" 25 return 26 } 27 puts "Test057: $method delete and replace in presence of cursor." 28 29 # Create the database and open the dictionary 30 set txnenv 0 31 set eindex [lsearch -exact $args "-env"] 32 # 33 # If we are using an env, then testfile should just be the db name. 34 # Otherwise it is the test directory and the name. 35 if { $eindex == -1 } { 36 set testfile $testdir/test057.db 37 set env NULL 38 } else { 39 set testfile test057.db 40 incr eindex 41 set env [lindex $args $eindex] 42 set txnenv [is_txnenv $env] 43 if { $txnenv == 1 } { 44 append args " -auto_commit " 45 } 46 set testdir [get_home $env] 47 } 48 cleanup $testdir $env 49 50 set flags "" 51 set txn "" 52 53 set db [eval {berkdb_open} $args {$omethod $testfile}] 54 error_check_good dbopen:dup [is_valid_db $db] TRUE 55 56 puts "\tTest057.a: Set cursor, delete cursor, put with key." 57 # Put three keys in the database 58 for { set key 1 } { $key <= 3 } {incr key} { 59 if { $txnenv == 1 } { 60 set t [$env txn] 61 error_check_good txn [is_valid_txn $t $env] TRUE 62 set txn "-txn $t" 63 } 64 set r [eval {$db put} $txn $flags {$key datum$key}] 65 error_check_good put $r 0 66 if { $txnenv == 1 } { 67 error_check_good txn [$t commit] 0 68 } 69 } 70 71 # Retrieve keys sequentially so we can figure out their order 72 set i 1 73 if { $txnenv == 1 } { 74 set t [$env txn] 75 error_check_good txn [is_valid_txn $t $env] TRUE 76 set txn "-txn $t" 77 } 78 set curs [eval {$db cursor} $txn] 79 error_check_good curs_open:dup [is_valid_cursor $curs $db] TRUE 80 81 for {set d [$curs get -first] } {[llength $d] != 0 } \ 82 {set d [$curs get -next] } { 83 set key_set($i) [lindex [lindex $d 0] 0] 84 incr i 85 } 86 87 # Now put in a bunch of duplicates for key 2 88 for { set d 1 } { $d <= 5 } {incr d} { 89 set r [eval {$db put} $txn $flags {$key_set(2) dup_$d}] 90 error_check_good dup:put $r 0 91 } 92 93 # Now put the cursor on key 1 94 95 # Now set the cursor on the first of the duplicate set. 96 set r [$curs get -set $key_set(1)] 97 error_check_bad cursor_get:DB_SET [llength $r] 0 98 set k [lindex [lindex $r 0] 0] 99 set d [lindex [lindex $r 0] 1] 100 error_check_good curs_get:DB_SET:key $k $key_set(1) 101 error_check_good curs_get:DB_SET:data $d datum$key_set(1) 102 103 # Now do the delete 104 set r [$curs del] 105 error_check_good delete $r 0 106 107 # Now check the get current on the cursor. 108 error_check_good curs_get:del [$curs get -current] "" 109 110 # Now do a put on the key 111 set r [eval {$db put} $txn $flags {$key_set(1) new_datum$key_set(1)}] 112 error_check_good put $r 0 113 114 # Do a get 115 set r [eval {$db get} $txn {$key_set(1)}] 116 error_check_good get [lindex [lindex $r 0] 1] new_datum$key_set(1) 117 118 # Recheck cursor 119 error_check_good curs_get:deleted [$curs get -current] "" 120 121 # Move cursor and see if we get the key. 122 set r [$curs get -first] 123 error_check_bad cursor_get:DB_FIRST [llength $r] 0 124 set k [lindex [lindex $r 0] 0] 125 set d [lindex [lindex $r 0] 1] 126 error_check_good curs_get:DB_FIRST:key $k $key_set(1) 127 error_check_good curs_get:DB_FIRST:data $d new_datum$key_set(1) 128 129 puts "\tTest057.b: Set two cursor on a key, delete one, overwrite other" 130 set curs2 [eval {$db cursor} $txn] 131 error_check_good curs2_open [is_valid_cursor $curs2 $db] TRUE 132 133 # Set both cursors on the 4rd key 134 set r [$curs get -set $key_set(3)] 135 error_check_bad cursor_get:DB_SET [llength $r] 0 136 set k [lindex [lindex $r 0] 0] 137 set d [lindex [lindex $r 0] 1] 138 error_check_good curs_get:DB_SET:key $k $key_set(3) 139 error_check_good curs_get:DB_SET:data $d datum$key_set(3) 140 141 set r [$curs2 get -set $key_set(3)] 142 error_check_bad cursor2_get:DB_SET [llength $r] 0 143 set k [lindex [lindex $r 0] 0] 144 set d [lindex [lindex $r 0] 1] 145 error_check_good curs2_get:DB_SET:key $k $key_set(3) 146 error_check_good curs2_get:DB_SET:data $d datum$key_set(3) 147 148 # Now delete through cursor 1 149 error_check_good curs1_del [$curs del] 0 150 151 # Verify gets on both 1 and 2 152 error_check_good curs_get:deleted [$curs get -current] "" 153 error_check_good curs_get:deleted [$curs2 get -current] "" 154 155 puts "\tTest057.c:\ 156 Set two cursors on a dup, delete one, overwrite other" 157 158 # Set both cursors on the 2nd duplicate of key 2 159 set r [$curs get -set $key_set(2)] 160 error_check_bad cursor_get:DB_SET [llength $r] 0 161 set k [lindex [lindex $r 0] 0] 162 set d [lindex [lindex $r 0] 1] 163 error_check_good curs_get:DB_SET:key $k $key_set(2) 164 error_check_good curs_get:DB_SET:data $d datum$key_set(2) 165 166 set r [$curs get -next] 167 error_check_bad cursor_get:DB_NEXT [llength $r] 0 168 set k [lindex [lindex $r 0] 0] 169 set d [lindex [lindex $r 0] 1] 170 error_check_good curs_get:DB_NEXT:key $k $key_set(2) 171 error_check_good curs_get:DB_NEXT:data $d dup_1 172 173 set r [$curs2 get -set $key_set(2)] 174 error_check_bad cursor2_get:DB_SET [llength $r] 0 175 set k [lindex [lindex $r 0] 0] 176 set d [lindex [lindex $r 0] 1] 177 error_check_good curs2_get:DB_SET:key $k $key_set(2) 178 error_check_good curs2_get:DB_SET:data $d datum$key_set(2) 179 180 set r [$curs2 get -next] 181 error_check_bad cursor2_get:DB_NEXT [llength $r] 0 182 set k [lindex [lindex $r 0] 0] 183 set d [lindex [lindex $r 0] 1] 184 error_check_good curs2_get:DB_NEXT:key $k $key_set(2) 185 error_check_good curs2_get:DB_NEXT:data $d dup_1 186 187 # Now delete through cursor 1 188 error_check_good curs1_del [$curs del] 0 189 190 # Verify gets on both 1 and 2 191 error_check_good curs_get:deleted [$curs get -current] "" 192 error_check_good curs_get:deleted [$curs2 get -current] "" 193 194 error_check_good curs2_close [$curs2 close] 0 195 error_check_good curs_close [$curs close] 0 196 if { $txnenv == 1 } { 197 error_check_good txn [$t commit] 0 198 } 199 error_check_good db_close [$db close] 0 200} 201