1# See the file LICENSE for redistribution information. 2# 3# Copyright (c) 1999,2008 Oracle. All rights reserved. 4# 5# $Id: test046.tcl,v 12.6 2008/01/08 20:58:53 bostic Exp $ 6# 7# TEST test046 8# TEST Overwrite test of small/big key/data with cursor checks. 9proc test046 { method args } { 10 global alphabet 11 global errorInfo 12 global errorCode 13 source ./include.tcl 14 15 set args [convert_args $method $args] 16 set omethod [convert_method $method] 17 18 puts "\tTest046: Overwrite test with cursor and small/big key/data." 19 puts "\tTest046:\t$method $args" 20 21 if { [is_rrecno $method] == 1} { 22 puts "\tTest046: skipping for method $method." 23 return 24 } 25 26 set key "key" 27 set data "data" 28 set txn "" 29 set flags "" 30 31 if { [is_record_based $method] == 1} { 32 set key "" 33 } 34 35 puts "\tTest046: Create $method database." 36 set txnenv 0 37 set eindex [lsearch -exact $args "-env"] 38 # 39 # If we are using an env, then testfile should just be the db name. 40 # Otherwise it is the test directory and the name. 41 if { $eindex == -1 } { 42 set testfile $testdir/test046 43 set env NULL 44 } else { 45 set testfile test046 46 incr eindex 47 set env [lindex $args $eindex] 48 set txnenv [is_txnenv $env] 49 if { $txnenv == 1 } { 50 append args " -auto_commit " 51 } 52 set testdir [get_home $env] 53 } 54 set t1 $testdir/t1 55 cleanup $testdir $env 56 57 set oflags "-create -mode 0644 $args $omethod" 58 set db [eval {berkdb_open} $oflags $testfile.a.db] 59 error_check_good dbopen [is_valid_db $db] TRUE 60 61 # keep nkeys even 62 set nkeys 20 63 64 # Fill page w/ small key/data pairs 65 puts "\tTest046: Fill page with $nkeys small key/data pairs." 66 for { set i 1 } { $i <= $nkeys } { incr i } { 67 if { $txnenv == 1 } { 68 set t [$env txn] 69 error_check_good txn [is_valid_txn $t $env] TRUE 70 set txn "-txn $t" 71 } 72 if { [is_record_based $method] == 1} { 73 set ret [eval {$db put} $txn {$i $data$i}] 74 } elseif { $i < 10 } { 75 set ret [eval {$db put} $txn [set key]00$i \ 76 [set data]00$i] 77 } elseif { $i < 100 } { 78 set ret [eval {$db put} $txn [set key]0$i \ 79 [set data]0$i] 80 } else { 81 set ret [eval {$db put} $txn {$key$i $data$i}] 82 } 83 error_check_good dbput $ret 0 84 if { $txnenv == 1 } { 85 error_check_good txn [$t commit] 0 86 } 87 } 88 89 # open curs to db 90 if { $txnenv == 1 } { 91 set t [$env txn] 92 error_check_good txn [is_valid_txn $t $env] TRUE 93 set txn "-txn $t" 94 } 95 set dbc [eval {$db cursor} $txn] 96 error_check_good db_cursor [is_substr $dbc $db] 1 97 98 # get db order of keys 99 for {set i 1; set ret [$dbc get -first]} { [llength $ret] != 0} { \ 100 set ret [$dbc get -next]} { 101 set key_set($i) [lindex [lindex $ret 0] 0] 102 set data_set($i) [lindex [lindex $ret 0] 1] 103 incr i 104 } 105 106 puts "\tTest046.a: Deletes by key." 107 puts "\t\tTest046.a.1: Get data with SET, then delete before cursor." 108 # get key in middle of page, call this the nth set curr to it 109 set i [expr $nkeys/2] 110 set ret [$dbc get -set $key_set($i)] 111 error_check_bad dbc_get:set [llength $ret] 0 112 set curr $ret 113 114 # delete before cursor(n-1), make sure it is gone 115 set i [expr $i - 1] 116 error_check_good db_del [eval {$db del} $txn {$key_set($i)}] 0 117 118 # use set_range to get first key starting at n-1, should 119 # give us nth--but only works for btree 120 if { [is_btree $method] == 1 } { 121 set ret [$dbc get -set_range $key_set($i)] 122 } else { 123 if { [is_record_based $method] == 1 } { 124 set ret [$dbc get -set $key_set($i)] 125 error_check_good \ 126 dbc_get:deleted(recno) [llength [lindex $ret 1]] 0 127 #error_check_good \ 128 # catch:get [catch {$dbc get -set $key_set($i)} ret] 1 129 #error_check_good \ 130 # dbc_get:deleted(recno) [is_substr $ret "KEYEMPTY"] 1 131 } else { 132 set ret [$dbc get -set $key_set($i)] 133 error_check_good dbc_get:deleted [llength $ret] 0 134 } 135 set ret [$dbc get -set $key_set([incr i])] 136 incr i -1 137 } 138 error_check_bad dbc_get:set(R)(post-delete) [llength $ret] 0 139 error_check_good dbc_get(match):set $ret $curr 140 141 puts "\t\tTest046.a.2: Delete cursor item by key." 142 # nth key, which cursor should be on now 143 set i [incr i] 144 set ret [eval {$db del} $txn {$key_set($i)}] 145 error_check_good db_del $ret 0 146 147 # this should return n+1 key/data, curr has nth key/data 148 if { [string compare $omethod "-btree"] == 0 } { 149 set ret [$dbc get -set_range $key_set($i)] 150 } else { 151 if { [is_record_based $method] == 1 } { 152 set ret [$dbc get -set $key_set($i)] 153 error_check_good \ 154 dbc_get:deleted(recno) [llength [lindex $ret 1]] 0 155 #error_check_good \ 156 # catch:get [catch {$dbc get -set $key_set($i)} ret] 1 157 #error_check_good \ 158 # dbc_get:deleted(recno) [is_substr $ret "KEYEMPTY"] 1 159 } else { 160 set ret [$dbc get -set $key_set($i)] 161 error_check_good dbc_get:deleted [llength $ret] 0 162 } 163 set ret [$dbc get -set $key_set([expr $i+1])] 164 } 165 error_check_bad dbc_get(post-delete):set_range [llength $ret] 0 166 error_check_bad dbc_get(no-match):set_range $ret $curr 167 168 puts "\t\tTest046.a.3: Delete item after cursor." 169 # we'll delete n+2, since we have deleted n-1 and n 170 # i still equal to nth, cursor on n+1 171 set i [incr i] 172 set ret [$dbc get -set $key_set($i)] 173 error_check_bad dbc_get:set [llength $ret] 0 174 set curr [$dbc get -next] 175 error_check_bad dbc_get:next [llength $curr] 0 176 set ret [$dbc get -prev] 177 error_check_bad dbc_get:prev [llength $curr] 0 178 # delete *after* cursor pos. 179 error_check_good db:del [eval {$db del} $txn {$key_set([incr i])}] 0 180 181 # make sure item is gone, try to get it 182 if { [string compare $omethod "-btree"] == 0} { 183 set ret [$dbc get -set_range $key_set($i)] 184 } else { 185 if { [is_record_based $method] == 1 } { 186 set ret [$dbc get -set $key_set($i)] 187 error_check_good \ 188 dbc_get:deleted(recno) [llength [lindex $ret 1]] 0 189 #error_check_good \ 190 # catch:get [catch {$dbc get -set $key_set($i)} ret] 1 191 #error_check_good \ 192 # dbc_get:deleted(recno) [is_substr $ret "KEYEMPTY"] 1 193 } else { 194 set ret [$dbc get -set $key_set($i)] 195 error_check_good dbc_get:deleted [llength $ret] 0 196 } 197 set ret [$dbc get -set $key_set([expr $i +1])] 198 } 199 error_check_bad dbc_get:set(_range) [llength $ret] 0 200 error_check_bad dbc_get:set(_range) $ret $curr 201 error_check_good dbc_get:set [lindex [lindex $ret 0] 0] \ 202 $key_set([expr $i+1]) 203 204 puts "\tTest046.b: Deletes by cursor." 205 puts "\t\tTest046.b.1: Delete, do DB_NEXT." 206 error_check_good dbc:del [$dbc del] 0 207 set ret [$dbc get -next] 208 error_check_bad dbc_get:next [llength $ret] 0 209 set i [expr $i+2] 210 # i = n+4 211 error_check_good dbc_get:next(match) \ 212 [lindex [lindex $ret 0] 0] $key_set($i) 213 214 puts "\t\tTest046.b.2: Delete, do DB_PREV." 215 error_check_good dbc:del [$dbc del] 0 216 set ret [$dbc get -prev] 217 error_check_bad dbc_get:prev [llength $ret] 0 218 set i [expr $i-3] 219 # i = n+1 (deleted all in between) 220 error_check_good dbc_get:prev(match) \ 221 [lindex [lindex $ret 0] 0] $key_set($i) 222 223 puts "\t\tTest046.b.3: Delete, do DB_CURRENT." 224 error_check_good dbc:del [$dbc del] 0 225 # we just deleted, so current item should be KEYEMPTY, throws err 226 set ret [$dbc get -current] 227 error_check_good dbc_get:curr:deleted [llength [lindex $ret 1]] 0 228 #error_check_good catch:get:current [catch {$dbc get -current} ret] 1 229 #error_check_good dbc_get:curr:deleted [is_substr $ret "DB_KEYEMPTY"] 1 230 231 puts "\tTest046.c: Inserts (before/after), by key then cursor." 232 puts "\t\tTest046.c.1: Insert by key before the cursor." 233 # i is at curs pos, i=n+1, we want to go BEFORE 234 set i [incr i -1] 235 set ret [eval {$db put} $txn {$key_set($i) $data_set($i)}] 236 error_check_good db_put:before $ret 0 237 238 puts "\t\tTest046.c.2: Insert by key after the cursor." 239 set i [incr i +2] 240 set ret [eval {$db put} $txn {$key_set($i) $data_set($i)}] 241 error_check_good db_put:after $ret 0 242 243 puts "\t\tTest046.c.3: Insert by curs with deleted curs (should fail)." 244 # cursor is on n+1, we'll change i to match 245 set i [incr i -1] 246 247 error_check_good dbc:close [$dbc close] 0 248 if { $txnenv == 1 } { 249 error_check_good txn [$t commit] 0 250 } 251 error_check_good db:close [$db close] 0 252 if { [is_record_based $method] == 1} { 253 puts "\t\tSkipping the rest of test for method $method." 254 puts "\tTest046 ($method) complete." 255 return 256 } else { 257 # Reopen without printing __db_errs. 258 set db [eval {berkdb_open_noerr} $oflags $testfile.a.db] 259 error_check_good dbopen [is_valid_db $db] TRUE 260 if { $txnenv == 1 } { 261 set t [$env txn] 262 error_check_good txn [is_valid_txn $t $env] TRUE 263 set txn "-txn $t" 264 } 265 set dbc [eval {$db cursor} $txn] 266 error_check_good cursor [is_valid_cursor $dbc $db] TRUE 267 268 # should fail with EINVAL (deleted cursor) 269 set errorCode NONE 270 error_check_good catch:put:before 1 \ 271 [catch {$dbc put -before $data_set($i)} ret] 272 error_check_good dbc_put:deleted:before \ 273 [is_substr $errorCode "EINVAL"] 1 274 275 # should fail with EINVAL 276 set errorCode NONE 277 error_check_good catch:put:after 1 \ 278 [catch {$dbc put -after $data_set($i)} ret] 279 error_check_good dbc_put:deleted:after \ 280 [is_substr $errorCode "EINVAL"] 1 281 282 puts "\t\tTest046.c.4:\ 283 Insert by cursor before/after existent cursor." 284 # can't use before after w/o dup except renumber in recno 285 # first, restore an item so they don't fail 286 #set ret [eval {$db put} $txn {$key_set($i) $data_set($i)}] 287 #error_check_good db_put $ret 0 288 289 #set ret [$dbc get -set $key_set($i)] 290 #error_check_bad dbc_get:set [llength $ret] 0 291 #set i [incr i -2] 292 # i = n - 1 293 #set ret [$dbc get -prev] 294 #set ret [$dbc put -before $key_set($i) $data_set($i)] 295 #error_check_good dbc_put:before $ret 0 296 # cursor pos is adjusted to match prev, recently inserted 297 #incr i 298 # i = n 299 #set ret [$dbc put -after $key_set($i) $data_set($i)] 300 #error_check_good dbc_put:after $ret 0 301 } 302 303 # For the next part of the test, we need a db with no dups to test 304 # overwrites 305 puts "\tTest046.d.0: Cleanup, close db, open new db with no dups." 306 error_check_good dbc:close [$dbc close] 0 307 if { $txnenv == 1 } { 308 error_check_good txn [$t commit] 0 309 } 310 error_check_good db:close [$db close] 0 311 312 set db [eval {berkdb_open} $oflags $testfile.d.db] 313 error_check_good dbopen [is_valid_db $db] TRUE 314 # Fill page w/ small key/data pairs 315 puts "\tTest046.d.0: Fill page with $nkeys small key/data pairs." 316 for { set i 1 } { $i < $nkeys } { incr i } { 317 if { $txnenv == 1 } { 318 set t [$env txn] 319 error_check_good txn [is_valid_txn $t $env] TRUE 320 set txn "-txn $t" 321 } 322 set ret [eval {$db put} $txn {$key$i $data$i}] 323 error_check_good dbput $ret 0 324 if { $txnenv == 1 } { 325 error_check_good txn [$t commit] 0 326 } 327 } 328 329 if { $txnenv == 1 } { 330 set t [$env txn] 331 error_check_good txn [is_valid_txn $t $env] TRUE 332 set txn "-txn $t" 333 } 334 set dbc [eval {$db cursor} $txn] 335 error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE 336 set nkeys 20 337 338 # Prepare cursor on item 339 set ret [$dbc get -first] 340 error_check_bad dbc_get:first [llength $ret] 0 341 342 # Prepare unique big/small values for an initial 343 # and an overwrite set of key/data 344 foreach ptype {init over} { 345 foreach size {big small} { 346 if { [string compare $size big] == 0 } { 347 set key_$ptype$size \ 348 KEY_$size[repeat alphabet 250] 349 set data_$ptype$size \ 350 DATA_$size[repeat alphabet 250] 351 } else { 352 set key_$ptype$size \ 353 KEY_$size[repeat alphabet 10] 354 set data_$ptype$size \ 355 DATA_$size[repeat alphabet 10] 356 } 357 } 358 } 359 360 set i 0 361 # Do all overwrites for key and cursor 362 foreach type {key_over curs_over} { 363 # Overwrite (i=initial) four different kinds of pairs 364 incr i 365 puts "\tTest046.d: Overwrites $type." 366 foreach i_pair {\ 367 {small small} {big small} {small big} {big big} } { 368 # Overwrite (w=write) with four different kinds of data 369 foreach w_pair {\ 370 {small small} {big small} {small big} {big big} } { 371 372 # we can only overwrite if key size matches 373 if { [string compare [lindex \ 374 $i_pair 0] [lindex $w_pair 0]] != 0} { 375 continue 376 } 377 378 # first write the initial key/data 379 set ret [$dbc put -keyfirst \ 380 key_init[lindex $i_pair 0] \ 381 data_init[lindex $i_pair 1]] 382 error_check_good \ 383 dbc_put:curr:init:$i_pair $ret 0 384 set ret [$dbc get -current] 385 error_check_bad dbc_get:curr [llength $ret] 0 386 error_check_good dbc_get:curr:data \ 387 [lindex [lindex $ret 0] 1] \ 388 data_init[lindex $i_pair 1] 389 390 # Now, try to overwrite: dups not supported in 391 # this db 392 if { [string compare $type key_over] == 0 } { 393 puts "\t\tTest046.d.$i: Key\ 394 Overwrite:($i_pair) by ($w_pair)." 395 set ret [eval {$db put} $txn \ 396 $"key_init[lindex $i_pair 0]" \ 397 $"data_over[lindex $w_pair 1]"] 398 error_check_good \ 399 dbput:over:i($i_pair):o($w_pair) $ret 0 400 # check value 401 set ret [eval {$db get} $txn \ 402 $"key_init[lindex $i_pair 0]"] 403 error_check_bad \ 404 db:get:check [llength $ret] 0 405 error_check_good db:get:compare_data \ 406 [lindex [lindex $ret 0] 1] \ 407 $"data_over[lindex $w_pair 1]" 408 } else { 409 # This is a cursor overwrite 410 puts \ 411 "\t\tTest046.d.$i:Curs Overwrite:($i_pair) by ($w_pair)." 412 set ret [$dbc put -current \ 413 $"data_over[lindex $w_pair 1]"] 414 error_check_good \ 415 dbcput:over:i($i_pair):o($w_pair) $ret 0 416 # check value 417 set ret [$dbc get -current] 418 error_check_bad \ 419 dbc_get:curr [llength $ret] 0 420 error_check_good dbc_get:curr:data \ 421 [lindex [lindex $ret 0] 1] \ 422 $"data_over[lindex $w_pair 1]" 423 } 424 } ;# foreach write pair 425 } ;# foreach initial pair 426 } ;# foreach type big/small 427 428 puts "\tTest046.d.3: Cleanup for next part of test." 429 error_check_good dbc_close [$dbc close] 0 430 if { $txnenv == 1 } { 431 error_check_good txn [$t commit] 0 432 } 433 error_check_good db_close [$db close] 0 434 435 if { [is_rbtree $method] == 1} { 436 puts "\tSkipping the rest of Test046 for method $method." 437 puts "\tTest046 complete." 438 return 439 } 440 441 puts "\tTest046.e.1: Open db with sorted dups." 442 set db [eval {berkdb_open_noerr} $oflags -dup -dupsort $testfile.e.db] 443 error_check_good dbopen [is_valid_db $db] TRUE 444 445 # keep nkeys even 446 set nkeys 20 447 set ndups 20 448 449 # Fill page w/ small key/data pairs 450 puts "\tTest046.e.2:\ 451 Put $nkeys small key/data pairs and $ndups sorted dups." 452 for { set i 0 } { $i < $nkeys } { incr i } { 453 if { $txnenv == 1 } { 454 set t [$env txn] 455 error_check_good txn [is_valid_txn $t $env] TRUE 456 set txn "-txn $t" 457 } 458 if { $i < 10 } { 459 set ret [eval {$db put} $txn [set key]0$i [set data]0$i] 460 } else { 461 set ret [eval {$db put} $txn {$key$i $data$i}] 462 } 463 error_check_good dbput $ret 0 464 if { $txnenv == 1 } { 465 error_check_good txn [$t commit] 0 466 } 467 } 468 469 if { $txnenv == 1 } { 470 set t [$env txn] 471 error_check_good txn [is_valid_txn $t $env] TRUE 472 set txn "-txn $t" 473 } 474 # open curs to db 475 set dbc [eval {$db cursor} $txn] 476 error_check_good db_cursor [is_substr $dbc $db] 1 477 478 # get db order of keys 479 for {set i 0; set ret [$dbc get -first]} { [llength $ret] != 0} { \ 480 set ret [$dbc get -next]} { 481 set key_set($i) [lindex [lindex $ret 0] 0] 482 set data_set($i) [lindex [lindex $ret 0] 1] 483 incr i 484 } 485 486 # put 20 sorted duplicates on key in middle of page 487 set i [expr $nkeys/2] 488 set ret [$dbc get -set $key_set($i)] 489 error_check_bad dbc_get:set [llength $ret] 0 490 491 set keym $key_set($i) 492 493 for { set i 0 } { $i < $ndups } { incr i } { 494 if { $i < 10 } { 495 set ret [eval {$db put} $txn {$keym DUPLICATE_0$i}] 496 } else { 497 set ret [eval {$db put} $txn {$keym DUPLICATE_$i}] 498 } 499 error_check_good db_put:DUP($i) $ret 0 500 } 501 502 puts "\tTest046.e.3: Check duplicate duplicates" 503 set ret [eval {$db put} $txn {$keym DUPLICATE_00}] 504 error_check_good dbput:dupdup [is_substr $ret "DB_KEYEXIST"] 1 505 506 # get dup ordering 507 for {set i 0; set ret [$dbc get -set $keym]} { [llength $ret] != 0} {\ 508 set ret [$dbc get -nextdup] } { 509 set dup_set($i) [lindex [lindex $ret 0] 1] 510 incr i 511 } 512 513 # put cursor on item in middle of dups 514 set i [expr $ndups/2] 515 set ret [$dbc get -get_both $keym $dup_set($i)] 516 error_check_bad dbc_get:get_both [llength $ret] 0 517 518 puts "\tTest046.f: Deletes by cursor." 519 puts "\t\tTest046.f.1: Delete by cursor, do a DB_NEXT, check cursor." 520 set ret [$dbc get -current] 521 error_check_bad dbc_get:current [llength $ret] 0 522 error_check_good dbc:del [$dbc del] 0 523 set ret [$dbc get -next] 524 error_check_bad dbc_get:next [llength $ret] 0 525 error_check_good \ 526 dbc_get:nextdup [lindex [lindex $ret 0] 1] $dup_set([incr i]) 527 528 puts "\t\tTest046.f.2: Delete by cursor, do DB_PREV, check cursor." 529 error_check_good dbc:del [$dbc del] 0 530 set ret [$dbc get -prev] 531 error_check_bad dbc_get:prev [llength $ret] 0 532 set i [incr i -2] 533 error_check_good dbc_get:prev [lindex [lindex $ret 0] 1] $dup_set($i) 534 535 puts "\t\tTest046.f.3: Delete by cursor, do DB_CURRENT, check cursor." 536 error_check_good dbc:del [$dbc del] 0 537 set ret [$dbc get -current] 538 error_check_good dbc_get:current:deleted [llength [lindex $ret 1]] 0 539 #error_check_good catch:dbc_get:curr [catch {$dbc get -current} ret] 1 540 #error_check_good \ 541 # dbc_get:current:deleted [is_substr $ret "DB_KEYEMPTY"] 1 542 error_check_good dbc_close [$dbc close] 0 543 if { $txnenv == 1 } { 544 error_check_good txn [$t commit] 0 545 } 546 547 if { $txnenv == 1 } { 548 set t [$env txn] 549 error_check_good txn [is_valid_txn $t $env] TRUE 550 set txn "-txn $t" 551 } 552 # restore deleted keys 553 error_check_good db_put:1 [eval {$db put} $txn {$keym $dup_set($i)}] 0 554 error_check_good db_put:2 [eval {$db put} $txn \ 555 {$keym $dup_set([incr i])}] 0 556 error_check_good db_put:3 [eval {$db put} $txn \ 557 {$keym $dup_set([incr i])}] 0 558 if { $txnenv == 1 } { 559 error_check_good txn [$t commit] 0 560 } 561 562 # tested above 563 564 # Reopen database without __db_err, reset cursor 565 error_check_good dbclose [$db close] 0 566 set db [eval {berkdb_open_noerr} $oflags -dup -dupsort $testfile.e.db] 567 error_check_good dbopen [is_valid_db $db] TRUE 568 if { $txnenv == 1 } { 569 set t [$env txn] 570 error_check_good txn [is_valid_txn $t $env] TRUE 571 set txn "-txn $t" 572 } 573 set dbc [eval {$db cursor} $txn] 574 error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE 575 576 set ret [$dbc get -set $keym] 577 error_check_bad dbc_get:set [llength $ret] 0 578 set ret2 [$dbc get -current] 579 error_check_bad dbc_get:current [llength $ret2] 0 580 # match 581 error_check_good dbc_get:current/set(match) $ret $ret2 582 # right one? 583 error_check_good \ 584 dbc_get:curr/set(matchdup) [lindex [lindex $ret 0] 1] $dup_set(0) 585 586 # cursor is on first dup 587 set ret [$dbc get -next] 588 error_check_bad dbc_get:next [llength $ret] 0 589 # now on second dup 590 error_check_good dbc_get:next [lindex [lindex $ret 0] 1] $dup_set(1) 591 # check cursor 592 set ret [$dbc get -current] 593 error_check_bad dbc_get:curr [llength $ret] 0 594 error_check_good \ 595 dbcget:curr(compare) [lindex [lindex $ret 0] 1] $dup_set(1) 596 597 puts "\tTest046.g: Inserts." 598 puts "\t\tTest046.g.1: Insert by key before cursor." 599 set i 0 600 601 # use "spam" to prevent a duplicate duplicate. 602 set ret [eval {$db put} $txn {$keym $dup_set($i)spam}] 603 error_check_good db_put:before $ret 0 604 # make sure cursor was maintained 605 set ret [$dbc get -current] 606 error_check_bad dbc_get:curr [llength $ret] 0 607 error_check_good \ 608 dbc_get:current(post-put) [lindex [lindex $ret 0] 1] $dup_set(1) 609 610 puts "\t\tTest046.g.2: Insert by key after cursor." 611 set i [expr $i + 2] 612 # use "eggs" to prevent a duplicate duplicate 613 set ret [eval {$db put} $txn {$keym $dup_set($i)eggs}] 614 error_check_good db_put:after $ret 0 615 # make sure cursor was maintained 616 set ret [$dbc get -current] 617 error_check_bad dbc_get:curr [llength $ret] 0 618 error_check_good \ 619 dbc_get:curr(post-put,after) [lindex [lindex $ret 0] 1] $dup_set(1) 620 621 puts "\t\tTest046.g.3: Insert by curs before/after curs (should fail)." 622 # should return EINVAL (dupsort specified) 623 error_check_good dbc_put:before:catch \ 624 [catch {$dbc put -before $dup_set([expr $i -1])} ret] 1 625 error_check_good \ 626 dbc_put:before:deleted [is_substr $errorCode "EINVAL"] 1 627 error_check_good dbc_put:after:catch \ 628 [catch {$dbc put -after $dup_set([expr $i +2])} ret] 1 629 error_check_good \ 630 dbc_put:after:deleted [is_substr $errorCode "EINVAL"] 1 631 632 puts "\tTest046.h: Cursor overwrites." 633 puts "\t\tTest046.h.1: Test that dupsort disallows current overwrite." 634 set ret [$dbc get -set $keym] 635 error_check_bad dbc_get:set [llength $ret] 0 636 error_check_good \ 637 catch:dbc_put:curr [catch {$dbc put -current DATA_OVERWRITE} ret] 1 638 error_check_good dbc_put:curr:dupsort [is_substr $errorCode EINVAL] 1 639 640 puts "\t\tTest046.h.2: New db (no dupsort)." 641 error_check_good dbc_close [$dbc close] 0 642 if { $txnenv == 1 } { 643 error_check_good txn [$t commit] 0 644 } 645 error_check_good db_close [$db close] 0 646 647 set db [eval {berkdb_open} \ 648 $oflags -dup $testfile.h.db] 649 error_check_good db_open [is_valid_db $db] TRUE 650 if { $txnenv == 1 } { 651 set t [$env txn] 652 error_check_good txn [is_valid_txn $t $env] TRUE 653 set txn "-txn $t" 654 } 655 set dbc [eval {$db cursor} $txn] 656 error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE 657 658 for {set i 0} {$i < $nkeys} {incr i} { 659 if { $i < 10 } { 660 set ret [eval {$db put} $txn {key0$i datum0$i}] 661 error_check_good db_put $ret 0 662 } else { 663 set ret [eval {$db put} $txn {key$i datum$i}] 664 error_check_good db_put $ret 0 665 } 666 if { $i == 0 } { 667 for {set j 0} {$j < $ndups} {incr j} { 668 if { $i < 10 } { 669 set keyput key0$i 670 } else { 671 set keyput key$i 672 } 673 if { $j < 10 } { 674 set ret [eval {$db put} $txn \ 675 {$keyput DUP_datum0$j}] 676 } else { 677 set ret [eval {$db put} $txn \ 678 {$keyput DUP_datum$j}] 679 } 680 error_check_good dbput:dup $ret 0 681 } 682 } 683 } 684 685 for {set i 0; set ret [$dbc get -first]} { [llength $ret] != 0} { \ 686 set ret [$dbc get -next]} { 687 set key_set($i) [lindex [lindex $ret 0] 0] 688 set data_set($i) [lindex [lindex $ret 0] 1] 689 incr i 690 } 691 692 for {set i 0; set ret [$dbc get -set key00]} {\ 693 [llength $ret] != 0} {set ret [$dbc get -nextdup]} { 694 set dup_set($i) [lindex [lindex $ret 0] 1] 695 incr i 696 } 697 set i 0 698 set keym key0$i 699 set ret [$dbc get -set $keym] 700 error_check_bad dbc_get:set [llength $ret] 0 701 error_check_good \ 702 dbc_get:set(match) [lindex [lindex $ret 0] 1] $dup_set($i) 703 704 set ret [$dbc get -nextdup] 705 error_check_bad dbc_get:nextdup [llength $ret] 0 706 error_check_good dbc_get:nextdup(match) \ 707 [lindex [lindex $ret 0] 1] $dup_set([expr $i + 1]) 708 709 puts "\t\tTest046.h.3: Insert by cursor before cursor (DB_BEFORE)." 710 set ret [$dbc put -before BEFOREPUT] 711 error_check_good dbc_put:before $ret 0 712 set ret [$dbc get -current] 713 error_check_bad dbc_get:curr [llength $ret] 0 714 error_check_good \ 715 dbc_get:curr:match [lindex [lindex $ret 0] 1] BEFOREPUT 716 # make sure that this is actually a dup w/ dup before 717 set ret [$dbc get -prev] 718 error_check_bad dbc_get:prev [llength $ret] 0 719 error_check_good dbc_get:prev:match \ 720 [lindex [lindex $ret 0] 1] $dup_set($i) 721 set ret [$dbc get -prev] 722 # should not be a dup 723 error_check_bad dbc_get:prev(no_dup) \ 724 [lindex [lindex $ret 0] 0] $keym 725 726 puts "\t\tTest046.h.4: Insert by cursor after cursor (DB_AFTER)." 727 set ret [$dbc get -set $keym] 728 729 # delete next 3 when fix 730 #puts "[$dbc get -current]\ 731 # [$dbc get -next] [$dbc get -next] [$dbc get -next] [$dbc get -next]" 732 #set ret [$dbc get -set $keym] 733 734 error_check_bad dbc_get:set [llength $ret] 0 735 set ret [$dbc put -after AFTERPUT] 736 error_check_good dbc_put:after $ret 0 737 #puts [$dbc get -current] 738 739 # delete next 3 when fix 740 #set ret [$dbc get -set $keym] 741 #puts "[$dbc get -current] next: [$dbc get -next] [$dbc get -next]" 742 #set ret [$dbc get -set AFTERPUT] 743 #set ret [$dbc get -set $keym] 744 #set ret [$dbc get -next] 745 #puts $ret 746 747 set ret [$dbc get -current] 748 error_check_bad dbc_get:curr [llength $ret] 0 749 error_check_good dbc_get:curr:match [lindex [lindex $ret 0] 1] AFTERPUT 750 set ret [$dbc get -prev] 751 # now should be on first item (non-dup) of keym 752 error_check_bad dbc_get:prev1 [llength $ret] 0 753 error_check_good \ 754 dbc_get:match [lindex [lindex $ret 0] 1] $dup_set($i) 755 set ret [$dbc get -next] 756 error_check_bad dbc_get:next [llength $ret] 0 757 error_check_good \ 758 dbc_get:match2 [lindex [lindex $ret 0] 1] AFTERPUT 759 set ret [$dbc get -next] 760 error_check_bad dbc_get:next [llength $ret] 0 761 # this is the dup we added previously 762 error_check_good \ 763 dbc_get:match3 [lindex [lindex $ret 0] 1] BEFOREPUT 764 765 # now get rid of the dups we added 766 error_check_good dbc_del [$dbc del] 0 767 set ret [$dbc get -prev] 768 error_check_bad dbc_get:prev2 [llength $ret] 0 769 error_check_good dbc_del2 [$dbc del] 0 770 # put cursor on first dup item for the rest of test 771 set ret [$dbc get -set $keym] 772 error_check_bad dbc_get:first [llength $ret] 0 773 error_check_good \ 774 dbc_get:first:check [lindex [lindex $ret 0] 1] $dup_set($i) 775 776 puts "\t\tTest046.h.5: Overwrite small by small." 777 set ret [$dbc put -current DATA_OVERWRITE] 778 error_check_good dbc_put:current:overwrite $ret 0 779 set ret [$dbc get -current] 780 error_check_good dbc_get:current(put,small/small) \ 781 [lindex [lindex $ret 0] 1] DATA_OVERWRITE 782 783 puts "\t\tTest046.h.6: Overwrite small with big." 784 set ret [$dbc put -current DATA_BIG_OVERWRITE[repeat $alphabet 200]] 785 error_check_good dbc_put:current:overwrite:big $ret 0 786 set ret [$dbc get -current] 787 error_check_good dbc_get:current(put,small/big) \ 788 [is_substr [lindex [lindex $ret 0] 1] DATA_BIG_OVERWRITE] 1 789 790 puts "\t\tTest046.h.7: Overwrite big with big." 791 set ret [$dbc put -current DATA_BIG_OVERWRITE2[repeat $alphabet 200]] 792 error_check_good dbc_put:current:overwrite(2):big $ret 0 793 set ret [$dbc get -current] 794 error_check_good dbc_get:current(put,big/big) \ 795 [is_substr [lindex [lindex $ret 0] 1] DATA_BIG_OVERWRITE2] 1 796 797 puts "\t\tTest046.h.8: Overwrite big with small." 798 set ret [$dbc put -current DATA_OVERWRITE2] 799 error_check_good dbc_put:current:overwrite:small $ret 0 800 set ret [$dbc get -current] 801 error_check_good dbc_get:current(put,big/small) \ 802 [is_substr [lindex [lindex $ret 0] 1] DATA_OVERWRITE2] 1 803 804 puts "\tTest046.i: Cleaning up from test." 805 error_check_good dbc_close [$dbc close] 0 806 if { $txnenv == 1 } { 807 error_check_good txn [$t commit] 0 808 } 809 error_check_good db_close [$db close] 0 810 811 puts "\tTest046 complete." 812} 813