1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 1996-2009 Oracle. All rights reserved. 4# 5# $Id$ 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 28 # Btree with compression does not support unsorted duplicates. 29 if { [is_compressed $args] == 1 } { 30 puts "Test057 skipping for btree with compression." 31 return 32 } 33 34 puts "Test057: $method delete and replace in presence of cursor." 35 36 # Create the database and open the dictionary 37 set txnenv 0 38 set eindex [lsearch -exact $args "-env"] 39 # 40 # If we are using an env, then testfile should just be the db name. 41 # Otherwise it is the test directory and the name. 42 if { $eindex == -1 } { 43 set testfile $testdir/test057.db 44 set env NULL 45 } else { 46 set testfile test057.db 47 incr eindex 48 set env [lindex $args $eindex] 49 set txnenv [is_txnenv $env] 50 if { $txnenv == 1 } { 51 append args " -auto_commit " 52 } 53 set testdir [get_home $env] 54 } 55 cleanup $testdir $env 56 57 set flags "" 58 set txn "" 59 60 set db [eval {berkdb_open} $args {$omethod $testfile}] 61 error_check_good dbopen:dup [is_valid_db $db] TRUE 62 63 puts "\tTest057.a: Set cursor, delete cursor, put with key." 64 # Put three keys in the database 65 for { set key 1 } { $key <= 3 } {incr key} { 66 if { $txnenv == 1 } { 67 set t [$env txn] 68 error_check_good txn [is_valid_txn $t $env] TRUE 69 set txn "-txn $t" 70 } 71 set r [eval {$db put} $txn $flags {$key datum$key}] 72 error_check_good put $r 0 73 if { $txnenv == 1 } { 74 error_check_good txn [$t commit] 0 75 } 76 } 77 78 # Retrieve keys sequentially so we can figure out their order 79 set i 1 80 if { $txnenv == 1 } { 81 set t [$env txn] 82 error_check_good txn [is_valid_txn $t $env] TRUE 83 set txn "-txn $t" 84 } 85 set curs [eval {$db cursor} $txn] 86 error_check_good curs_open:dup [is_valid_cursor $curs $db] TRUE 87 88 for {set d [$curs get -first] } {[llength $d] != 0 } \ 89 {set d [$curs get -next] } { 90 set key_set($i) [lindex [lindex $d 0] 0] 91 incr i 92 } 93 94 # Now put in a bunch of duplicates for key 2 95 for { set d 1 } { $d <= 5 } {incr d} { 96 set r [eval {$db put} $txn $flags {$key_set(2) dup_$d}] 97 error_check_good dup:put $r 0 98 } 99 100 # Now put the cursor on key 1 101 102 # Now set the cursor on the first of the duplicate set. 103 set r [$curs get -set $key_set(1)] 104 error_check_bad cursor_get:DB_SET [llength $r] 0 105 set k [lindex [lindex $r 0] 0] 106 set d [lindex [lindex $r 0] 1] 107 error_check_good curs_get:DB_SET:key $k $key_set(1) 108 error_check_good curs_get:DB_SET:data $d datum$key_set(1) 109 110 # Now do the delete 111 set r [$curs del] 112 error_check_good delete $r 0 113 114 # Now check the get current on the cursor. 115 error_check_good curs_get:del [$curs get -current] "" 116 117 # Now do a put on the key 118 set r [eval {$db put} $txn $flags {$key_set(1) new_datum$key_set(1)}] 119 error_check_good put $r 0 120 121 # Do a get 122 set r [eval {$db get} $txn {$key_set(1)}] 123 error_check_good get [lindex [lindex $r 0] 1] new_datum$key_set(1) 124 125 # Recheck cursor 126 error_check_good curs_get:deleted [$curs get -current] "" 127 128 # Move cursor and see if we get the key. 129 set r [$curs get -first] 130 error_check_bad cursor_get:DB_FIRST [llength $r] 0 131 set k [lindex [lindex $r 0] 0] 132 set d [lindex [lindex $r 0] 1] 133 error_check_good curs_get:DB_FIRST:key $k $key_set(1) 134 error_check_good curs_get:DB_FIRST:data $d new_datum$key_set(1) 135 136 puts "\tTest057.b: Set two cursor on a key, delete one, overwrite other" 137 set curs2 [eval {$db cursor} $txn] 138 error_check_good curs2_open [is_valid_cursor $curs2 $db] TRUE 139 140 # Set both cursors on the 4rd key 141 set r [$curs get -set $key_set(3)] 142 error_check_bad cursor_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 curs_get:DB_SET:key $k $key_set(3) 146 error_check_good curs_get:DB_SET:data $d datum$key_set(3) 147 148 set r [$curs2 get -set $key_set(3)] 149 error_check_bad cursor2_get:DB_SET [llength $r] 0 150 set k [lindex [lindex $r 0] 0] 151 set d [lindex [lindex $r 0] 1] 152 error_check_good curs2_get:DB_SET:key $k $key_set(3) 153 error_check_good curs2_get:DB_SET:data $d datum$key_set(3) 154 155 # Now delete through cursor 1 156 error_check_good curs1_del [$curs del] 0 157 158 # Verify gets on both 1 and 2 159 error_check_good curs_get:deleted [$curs get -current] "" 160 error_check_good curs_get:deleted [$curs2 get -current] "" 161 162 puts "\tTest057.c:\ 163 Set two cursors on a dup, delete one, overwrite other" 164 165 # Set both cursors on the 2nd duplicate of key 2 166 set r [$curs get -set $key_set(2)] 167 error_check_bad cursor_get:DB_SET [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_SET:key $k $key_set(2) 171 error_check_good curs_get:DB_SET:data $d datum$key_set(2) 172 173 set r [$curs get -next] 174 error_check_bad cursor_get:DB_NEXT [llength $r] 0 175 set k [lindex [lindex $r 0] 0] 176 set d [lindex [lindex $r 0] 1] 177 error_check_good curs_get:DB_NEXT:key $k $key_set(2) 178 error_check_good curs_get:DB_NEXT:data $d dup_1 179 180 set r [$curs2 get -set $key_set(2)] 181 error_check_bad cursor2_get:DB_SET [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_SET:key $k $key_set(2) 185 error_check_good curs2_get:DB_SET:data $d datum$key_set(2) 186 187 set r [$curs2 get -next] 188 error_check_bad cursor2_get:DB_NEXT [llength $r] 0 189 set k [lindex [lindex $r 0] 0] 190 set d [lindex [lindex $r 0] 1] 191 error_check_good curs2_get:DB_NEXT:key $k $key_set(2) 192 error_check_good curs2_get:DB_NEXT:data $d dup_1 193 194 # Now delete through cursor 1 195 error_check_good curs1_del [$curs del] 0 196 197 # Verify gets on both 1 and 2 198 error_check_good curs_get:deleted [$curs get -current] "" 199 error_check_good curs_get:deleted [$curs2 get -current] "" 200 201 error_check_good curs2_close [$curs2 close] 0 202 error_check_good curs_close [$curs close] 0 203 if { $txnenv == 1 } { 204 error_check_good txn [$t commit] 0 205 } 206 error_check_good db_close [$db close] 0 207} 208