1b39c5158Smillert#!./perl -w 2b39c5158Smillert 3b39c5158Smillertuse warnings; 4b39c5158Smillertuse strict; 5b39c5158Smillertuse Config; 6b39c5158Smillert 7b39c5158SmillertBEGIN { 8898184e3Ssthen if(-d "lib" && -f "TEST") { 9b39c5158Smillert if ($Config{'extensions'} !~ /\bDB_File\b/ ) { 10b39c5158Smillert print "1..0 # Skip: DB_File was not built\n"; 11b39c5158Smillert exit 0; 12b39c5158Smillert } 13b39c5158Smillert } 14b39c5158Smillert} 15b39c5158Smillert 16b39c5158SmillertBEGIN 17b39c5158Smillert{ 18b39c5158Smillert if ($^O eq 'darwin' 19b39c5158Smillert && (split(/\./, $Config{osvers}))[0] < 7 # Mac OS X 10.3 == Darwin 7 20b39c5158Smillert && $Config{db_version_major} == 1 21b39c5158Smillert && $Config{db_version_minor} == 0 22b39c5158Smillert && $Config{db_version_patch} == 0) { 23b39c5158Smillert warn <<EOM; 24b39c5158Smillert# 25b39c5158Smillert# This test is known to crash in Mac OS X versions 10.2 (or earlier) 26b39c5158Smillert# because of the buggy Berkeley DB version included with the OS. 27b39c5158Smillert# 28b39c5158SmillertEOM 29b39c5158Smillert } 30b39c5158Smillert} 31b39c5158Smillert 32b39c5158Smillertuse DB_File; 33b39c5158Smillertuse Fcntl; 34f3efcd01Safresh1use File::Temp qw(tempdir) ; 35b39c5158Smillert 36b39c5158Smillertprint "1..197\n"; 37b39c5158Smillert 38b39c5158Smillertunlink glob "__db.*"; 39b39c5158Smillert 40b39c5158Smillertsub ok 41b39c5158Smillert{ 42b39c5158Smillert my $no = shift ; 43b39c5158Smillert my $result = shift ; 44b39c5158Smillert 45b39c5158Smillert print "not " unless $result ; 46b39c5158Smillert print "ok $no\n" ; 47b39c5158Smillert} 48b39c5158Smillert 49b39c5158Smillertsub lexical 50b39c5158Smillert{ 51b39c5158Smillert my(@a) = unpack ("C*", $a) ; 52b39c5158Smillert my(@b) = unpack ("C*", $b) ; 53b39c5158Smillert 54b39c5158Smillert my $len = (@a > @b ? @b : @a) ; 55b39c5158Smillert my $i = 0 ; 56b39c5158Smillert 57b39c5158Smillert foreach $i ( 0 .. $len -1) { 58b39c5158Smillert return $a[$i] - $b[$i] if $a[$i] != $b[$i] ; 59b39c5158Smillert } 60b39c5158Smillert 61b39c5158Smillert return @a - @b ; 62b39c5158Smillert} 63b39c5158Smillert 64b39c5158Smillert{ 65b39c5158Smillert package Redirect ; 66b39c5158Smillert use Symbol ; 67b39c5158Smillert 68b39c5158Smillert sub new 69b39c5158Smillert { 70b39c5158Smillert my $class = shift ; 71b39c5158Smillert my $filename = shift ; 72b39c5158Smillert my $fh = gensym ; 73b39c5158Smillert open ($fh, ">$filename") || die "Cannot open $filename: $!" ; 74b39c5158Smillert my $real_stdout = select($fh) ; 75b39c5158Smillert return bless [$fh, $real_stdout ] ; 76b39c5158Smillert 77b39c5158Smillert } 78b39c5158Smillert sub DESTROY 79b39c5158Smillert { 80b39c5158Smillert my $self = shift ; 81b39c5158Smillert close $self->[0] ; 82b39c5158Smillert select($self->[1]) ; 83b39c5158Smillert } 84b39c5158Smillert} 85b39c5158Smillert 86b39c5158Smillertsub docat 87b39c5158Smillert{ 88b39c5158Smillert my $file = shift; 89b39c5158Smillert local $/ = undef ; 90b39c5158Smillert open(CAT,$file) || die "Cannot open $file: $!"; 91b39c5158Smillert my $result = <CAT>; 92b39c5158Smillert close(CAT); 93b39c5158Smillert $result = normalise($result) ; 94b39c5158Smillert return $result ; 95b39c5158Smillert} 96b39c5158Smillert 97b39c5158Smillertsub docat_del 98b39c5158Smillert{ 99b39c5158Smillert my $file = shift; 100b39c5158Smillert my $result = docat($file); 101b39c5158Smillert unlink $file ; 102b39c5158Smillert return $result ; 103b39c5158Smillert} 104b39c5158Smillert 105b39c5158Smillertsub normalise 106b39c5158Smillert{ 107b39c5158Smillert my $data = shift ; 108b39c5158Smillert $data =~ s#\r\n#\n#g 109b39c5158Smillert if $^O eq 'cygwin' ; 110b39c5158Smillert 111b39c5158Smillert return $data ; 112b39c5158Smillert} 113b39c5158Smillert 114b39c5158Smillertsub safeUntie 115b39c5158Smillert{ 116b39c5158Smillert my $hashref = shift ; 117b39c5158Smillert my $no_inner = 1; 118b39c5158Smillert local $SIG{__WARN__} = sub {-- $no_inner } ; 119b39c5158Smillert untie %$hashref; 120b39c5158Smillert return $no_inner; 121b39c5158Smillert} 122b39c5158Smillert 123b39c5158Smillert 124b39c5158Smillert 125b39c5158Smillertmy $db185mode = ($DB_File::db_version == 1 && ! $DB_File::db_185_compat) ; 126b39c5158Smillertmy $null_keys_allowed = ($DB_File::db_ver < 2.004010 127b39c5158Smillert || $DB_File::db_ver >= 3.1 ); 128b39c5158Smillert 129f3efcd01Safresh1my $TEMPDIR = tempdir( CLEANUP => 1 ); 130f3efcd01Safresh1chdir $TEMPDIR; 131f3efcd01Safresh1 132b39c5158Smillertmy $Dfile = "dbbtree.tmp"; 133b39c5158Smillertunlink $Dfile; 134b39c5158Smillert 135b39c5158Smillertumask(0); 136b39c5158Smillert 137b39c5158Smillert# Check the interface to BTREEINFO 138b39c5158Smillert 139*256a93a4Safresh1my $dbh = DB_File::BTREEINFO->new(); 140b39c5158Smillertok(1, ! defined $dbh->{flags}) ; 141b39c5158Smillertok(2, ! defined $dbh->{cachesize}) ; 142b39c5158Smillertok(3, ! defined $dbh->{psize}) ; 143b39c5158Smillertok(4, ! defined $dbh->{lorder}) ; 144b39c5158Smillertok(5, ! defined $dbh->{minkeypage}) ; 145b39c5158Smillertok(6, ! defined $dbh->{maxkeypage}) ; 146b39c5158Smillertok(7, ! defined $dbh->{compare}) ; 147b39c5158Smillertok(8, ! defined $dbh->{prefix}) ; 148b39c5158Smillert 149b39c5158Smillert$dbh->{flags} = 3000 ; 150b39c5158Smillertok(9, $dbh->{flags} == 3000) ; 151b39c5158Smillert 152b39c5158Smillert$dbh->{cachesize} = 9000 ; 153b39c5158Smillertok(10, $dbh->{cachesize} == 9000); 154b39c5158Smillert 155b39c5158Smillert$dbh->{psize} = 400 ; 156b39c5158Smillertok(11, $dbh->{psize} == 400) ; 157b39c5158Smillert 158b39c5158Smillert$dbh->{lorder} = 65 ; 159b39c5158Smillertok(12, $dbh->{lorder} == 65) ; 160b39c5158Smillert 161b39c5158Smillert$dbh->{minkeypage} = 123 ; 162b39c5158Smillertok(13, $dbh->{minkeypage} == 123) ; 163b39c5158Smillert 164b39c5158Smillert$dbh->{maxkeypage} = 1234 ; 165b39c5158Smillertok(14, $dbh->{maxkeypage} == 1234 ); 166b39c5158Smillert 167b39c5158Smillert# Check that an invalid entry is caught both for store & fetch 168b39c5158Smillerteval '$dbh->{fred} = 1234' ; 169b39c5158Smillertok(15, $@ =~ /^DB_File::BTREEINFO::STORE - Unknown element 'fred' at/ ) ; 170b39c5158Smillerteval 'my $q = $dbh->{fred}' ; 171b39c5158Smillertok(16, $@ =~ /^DB_File::BTREEINFO::FETCH - Unknown element 'fred' at/ ) ; 172b39c5158Smillert 173b39c5158Smillert# Now check the interface to BTREE 174b39c5158Smillert 175b39c5158Smillertmy ($X, %h) ; 176b39c5158Smillertok(17, $X = tie(%h, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE )) ; 177b39c5158Smillertdie "Could not tie: $!" unless $X; 178b39c5158Smillert 179b39c5158Smillertmy ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, 180b39c5158Smillert $blksize,$blocks) = stat($Dfile); 181b39c5158Smillert 182b39c5158Smillertmy %noMode = map { $_, 1} qw( amigaos MSWin32 NetWare cygwin ) ; 183b39c5158Smillert 184b39c5158Smillertok(18, ($mode & 0777) == (($^O eq 'os2' || $^O eq 'MacOS') ? 0666 : 0640) 185b39c5158Smillert || $noMode{$^O} ); 186b39c5158Smillert 187b39c5158Smillertmy ($key, $value, $i); 188b39c5158Smillertwhile (($key,$value) = each(%h)) { 189b39c5158Smillert $i++; 190b39c5158Smillert} 191b39c5158Smillertok(19, !$i ) ; 192b39c5158Smillert 193b39c5158Smillert$h{'goner1'} = 'snork'; 194b39c5158Smillert 195b39c5158Smillert$h{'abc'} = 'ABC'; 196b39c5158Smillertok(20, $h{'abc'} eq 'ABC' ); 197b39c5158Smillertok(21, ! defined $h{'jimmy'} ) ; 198b39c5158Smillertok(22, ! exists $h{'jimmy'} ) ; 199b39c5158Smillertok(23, defined $h{'abc'} ) ; 200b39c5158Smillert 201b39c5158Smillert$h{'def'} = 'DEF'; 202b39c5158Smillert$h{'jkl','mno'} = "JKL\034MNO"; 203b39c5158Smillert$h{'a',2,3,4,5} = join("\034",'A',2,3,4,5); 204b39c5158Smillert$h{'a'} = 'A'; 205b39c5158Smillert 206b39c5158Smillert#$h{'b'} = 'B'; 207b39c5158Smillert$X->STORE('b', 'B') ; 208b39c5158Smillert 209b39c5158Smillert$h{'c'} = 'C'; 210b39c5158Smillert 211b39c5158Smillert#$h{'d'} = 'D'; 212b39c5158Smillert$X->put('d', 'D') ; 213b39c5158Smillert 214b39c5158Smillert$h{'e'} = 'E'; 215b39c5158Smillert$h{'f'} = 'F'; 216b39c5158Smillert$h{'g'} = 'X'; 217b39c5158Smillert$h{'h'} = 'H'; 218b39c5158Smillert$h{'i'} = 'I'; 219b39c5158Smillert 220b39c5158Smillert$h{'goner2'} = 'snork'; 221b39c5158Smillertdelete $h{'goner2'}; 222b39c5158Smillert 223b39c5158Smillert 224b39c5158Smillert# IMPORTANT - $X must be undefined before the untie otherwise the 225b39c5158Smillert# underlying DB close routine will not get called. 226b39c5158Smillertundef $X ; 227b39c5158Smillertuntie(%h); 228b39c5158Smillert 229b39c5158Smillert# tie to the same file again 230b39c5158Smillertok(24, $X = tie(%h,'DB_File',$Dfile, O_RDWR, 0640, $DB_BTREE)) ; 231b39c5158Smillert 232b39c5158Smillert# Modify an entry from the previous tie 233b39c5158Smillert$h{'g'} = 'G'; 234b39c5158Smillert 235b39c5158Smillert$h{'j'} = 'J'; 236b39c5158Smillert$h{'k'} = 'K'; 237b39c5158Smillert$h{'l'} = 'L'; 238b39c5158Smillert$h{'m'} = 'M'; 239b39c5158Smillert$h{'n'} = 'N'; 240b39c5158Smillert$h{'o'} = 'O'; 241b39c5158Smillert$h{'p'} = 'P'; 242b39c5158Smillert$h{'q'} = 'Q'; 243b39c5158Smillert$h{'r'} = 'R'; 244b39c5158Smillert$h{'s'} = 'S'; 245b39c5158Smillert$h{'t'} = 'T'; 246b39c5158Smillert$h{'u'} = 'U'; 247b39c5158Smillert$h{'v'} = 'V'; 248b39c5158Smillert$h{'w'} = 'W'; 249b39c5158Smillert$h{'x'} = 'X'; 250b39c5158Smillert$h{'y'} = 'Y'; 251b39c5158Smillert$h{'z'} = 'Z'; 252b39c5158Smillert 253b39c5158Smillert$h{'goner3'} = 'snork'; 254b39c5158Smillert 255b39c5158Smillertdelete $h{'goner1'}; 256b39c5158Smillert$X->DELETE('goner3'); 257b39c5158Smillert 258b39c5158Smillertmy @keys = keys(%h); 259b39c5158Smillertmy @values = values(%h); 260b39c5158Smillert 261b39c5158Smillertok(25, $#keys == 29 && $#values == 29) ; 262b39c5158Smillert 263b39c5158Smillert$i = 0 ; 264b39c5158Smillertwhile (($key,$value) = each(%h)) { 265b39c5158Smillert if ($key eq $keys[$i] && $value eq $values[$i] && $key eq lc($value)) { 266b39c5158Smillert $key =~ y/a-z/A-Z/; 267b39c5158Smillert $i++ if $key eq $value; 268b39c5158Smillert } 269b39c5158Smillert} 270b39c5158Smillert 271b39c5158Smillertok(26, $i == 30) ; 272b39c5158Smillert 273b39c5158Smillert@keys = ('blurfl', keys(%h), 'dyick'); 274b39c5158Smillertok(27, $#keys == 31) ; 275b39c5158Smillert 276b39c5158Smillert#Check that the keys can be retrieved in order 277b39c5158Smillertmy @b = keys %h ; 278b39c5158Smillertmy @c = sort lexical @b ; 279b39c5158Smillertok(28, ArrayCompare(\@b, \@c)) ; 280b39c5158Smillert 281b39c5158Smillert$h{'foo'} = ''; 282b39c5158Smillertok(29, $h{'foo'} eq '' ) ; 283b39c5158Smillert 284b39c5158Smillert# Berkeley DB from version 2.4.10 to 3.0 does not allow null keys. 285b39c5158Smillert# This feature was reenabled in version 3.1 of Berkeley DB. 286b39c5158Smillertmy $result = 0 ; 287b39c5158Smillertif ($null_keys_allowed) { 288b39c5158Smillert $h{''} = 'bar'; 289b39c5158Smillert $result = ( $h{''} eq 'bar' ); 290b39c5158Smillert} 291b39c5158Smillertelse 292b39c5158Smillert { $result = 1 } 293b39c5158Smillertok(30, $result) ; 294b39c5158Smillert 295b39c5158Smillert# check cache overflow and numeric keys and contents 296b39c5158Smillertmy $ok = 1; 297b39c5158Smillertfor ($i = 1; $i < 200; $i++) { $h{$i + 0} = $i + 0; } 298b39c5158Smillertfor ($i = 1; $i < 200; $i++) { $ok = 0 unless $h{$i} == $i; } 299b39c5158Smillertok(31, $ok); 300b39c5158Smillert 301b39c5158Smillert($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, 302b39c5158Smillert $blksize,$blocks) = stat($Dfile); 303b39c5158Smillertok(32, $size > 0 ); 304b39c5158Smillert 305b39c5158Smillert@h{0..200} = 200..400; 306b39c5158Smillertmy @foo = @h{0..200}; 307b39c5158Smillertok(33, join(':',200..400) eq join(':',@foo) ); 308b39c5158Smillert 309b39c5158Smillert# Now check all the non-tie specific stuff 310b39c5158Smillert 311b39c5158Smillert 312b39c5158Smillert# Check R_NOOVERWRITE flag will make put fail when attempting to overwrite 313b39c5158Smillert# an existing record. 314b39c5158Smillert 315b39c5158Smillertmy $status = $X->put( 'x', 'newvalue', R_NOOVERWRITE) ; 316b39c5158Smillertok(34, $status == 1 ); 317b39c5158Smillert 318b39c5158Smillert# check that the value of the key 'x' has not been changed by the 319b39c5158Smillert# previous test 320b39c5158Smillertok(35, $h{'x'} eq 'X' ); 321b39c5158Smillert 322b39c5158Smillert# standard put 323b39c5158Smillert$status = $X->put('key', 'value') ; 324b39c5158Smillertok(36, $status == 0 ); 325b39c5158Smillert 326b39c5158Smillert#check that previous put can be retrieved 327b39c5158Smillert$value = 0 ; 328b39c5158Smillert$status = $X->get('key', $value) ; 329b39c5158Smillertok(37, $status == 0 ); 330b39c5158Smillertok(38, $value eq 'value' ); 331b39c5158Smillert 332b39c5158Smillert# Attempting to delete an existing key should work 333b39c5158Smillert 334b39c5158Smillert$status = $X->del('q') ; 335b39c5158Smillertok(39, $status == 0 ); 336b39c5158Smillertif ($null_keys_allowed) { 337b39c5158Smillert $status = $X->del('') ; 338b39c5158Smillert} else { 339b39c5158Smillert $status = 0 ; 340b39c5158Smillert} 341b39c5158Smillertok(40, $status == 0 ); 342b39c5158Smillert 343b39c5158Smillert# Make sure that the key deleted, cannot be retrieved 344b39c5158Smillertok(41, ! defined $h{'q'}) ; 345b39c5158Smillertok(42, ! defined $h{''}) ; 346b39c5158Smillert 347b39c5158Smillertundef $X ; 348b39c5158Smillertuntie %h ; 349b39c5158Smillert 350b39c5158Smillertok(43, $X = tie(%h, 'DB_File',$Dfile, O_RDWR, 0640, $DB_BTREE )); 351b39c5158Smillert 352898184e3Ssthen# Attempting to delete a non-existent key should fail 353b39c5158Smillert 354b39c5158Smillert$status = $X->del('joe') ; 355b39c5158Smillertok(44, $status == 1 ); 356b39c5158Smillert 357b39c5158Smillert# Check the get interface 358b39c5158Smillert 359b39c5158Smillert# First a non-existing key 360b39c5158Smillert$status = $X->get('aaaa', $value) ; 361b39c5158Smillertok(45, $status == 1 ); 362b39c5158Smillert 363b39c5158Smillert# Next an existing key 364b39c5158Smillert$status = $X->get('a', $value) ; 365b39c5158Smillertok(46, $status == 0 ); 366b39c5158Smillertok(47, $value eq 'A' ); 367b39c5158Smillert 368b39c5158Smillert# seq 369b39c5158Smillert# ### 370b39c5158Smillert 371b39c5158Smillert# use seq to find an approximate match 372b39c5158Smillert$key = 'ke' ; 373b39c5158Smillert$value = '' ; 374b39c5158Smillert$status = $X->seq($key, $value, R_CURSOR) ; 375b39c5158Smillertok(48, $status == 0 ); 376b39c5158Smillertok(49, $key eq 'key' ); 377b39c5158Smillertok(50, $value eq 'value' ); 378b39c5158Smillert 379b39c5158Smillert# seq when the key does not match 380b39c5158Smillert$key = 'zzz' ; 381b39c5158Smillert$value = '' ; 382b39c5158Smillert$status = $X->seq($key, $value, R_CURSOR) ; 383b39c5158Smillertok(51, $status == 1 ); 384b39c5158Smillert 385b39c5158Smillert 386b39c5158Smillert# use seq to set the cursor, then delete the record @ the cursor. 387b39c5158Smillert 388b39c5158Smillert$key = 'x' ; 389b39c5158Smillert$value = '' ; 390b39c5158Smillert$status = $X->seq($key, $value, R_CURSOR) ; 391b39c5158Smillertok(52, $status == 0 ); 392b39c5158Smillertok(53, $key eq 'x' ); 393b39c5158Smillertok(54, $value eq 'X' ); 394b39c5158Smillert$status = $X->del(0, R_CURSOR) ; 395b39c5158Smillertok(55, $status == 0 ); 396b39c5158Smillert$status = $X->get('x', $value) ; 397b39c5158Smillertok(56, $status == 1 ); 398b39c5158Smillert 399b39c5158Smillert# ditto, but use put to replace the key/value pair. 400b39c5158Smillert$key = 'y' ; 401b39c5158Smillert$value = '' ; 402b39c5158Smillert$status = $X->seq($key, $value, R_CURSOR) ; 403b39c5158Smillertok(57, $status == 0 ); 404b39c5158Smillertok(58, $key eq 'y' ); 405b39c5158Smillertok(59, $value eq 'Y' ); 406b39c5158Smillert 407b39c5158Smillert$key = "replace key" ; 408b39c5158Smillert$value = "replace value" ; 409b39c5158Smillert$status = $X->put($key, $value, R_CURSOR) ; 410b39c5158Smillertok(60, $status == 0 ); 411b39c5158Smillertok(61, $key eq 'replace key' ); 412b39c5158Smillertok(62, $value eq 'replace value' ); 413b39c5158Smillert$status = $X->get('y', $value) ; 414b39c5158Smillertok(63, 1) ; # hard-wire to always pass. the previous test ($status == 1) 415b39c5158Smillert # only worked because of a bug in 1.85/6 416b39c5158Smillert 417b39c5158Smillert# use seq to walk forwards through a file 418b39c5158Smillert 419b39c5158Smillert$status = $X->seq($key, $value, R_FIRST) ; 420b39c5158Smillertok(64, $status == 0 ); 421b39c5158Smillertmy $previous = $key ; 422b39c5158Smillert 423b39c5158Smillert$ok = 1 ; 424b39c5158Smillertwhile (($status = $X->seq($key, $value, R_NEXT)) == 0) 425b39c5158Smillert{ 426b39c5158Smillert ($ok = 0), last if ($previous cmp $key) == 1 ; 427b39c5158Smillert} 428b39c5158Smillert 429b39c5158Smillertok(65, $status == 1 ); 430b39c5158Smillertok(66, $ok == 1 ); 431b39c5158Smillert 432b39c5158Smillert# use seq to walk backwards through a file 433b39c5158Smillert$status = $X->seq($key, $value, R_LAST) ; 434b39c5158Smillertok(67, $status == 0 ); 435b39c5158Smillert$previous = $key ; 436b39c5158Smillert 437b39c5158Smillert$ok = 1 ; 438b39c5158Smillertwhile (($status = $X->seq($key, $value, R_PREV)) == 0) 439b39c5158Smillert{ 440b39c5158Smillert ($ok = 0), last if ($previous cmp $key) == -1 ; 441b39c5158Smillert #print "key = [$key] value = [$value]\n" ; 442b39c5158Smillert} 443b39c5158Smillert 444b39c5158Smillertok(68, $status == 1 ); 445b39c5158Smillertok(69, $ok == 1 ); 446b39c5158Smillert 447b39c5158Smillert 448b39c5158Smillert# check seq FIRST/LAST 449b39c5158Smillert 450b39c5158Smillert# sync 451b39c5158Smillert# #### 452b39c5158Smillert 453b39c5158Smillert$status = $X->sync ; 454b39c5158Smillertok(70, $status == 0 ); 455b39c5158Smillert 456b39c5158Smillert 457b39c5158Smillert# fd 458b39c5158Smillert# ## 459b39c5158Smillert 460b39c5158Smillert$status = $X->fd ; 461b39c5158Smillertok(71, 1 ); 462b39c5158Smillert#ok(71, $status != 0 ); 463b39c5158Smillert 464b39c5158Smillert 465b39c5158Smillertundef $X ; 466b39c5158Smillertuntie %h ; 467b39c5158Smillert 468b39c5158Smillertunlink $Dfile; 469b39c5158Smillert 470b39c5158Smillert# Now try an in memory file 471b39c5158Smillertmy $Y; 472b39c5158Smillertok(72, $Y = tie(%h, 'DB_File',undef, O_RDWR|O_CREAT, 0640, $DB_BTREE )); 473b39c5158Smillert 474b39c5158Smillert# fd with an in memory file should return failure 475b39c5158Smillert$status = $Y->fd ; 476b39c5158Smillertok(73, $status == -1 ); 477b39c5158Smillert 478b39c5158Smillert 479b39c5158Smillertundef $Y ; 480b39c5158Smillertuntie %h ; 481b39c5158Smillert 482b39c5158Smillert# Duplicate keys 483*256a93a4Safresh1my $bt = DB_File::BTREEINFO->new(); 484b39c5158Smillert$bt->{flags} = R_DUP ; 485b39c5158Smillertmy ($YY, %hh); 486b39c5158Smillertok(74, $YY = tie(%hh, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $bt )) ; 487b39c5158Smillert 488b39c5158Smillert$hh{'Wall'} = 'Larry' ; 489b39c5158Smillert$hh{'Wall'} = 'Stone' ; # Note the duplicate key 490b39c5158Smillert$hh{'Wall'} = 'Brick' ; # Note the duplicate key 491b39c5158Smillert$hh{'Wall'} = 'Brick' ; # Note the duplicate key and value 492b39c5158Smillert$hh{'Smith'} = 'John' ; 493b39c5158Smillert$hh{'mouse'} = 'mickey' ; 494b39c5158Smillert 495b39c5158Smillert# first work in scalar context 496b39c5158Smillertok(75, scalar $YY->get_dup('Unknown') == 0 ); 497b39c5158Smillertok(76, scalar $YY->get_dup('Smith') == 1 ); 498b39c5158Smillertok(77, scalar $YY->get_dup('Wall') == 4 ); 499b39c5158Smillert 500b39c5158Smillert# now in list context 501b39c5158Smillertmy @unknown = $YY->get_dup('Unknown') ; 502b39c5158Smillertok(78, "@unknown" eq "" ); 503b39c5158Smillert 504b39c5158Smillertmy @smith = $YY->get_dup('Smith') ; 505b39c5158Smillertok(79, "@smith" eq "John" ); 506b39c5158Smillert 507b39c5158Smillert{ 508b39c5158Smillertmy @wall = $YY->get_dup('Wall') ; 509b39c5158Smillertmy %wall ; 510b39c5158Smillert@wall{@wall} = @wall ; 511b39c5158Smillertok(80, (@wall == 4 && $wall{'Larry'} && $wall{'Stone'} && $wall{'Brick'}) ); 512b39c5158Smillert} 513b39c5158Smillert 514b39c5158Smillert# hash 515b39c5158Smillertmy %unknown = $YY->get_dup('Unknown', 1) ; 516b39c5158Smillertok(81, keys %unknown == 0 ); 517b39c5158Smillert 518b39c5158Smillertmy %smith = $YY->get_dup('Smith', 1) ; 519b39c5158Smillertok(82, keys %smith == 1 && $smith{'John'}) ; 520b39c5158Smillert 521b39c5158Smillertmy %wall = $YY->get_dup('Wall', 1) ; 522b39c5158Smillertok(83, keys %wall == 3 && $wall{'Larry'} == 1 && $wall{'Stone'} == 1 523b39c5158Smillert && $wall{'Brick'} == 2); 524b39c5158Smillert 525b39c5158Smillertundef $YY ; 526b39c5158Smillertuntie %hh ; 527b39c5158Smillertunlink $Dfile; 528b39c5158Smillert 529b39c5158Smillert 530b39c5158Smillert# test multiple callbacks 531b39c5158Smillertmy $Dfile1 = "btree1" ; 532b39c5158Smillertmy $Dfile2 = "btree2" ; 533b39c5158Smillertmy $Dfile3 = "btree3" ; 534b39c5158Smillert 535*256a93a4Safresh1my $dbh1 = DB_File::BTREEINFO->new(); 536b39c5158Smillert$dbh1->{compare} = sub { 537b39c5158Smillert no warnings 'numeric' ; 538b39c5158Smillert $_[0] <=> $_[1] } ; 539b39c5158Smillert 540*256a93a4Safresh1my $dbh2 = DB_File::BTREEINFO->new(); 541b39c5158Smillert$dbh2->{compare} = sub { $_[0] cmp $_[1] } ; 542b39c5158Smillert 543*256a93a4Safresh1my $dbh3 = DB_File::BTREEINFO->new(); 544b39c5158Smillert$dbh3->{compare} = sub { length $_[0] <=> length $_[1] } ; 545b39c5158Smillert 546b39c5158Smillert 547b39c5158Smillertmy (%g, %k); 548b39c5158Smillerttie(%h, 'DB_File',$Dfile1, O_RDWR|O_CREAT, 0640, $dbh1 ) or die $!; 549b39c5158Smillerttie(%g, 'DB_File',$Dfile2, O_RDWR|O_CREAT, 0640, $dbh2 ) or die $!; 550b39c5158Smillerttie(%k, 'DB_File',$Dfile3, O_RDWR|O_CREAT, 0640, $dbh3 ) or die $!; 551b39c5158Smillert 552b39c5158Smillertmy @Keys = qw( 0123 12 -1234 9 987654321 def ) ; 553b39c5158Smillertmy (@srt_1, @srt_2, @srt_3); 554b39c5158Smillert{ 555b39c5158Smillert no warnings 'numeric' ; 556b39c5158Smillert @srt_1 = sort { $a <=> $b } @Keys ; 557b39c5158Smillert} 558b39c5158Smillert@srt_2 = sort { $a cmp $b } @Keys ; 559b39c5158Smillert@srt_3 = sort { length $a <=> length $b } @Keys ; 560b39c5158Smillert 561b39c5158Smillertforeach (@Keys) { 562b39c5158Smillert $h{$_} = 1 ; 563b39c5158Smillert $g{$_} = 1 ; 564b39c5158Smillert $k{$_} = 1 ; 565b39c5158Smillert} 566b39c5158Smillert 567b39c5158Smillertsub ArrayCompare 568b39c5158Smillert{ 569b39c5158Smillert my($a, $b) = @_ ; 570b39c5158Smillert 571b39c5158Smillert return 0 if @$a != @$b ; 572b39c5158Smillert 573898184e3Ssthen foreach (0 .. @$a - 1) 574b39c5158Smillert { 575b39c5158Smillert return 0 unless $$a[$_] eq $$b[$_]; 576b39c5158Smillert } 577b39c5158Smillert 578b39c5158Smillert 1 ; 579b39c5158Smillert} 580b39c5158Smillert 581b39c5158Smillertok(84, ArrayCompare (\@srt_1, [keys %h]) ); 582b39c5158Smillertok(85, ArrayCompare (\@srt_2, [keys %g]) ); 583b39c5158Smillertok(86, ArrayCompare (\@srt_3, [keys %k]) ); 584b39c5158Smillert 585b39c5158Smillertuntie %h ; 586b39c5158Smillertuntie %g ; 587b39c5158Smillertuntie %k ; 588b39c5158Smillertunlink $Dfile1, $Dfile2, $Dfile3 ; 589b39c5158Smillert 590b39c5158Smillert# clear 591b39c5158Smillert# ##### 592b39c5158Smillert 593b39c5158Smillertok(87, tie(%h, 'DB_File', $Dfile1, O_RDWR|O_CREAT, 0640, $DB_BTREE ) ); 594b39c5158Smillertforeach (1 .. 10) 595b39c5158Smillert { $h{$_} = $_ * 100 } 596b39c5158Smillert 597b39c5158Smillert# check that there are 10 elements in the hash 598b39c5158Smillert$i = 0 ; 599b39c5158Smillertwhile (($key,$value) = each(%h)) { 600b39c5158Smillert $i++; 601b39c5158Smillert} 602b39c5158Smillertok(88, $i == 10); 603b39c5158Smillert 604b39c5158Smillert# now clear the hash 605b39c5158Smillert%h = () ; 606b39c5158Smillert 607b39c5158Smillert# check it is empty 608b39c5158Smillert$i = 0 ; 609b39c5158Smillertwhile (($key,$value) = each(%h)) { 610b39c5158Smillert $i++; 611b39c5158Smillert} 612b39c5158Smillertok(89, $i == 0); 613b39c5158Smillert 614b39c5158Smillertuntie %h ; 615b39c5158Smillertunlink $Dfile1 ; 616b39c5158Smillert 617b39c5158Smillert{ 618b39c5158Smillert # check that attempting to tie an array to a DB_BTREE will fail 619b39c5158Smillert 620b39c5158Smillert my $filename = "xyz" ; 621b39c5158Smillert my @x ; 622b39c5158Smillert eval { tie @x, 'DB_File', $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE ; } ; 623b39c5158Smillert ok(90, $@ =~ /^DB_File can only tie an associative array to a DB_BTREE database/) ; 624b39c5158Smillert unlink $filename ; 625b39c5158Smillert} 626b39c5158Smillert 627b39c5158Smillert{ 628b39c5158Smillert # sub-class test 629b39c5158Smillert 630b39c5158Smillert package Another ; 631b39c5158Smillert 632b39c5158Smillert use warnings ; 633b39c5158Smillert use strict ; 634b39c5158Smillert 635b39c5158Smillert open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ; 636b39c5158Smillert print FILE <<'EOM' ; 637b39c5158Smillert 638b39c5158Smillert package SubDB ; 639b39c5158Smillert 640b39c5158Smillert use warnings ; 641b39c5158Smillert use strict ; 642b39c5158Smillert our (@ISA, @EXPORT); 643b39c5158Smillert 644b39c5158Smillert require Exporter ; 645b39c5158Smillert use DB_File; 646b39c5158Smillert @ISA=qw(DB_File); 647b39c5158Smillert @EXPORT = @DB_File::EXPORT ; 648b39c5158Smillert 649b39c5158Smillert sub STORE { 650b39c5158Smillert my $self = shift ; 651b39c5158Smillert my $key = shift ; 652b39c5158Smillert my $value = shift ; 653b39c5158Smillert $self->SUPER::STORE($key, $value * 2) ; 654b39c5158Smillert } 655b39c5158Smillert 656b39c5158Smillert sub FETCH { 657b39c5158Smillert my $self = shift ; 658b39c5158Smillert my $key = shift ; 659b39c5158Smillert $self->SUPER::FETCH($key) - 1 ; 660b39c5158Smillert } 661b39c5158Smillert 662b39c5158Smillert sub put { 663b39c5158Smillert my $self = shift ; 664b39c5158Smillert my $key = shift ; 665b39c5158Smillert my $value = shift ; 666b39c5158Smillert $self->SUPER::put($key, $value * 3) ; 667b39c5158Smillert } 668b39c5158Smillert 669b39c5158Smillert sub get { 670b39c5158Smillert my $self = shift ; 671b39c5158Smillert $self->SUPER::get($_[0], $_[1]) ; 672b39c5158Smillert $_[1] -= 2 ; 673b39c5158Smillert } 674b39c5158Smillert 675b39c5158Smillert sub A_new_method 676b39c5158Smillert { 677b39c5158Smillert my $self = shift ; 678b39c5158Smillert my $key = shift ; 679b39c5158Smillert my $value = $self->FETCH($key) ; 680b39c5158Smillert return "[[$value]]" ; 681b39c5158Smillert } 682b39c5158Smillert 683b39c5158Smillert 1 ; 684b39c5158SmillertEOM 685b39c5158Smillert 686b39c5158Smillert close FILE ; 687b39c5158Smillert 688b39c5158Smillert BEGIN { push @INC, '.'; } 689b39c5158Smillert eval 'use SubDB ; '; 690b39c5158Smillert main::ok(91, $@ eq "") ; 691b39c5158Smillert my %h ; 692b39c5158Smillert my $X ; 693b39c5158Smillert eval ' 694b39c5158Smillert $X = tie(%h, "SubDB","dbbtree.tmp", O_RDWR|O_CREAT, 0640, $DB_BTREE ); 695b39c5158Smillert ' ; 696b39c5158Smillert 697b39c5158Smillert main::ok(92, $@ eq "") ; 698b39c5158Smillert 699b39c5158Smillert my $ret = eval '$h{"fred"} = 3 ; return $h{"fred"} ' ; 700b39c5158Smillert main::ok(93, $@ eq "") ; 701b39c5158Smillert main::ok(94, $ret == 5) ; 702b39c5158Smillert 703b39c5158Smillert my $value = 0; 704b39c5158Smillert $ret = eval '$X->put("joe", 4) ; $X->get("joe", $value) ; return $value' ; 705b39c5158Smillert main::ok(95, $@ eq "") ; 706b39c5158Smillert main::ok(96, $ret == 10) ; 707b39c5158Smillert 708b39c5158Smillert $ret = eval ' R_NEXT eq main::R_NEXT ' ; 709b39c5158Smillert main::ok(97, $@ eq "" ) ; 710b39c5158Smillert main::ok(98, $ret == 1) ; 711b39c5158Smillert 712b39c5158Smillert $ret = eval '$X->A_new_method("joe") ' ; 713b39c5158Smillert main::ok(99, $@ eq "") ; 714b39c5158Smillert main::ok(100, $ret eq "[[11]]") ; 715b39c5158Smillert 716b39c5158Smillert undef $X; 717b39c5158Smillert untie(%h); 718b39c5158Smillert unlink "SubDB.pm", "dbbtree.tmp" ; 719b39c5158Smillert 720b39c5158Smillert} 721b39c5158Smillert 722b39c5158Smillert{ 723b39c5158Smillert # DBM Filter tests 724b39c5158Smillert use warnings ; 725b39c5158Smillert use strict ; 726b39c5158Smillert my (%h, $db) ; 727b39c5158Smillert my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 728b39c5158Smillert unlink $Dfile; 729b39c5158Smillert 730b39c5158Smillert sub checkOutput 731b39c5158Smillert { 732b39c5158Smillert my($fk, $sk, $fv, $sv) = @_ ; 733b39c5158Smillert return 734b39c5158Smillert $fetch_key eq $fk && $store_key eq $sk && 735b39c5158Smillert $fetch_value eq $fv && $store_value eq $sv && 736b39c5158Smillert $_ eq 'original' ; 737b39c5158Smillert } 738b39c5158Smillert 739b39c5158Smillert ok(101, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) ); 740b39c5158Smillert 741b39c5158Smillert $db->filter_fetch_key (sub { $fetch_key = $_ }) ; 742b39c5158Smillert $db->filter_store_key (sub { $store_key = $_ }) ; 743b39c5158Smillert $db->filter_fetch_value (sub { $fetch_value = $_}) ; 744b39c5158Smillert $db->filter_store_value (sub { $store_value = $_ }) ; 745b39c5158Smillert 746b39c5158Smillert $_ = "original" ; 747b39c5158Smillert 748b39c5158Smillert $h{"fred"} = "joe" ; 749b39c5158Smillert # fk sk fv sv 750b39c5158Smillert ok(102, checkOutput( "", "fred", "", "joe")) ; 751b39c5158Smillert 752b39c5158Smillert ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 753b39c5158Smillert ok(103, $h{"fred"} eq "joe"); 754b39c5158Smillert # fk sk fv sv 755b39c5158Smillert ok(104, checkOutput( "", "fred", "joe", "")) ; 756b39c5158Smillert 757b39c5158Smillert ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 758b39c5158Smillert ok(105, $db->FIRSTKEY() eq "fred") ; 759b39c5158Smillert # fk sk fv sv 760b39c5158Smillert ok(106, checkOutput( "fred", "", "", "")) ; 761b39c5158Smillert 762b39c5158Smillert # replace the filters, but remember the previous set 763b39c5158Smillert my ($old_fk) = $db->filter_fetch_key 764b39c5158Smillert (sub { $_ = uc $_ ; $fetch_key = $_ }) ; 765b39c5158Smillert my ($old_sk) = $db->filter_store_key 766b39c5158Smillert (sub { $_ = lc $_ ; $store_key = $_ }) ; 767b39c5158Smillert my ($old_fv) = $db->filter_fetch_value 768b39c5158Smillert (sub { $_ = "[$_]"; $fetch_value = $_ }) ; 769b39c5158Smillert my ($old_sv) = $db->filter_store_value 770b39c5158Smillert (sub { s/o/x/g; $store_value = $_ }) ; 771b39c5158Smillert 772b39c5158Smillert ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 773b39c5158Smillert $h{"Fred"} = "Joe" ; 774b39c5158Smillert # fk sk fv sv 775b39c5158Smillert ok(107, checkOutput( "", "fred", "", "Jxe")) ; 776b39c5158Smillert 777b39c5158Smillert ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 778b39c5158Smillert ok(108, $h{"Fred"} eq "[Jxe]"); 779b39c5158Smillert # fk sk fv sv 780b39c5158Smillert ok(109, checkOutput( "", "fred", "[Jxe]", "")) ; 781b39c5158Smillert 782b39c5158Smillert ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 783b39c5158Smillert ok(110, $db->FIRSTKEY() eq "FRED") ; 784b39c5158Smillert # fk sk fv sv 785b39c5158Smillert ok(111, checkOutput( "FRED", "", "", "")) ; 786b39c5158Smillert 787b39c5158Smillert # put the original filters back 788b39c5158Smillert $db->filter_fetch_key ($old_fk); 789b39c5158Smillert $db->filter_store_key ($old_sk); 790b39c5158Smillert $db->filter_fetch_value ($old_fv); 791b39c5158Smillert $db->filter_store_value ($old_sv); 792b39c5158Smillert 793b39c5158Smillert ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 794b39c5158Smillert $h{"fred"} = "joe" ; 795b39c5158Smillert ok(112, checkOutput( "", "fred", "", "joe")) ; 796b39c5158Smillert 797b39c5158Smillert ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 798b39c5158Smillert ok(113, $h{"fred"} eq "joe"); 799b39c5158Smillert ok(114, checkOutput( "", "fred", "joe", "")) ; 800b39c5158Smillert 801b39c5158Smillert ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 802b39c5158Smillert ok(115, $db->FIRSTKEY() eq "fred") ; 803b39c5158Smillert ok(116, checkOutput( "fred", "", "", "")) ; 804b39c5158Smillert 805b39c5158Smillert # delete the filters 806b39c5158Smillert $db->filter_fetch_key (undef); 807b39c5158Smillert $db->filter_store_key (undef); 808b39c5158Smillert $db->filter_fetch_value (undef); 809b39c5158Smillert $db->filter_store_value (undef); 810b39c5158Smillert 811b39c5158Smillert ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 812b39c5158Smillert $h{"fred"} = "joe" ; 813b39c5158Smillert ok(117, checkOutput( "", "", "", "")) ; 814b39c5158Smillert 815b39c5158Smillert ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 816b39c5158Smillert ok(118, $h{"fred"} eq "joe"); 817b39c5158Smillert ok(119, checkOutput( "", "", "", "")) ; 818b39c5158Smillert 819b39c5158Smillert ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 820b39c5158Smillert ok(120, $db->FIRSTKEY() eq "fred") ; 821b39c5158Smillert ok(121, checkOutput( "", "", "", "")) ; 822b39c5158Smillert 823b39c5158Smillert undef $db ; 824b39c5158Smillert untie %h; 825b39c5158Smillert unlink $Dfile; 826b39c5158Smillert} 827b39c5158Smillert 828b39c5158Smillert{ 829b39c5158Smillert # DBM Filter with a closure 830b39c5158Smillert 831b39c5158Smillert use warnings ; 832b39c5158Smillert use strict ; 833b39c5158Smillert my (%h, $db) ; 834b39c5158Smillert 835b39c5158Smillert unlink $Dfile; 836b39c5158Smillert ok(122, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) ); 837b39c5158Smillert 838b39c5158Smillert my %result = () ; 839b39c5158Smillert 840b39c5158Smillert sub Closure 841b39c5158Smillert { 842b39c5158Smillert my ($name) = @_ ; 843b39c5158Smillert my $count = 0 ; 844b39c5158Smillert my @kept = () ; 845b39c5158Smillert 846b39c5158Smillert return sub { ++$count ; 847b39c5158Smillert push @kept, $_ ; 848b39c5158Smillert $result{$name} = "$name - $count: [@kept]" ; 849b39c5158Smillert } 850b39c5158Smillert } 851b39c5158Smillert 852b39c5158Smillert $db->filter_store_key(Closure("store key")) ; 853b39c5158Smillert $db->filter_store_value(Closure("store value")) ; 854b39c5158Smillert $db->filter_fetch_key(Closure("fetch key")) ; 855b39c5158Smillert $db->filter_fetch_value(Closure("fetch value")) ; 856b39c5158Smillert 857b39c5158Smillert $_ = "original" ; 858b39c5158Smillert 859b39c5158Smillert $h{"fred"} = "joe" ; 860b39c5158Smillert ok(123, $result{"store key"} eq "store key - 1: [fred]"); 861b39c5158Smillert ok(124, $result{"store value"} eq "store value - 1: [joe]"); 862b39c5158Smillert ok(125, ! defined $result{"fetch key"} ); 863b39c5158Smillert ok(126, ! defined $result{"fetch value"} ); 864b39c5158Smillert ok(127, $_ eq "original") ; 865b39c5158Smillert 866b39c5158Smillert ok(128, $db->FIRSTKEY() eq "fred") ; 867b39c5158Smillert ok(129, $result{"store key"} eq "store key - 1: [fred]"); 868b39c5158Smillert ok(130, $result{"store value"} eq "store value - 1: [joe]"); 869b39c5158Smillert ok(131, $result{"fetch key"} eq "fetch key - 1: [fred]"); 870b39c5158Smillert ok(132, ! defined $result{"fetch value"} ); 871b39c5158Smillert ok(133, $_ eq "original") ; 872b39c5158Smillert 873b39c5158Smillert $h{"jim"} = "john" ; 874b39c5158Smillert ok(134, $result{"store key"} eq "store key - 2: [fred jim]"); 875b39c5158Smillert ok(135, $result{"store value"} eq "store value - 2: [joe john]"); 876b39c5158Smillert ok(136, $result{"fetch key"} eq "fetch key - 1: [fred]"); 877b39c5158Smillert ok(137, ! defined $result{"fetch value"} ); 878b39c5158Smillert ok(138, $_ eq "original") ; 879b39c5158Smillert 880b39c5158Smillert ok(139, $h{"fred"} eq "joe"); 881b39c5158Smillert ok(140, $result{"store key"} eq "store key - 3: [fred jim fred]"); 882b39c5158Smillert ok(141, $result{"store value"} eq "store value - 2: [joe john]"); 883b39c5158Smillert ok(142, $result{"fetch key"} eq "fetch key - 1: [fred]"); 884b39c5158Smillert ok(143, $result{"fetch value"} eq "fetch value - 1: [joe]"); 885b39c5158Smillert ok(144, $_ eq "original") ; 886b39c5158Smillert 887b39c5158Smillert undef $db ; 888b39c5158Smillert untie %h; 889b39c5158Smillert unlink $Dfile; 890b39c5158Smillert} 891b39c5158Smillert 892b39c5158Smillert{ 893b39c5158Smillert # DBM Filter recursion detection 894b39c5158Smillert use warnings ; 895b39c5158Smillert use strict ; 896b39c5158Smillert my (%h, $db) ; 897b39c5158Smillert unlink $Dfile; 898b39c5158Smillert 899b39c5158Smillert ok(145, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) ); 900b39c5158Smillert 901b39c5158Smillert $db->filter_store_key (sub { $_ = $h{$_} }) ; 902b39c5158Smillert 903b39c5158Smillert eval '$h{1} = 1234' ; 904b39c5158Smillert ok(146, $@ =~ /^recursion detected in filter_store_key at/ ); 905b39c5158Smillert 906b39c5158Smillert undef $db ; 907b39c5158Smillert untie %h; 908b39c5158Smillert unlink $Dfile; 909b39c5158Smillert} 910b39c5158Smillert 911b39c5158Smillert 912b39c5158Smillert{ 913b39c5158Smillert # Examples from the POD 914b39c5158Smillert 915b39c5158Smillert 916b39c5158Smillert my $file = "xyzt" ; 917b39c5158Smillert { 918*256a93a4Safresh1 my $redirect = Redirect->new( $file ); 919b39c5158Smillert 920b39c5158Smillert # BTREE example 1 921b39c5158Smillert ### 922b39c5158Smillert 923b39c5158Smillert use warnings FATAL => qw(all) ; 924b39c5158Smillert use strict ; 925b39c5158Smillert use DB_File ; 926b39c5158Smillert 927b39c5158Smillert my %h ; 928b39c5158Smillert 929b39c5158Smillert sub Compare 930b39c5158Smillert { 931b39c5158Smillert my ($key1, $key2) = @_ ; 932b39c5158Smillert "\L$key1" cmp "\L$key2" ; 933b39c5158Smillert } 934b39c5158Smillert 935b39c5158Smillert # specify the Perl sub that will do the comparison 936b39c5158Smillert $DB_BTREE->{'compare'} = \&Compare ; 937b39c5158Smillert 938b39c5158Smillert unlink "tree" ; 939b39c5158Smillert tie %h, "DB_File", "tree", O_RDWR|O_CREAT, 0640, $DB_BTREE 940b39c5158Smillert or die "Cannot open file 'tree': $!\n" ; 941b39c5158Smillert 942b39c5158Smillert # Add a key/value pair to the file 943b39c5158Smillert $h{'Wall'} = 'Larry' ; 944b39c5158Smillert $h{'Smith'} = 'John' ; 945b39c5158Smillert $h{'mouse'} = 'mickey' ; 946b39c5158Smillert $h{'duck'} = 'donald' ; 947b39c5158Smillert 948b39c5158Smillert # Delete 949b39c5158Smillert delete $h{"duck"} ; 950b39c5158Smillert 951b39c5158Smillert # Cycle through the keys printing them in order. 952b39c5158Smillert # Note it is not necessary to sort the keys as 953b39c5158Smillert # the btree will have kept them in order automatically. 954b39c5158Smillert foreach (keys %h) 955b39c5158Smillert { print "$_\n" } 956b39c5158Smillert 957b39c5158Smillert untie %h ; 958b39c5158Smillert 959b39c5158Smillert unlink "tree" ; 960b39c5158Smillert } 961b39c5158Smillert 962b39c5158Smillert delete $DB_BTREE->{'compare'} ; 963b39c5158Smillert 964b39c5158Smillert ok(147, docat_del($file) eq <<'EOM') ; 965b39c5158Smillertmouse 966b39c5158SmillertSmith 967b39c5158SmillertWall 968b39c5158SmillertEOM 969b39c5158Smillert 970b39c5158Smillert { 971*256a93a4Safresh1 my $redirect = Redirect->new( $file ); 972b39c5158Smillert 973b39c5158Smillert # BTREE example 2 974b39c5158Smillert ### 975b39c5158Smillert 976b39c5158Smillert use warnings FATAL => qw(all) ; 977b39c5158Smillert use strict ; 978b39c5158Smillert use DB_File ; 979b39c5158Smillert 980b39c5158Smillert my ($filename, %h); 981b39c5158Smillert 982b39c5158Smillert $filename = "tree" ; 983b39c5158Smillert unlink $filename ; 984b39c5158Smillert 985b39c5158Smillert # Enable duplicate records 986b39c5158Smillert $DB_BTREE->{'flags'} = R_DUP ; 987b39c5158Smillert 988b39c5158Smillert tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE 989b39c5158Smillert or die "Cannot open $filename: $!\n"; 990b39c5158Smillert 991b39c5158Smillert # Add some key/value pairs to the file 992b39c5158Smillert $h{'Wall'} = 'Larry' ; 993b39c5158Smillert $h{'Wall'} = 'Brick' ; # Note the duplicate key 994b39c5158Smillert $h{'Wall'} = 'Brick' ; # Note the duplicate key and value 995b39c5158Smillert $h{'Smith'} = 'John' ; 996b39c5158Smillert $h{'mouse'} = 'mickey' ; 997b39c5158Smillert 998b39c5158Smillert # iterate through the associative array 999b39c5158Smillert # and print each key/value pair. 1000b39c5158Smillert foreach (keys %h) 1001b39c5158Smillert { print "$_ -> $h{$_}\n" } 1002b39c5158Smillert 1003b39c5158Smillert untie %h ; 1004b39c5158Smillert 1005b39c5158Smillert unlink $filename ; 1006b39c5158Smillert } 1007b39c5158Smillert 1008b39c5158Smillert ok(148, docat_del($file) eq ($db185mode ? <<'EOM' : <<'EOM') ) ; 1009b39c5158SmillertSmith -> John 1010b39c5158SmillertWall -> Brick 1011b39c5158SmillertWall -> Brick 1012b39c5158SmillertWall -> Brick 1013b39c5158Smillertmouse -> mickey 1014b39c5158SmillertEOM 1015b39c5158SmillertSmith -> John 1016b39c5158SmillertWall -> Larry 1017b39c5158SmillertWall -> Larry 1018b39c5158SmillertWall -> Larry 1019b39c5158Smillertmouse -> mickey 1020b39c5158SmillertEOM 1021b39c5158Smillert 1022b39c5158Smillert { 1023*256a93a4Safresh1 my $redirect = Redirect->new( $file ); 1024b39c5158Smillert 1025b39c5158Smillert # BTREE example 3 1026b39c5158Smillert ### 1027b39c5158Smillert 1028b39c5158Smillert use warnings FATAL => qw(all) ; 1029b39c5158Smillert use strict ; 1030b39c5158Smillert use DB_File ; 1031b39c5158Smillert 1032b39c5158Smillert my ($filename, $x, %h, $status, $key, $value); 1033b39c5158Smillert 1034b39c5158Smillert $filename = "tree" ; 1035b39c5158Smillert unlink $filename ; 1036b39c5158Smillert 1037b39c5158Smillert # Enable duplicate records 1038b39c5158Smillert $DB_BTREE->{'flags'} = R_DUP ; 1039b39c5158Smillert 1040b39c5158Smillert $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE 1041b39c5158Smillert or die "Cannot open $filename: $!\n"; 1042b39c5158Smillert 1043b39c5158Smillert # Add some key/value pairs to the file 1044b39c5158Smillert $h{'Wall'} = 'Larry' ; 1045b39c5158Smillert $h{'Wall'} = 'Brick' ; # Note the duplicate key 1046b39c5158Smillert $h{'Wall'} = 'Brick' ; # Note the duplicate key and value 1047b39c5158Smillert $h{'Smith'} = 'John' ; 1048b39c5158Smillert $h{'mouse'} = 'mickey' ; 1049b39c5158Smillert 1050b39c5158Smillert # iterate through the btree using seq 1051b39c5158Smillert # and print each key/value pair. 1052b39c5158Smillert $key = $value = 0 ; 1053b39c5158Smillert for ($status = $x->seq($key, $value, R_FIRST) ; 1054b39c5158Smillert $status == 0 ; 1055b39c5158Smillert $status = $x->seq($key, $value, R_NEXT) ) 1056b39c5158Smillert { print "$key -> $value\n" } 1057b39c5158Smillert 1058b39c5158Smillert 1059b39c5158Smillert undef $x ; 1060b39c5158Smillert untie %h ; 1061b39c5158Smillert } 1062b39c5158Smillert 1063b39c5158Smillert ok(149, docat_del($file) eq ($db185mode == 1 ? <<'EOM' : <<'EOM') ) ; 1064b39c5158SmillertSmith -> John 1065b39c5158SmillertWall -> Brick 1066b39c5158SmillertWall -> Brick 1067b39c5158SmillertWall -> Larry 1068b39c5158Smillertmouse -> mickey 1069b39c5158SmillertEOM 1070b39c5158SmillertSmith -> John 1071b39c5158SmillertWall -> Larry 1072b39c5158SmillertWall -> Brick 1073b39c5158SmillertWall -> Brick 1074b39c5158Smillertmouse -> mickey 1075b39c5158SmillertEOM 1076b39c5158Smillert 1077b39c5158Smillert 1078b39c5158Smillert { 1079*256a93a4Safresh1 my $redirect = Redirect->new( $file ); 1080b39c5158Smillert 1081b39c5158Smillert # BTREE example 4 1082b39c5158Smillert ### 1083b39c5158Smillert 1084b39c5158Smillert use warnings FATAL => qw(all) ; 1085b39c5158Smillert use strict ; 1086b39c5158Smillert use DB_File ; 1087b39c5158Smillert 1088b39c5158Smillert my ($filename, $x, %h); 1089b39c5158Smillert 1090b39c5158Smillert $filename = "tree" ; 1091b39c5158Smillert 1092b39c5158Smillert # Enable duplicate records 1093b39c5158Smillert $DB_BTREE->{'flags'} = R_DUP ; 1094b39c5158Smillert 1095b39c5158Smillert $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE 1096b39c5158Smillert or die "Cannot open $filename: $!\n"; 1097b39c5158Smillert 1098b39c5158Smillert my $cnt = $x->get_dup("Wall") ; 1099b39c5158Smillert print "Wall occurred $cnt times\n" ; 1100b39c5158Smillert 1101b39c5158Smillert my %hash = $x->get_dup("Wall", 1) ; 1102b39c5158Smillert print "Larry is there\n" if $hash{'Larry'} ; 1103b39c5158Smillert print "There are $hash{'Brick'} Brick Walls\n" ; 1104b39c5158Smillert 1105b39c5158Smillert my @list = sort $x->get_dup("Wall") ; 1106b39c5158Smillert print "Wall => [@list]\n" ; 1107b39c5158Smillert 1108b39c5158Smillert @list = $x->get_dup("Smith") ; 1109b39c5158Smillert print "Smith => [@list]\n" ; 1110b39c5158Smillert 1111b39c5158Smillert @list = $x->get_dup("Dog") ; 1112b39c5158Smillert print "Dog => [@list]\n" ; 1113b39c5158Smillert 1114b39c5158Smillert undef $x ; 1115b39c5158Smillert untie %h ; 1116b39c5158Smillert } 1117b39c5158Smillert 1118b39c5158Smillert ok(150, docat_del($file) eq <<'EOM') ; 1119b39c5158SmillertWall occurred 3 times 1120b39c5158SmillertLarry is there 1121b39c5158SmillertThere are 2 Brick Walls 1122b39c5158SmillertWall => [Brick Brick Larry] 1123b39c5158SmillertSmith => [John] 1124b39c5158SmillertDog => [] 1125b39c5158SmillertEOM 1126b39c5158Smillert 1127b39c5158Smillert { 1128*256a93a4Safresh1 my $redirect = Redirect->new( $file ); 1129b39c5158Smillert 1130b39c5158Smillert # BTREE example 5 1131b39c5158Smillert ### 1132b39c5158Smillert 1133b39c5158Smillert use warnings FATAL => qw(all) ; 1134b39c5158Smillert use strict ; 1135b39c5158Smillert use DB_File ; 1136b39c5158Smillert 1137b39c5158Smillert my ($filename, $x, %h, $found); 1138b39c5158Smillert 1139b39c5158Smillert $filename = "tree" ; 1140b39c5158Smillert 1141b39c5158Smillert # Enable duplicate records 1142b39c5158Smillert $DB_BTREE->{'flags'} = R_DUP ; 1143b39c5158Smillert 1144b39c5158Smillert $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE 1145b39c5158Smillert or die "Cannot open $filename: $!\n"; 1146b39c5158Smillert 1147b39c5158Smillert $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ; 1148b39c5158Smillert print "Larry Wall is $found there\n" ; 1149b39c5158Smillert 1150b39c5158Smillert $found = ( $x->find_dup("Wall", "Harry") == 0 ? "" : "not") ; 1151b39c5158Smillert print "Harry Wall is $found there\n" ; 1152b39c5158Smillert 1153b39c5158Smillert undef $x ; 1154b39c5158Smillert untie %h ; 1155b39c5158Smillert } 1156b39c5158Smillert 1157b39c5158Smillert ok(151, docat_del($file) eq <<'EOM') ; 1158b39c5158SmillertLarry Wall is there 1159b39c5158SmillertHarry Wall is not there 1160b39c5158SmillertEOM 1161b39c5158Smillert 1162b39c5158Smillert { 1163*256a93a4Safresh1 my $redirect = Redirect->new( $file ); 1164b39c5158Smillert 1165b39c5158Smillert # BTREE example 6 1166b39c5158Smillert ### 1167b39c5158Smillert 1168b39c5158Smillert use warnings FATAL => qw(all) ; 1169b39c5158Smillert use strict ; 1170b39c5158Smillert use DB_File ; 1171b39c5158Smillert 1172b39c5158Smillert my ($filename, $x, %h, $found); 1173b39c5158Smillert 1174b39c5158Smillert $filename = "tree" ; 1175b39c5158Smillert 1176b39c5158Smillert # Enable duplicate records 1177b39c5158Smillert $DB_BTREE->{'flags'} = R_DUP ; 1178b39c5158Smillert 1179b39c5158Smillert $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE 1180b39c5158Smillert or die "Cannot open $filename: $!\n"; 1181b39c5158Smillert 1182b39c5158Smillert $x->del_dup("Wall", "Larry") ; 1183b39c5158Smillert 1184b39c5158Smillert $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ; 1185b39c5158Smillert print "Larry Wall is $found there\n" ; 1186b39c5158Smillert 1187b39c5158Smillert undef $x ; 1188b39c5158Smillert untie %h ; 1189b39c5158Smillert 1190b39c5158Smillert unlink $filename ; 1191b39c5158Smillert } 1192b39c5158Smillert 1193b39c5158Smillert ok(152, docat_del($file) eq <<'EOM') ; 1194b39c5158SmillertLarry Wall is not there 1195b39c5158SmillertEOM 1196b39c5158Smillert 1197b39c5158Smillert { 1198*256a93a4Safresh1 my $redirect = Redirect->new( $file ); 1199b39c5158Smillert 1200b39c5158Smillert # BTREE example 7 1201b39c5158Smillert ### 1202b39c5158Smillert 1203b39c5158Smillert use warnings FATAL => qw(all) ; 1204b39c5158Smillert use strict ; 1205b39c5158Smillert use DB_File ; 1206b39c5158Smillert use Fcntl ; 1207b39c5158Smillert 1208b39c5158Smillert my ($filename, $x, %h, $st, $key, $value); 1209b39c5158Smillert 1210b39c5158Smillert sub match 1211b39c5158Smillert { 1212b39c5158Smillert my $key = shift ; 1213b39c5158Smillert my $value = 0; 1214b39c5158Smillert my $orig_key = $key ; 1215b39c5158Smillert $x->seq($key, $value, R_CURSOR) ; 1216de8cc8edSafresh1 print "$orig_key -> $key -> $value\n" ; 1217b39c5158Smillert } 1218b39c5158Smillert 1219b39c5158Smillert $filename = "tree" ; 1220b39c5158Smillert unlink $filename ; 1221b39c5158Smillert 1222b39c5158Smillert $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0640, $DB_BTREE 1223b39c5158Smillert or die "Cannot open $filename: $!\n"; 1224b39c5158Smillert 1225b39c5158Smillert # Add some key/value pairs to the file 1226b39c5158Smillert $h{'mouse'} = 'mickey' ; 1227b39c5158Smillert $h{'Wall'} = 'Larry' ; 1228b39c5158Smillert $h{'Walls'} = 'Brick' ; 1229b39c5158Smillert $h{'Smith'} = 'John' ; 1230b39c5158Smillert 1231b39c5158Smillert 1232b39c5158Smillert $key = $value = 0 ; 1233b39c5158Smillert print "IN ORDER\n" ; 1234b39c5158Smillert for ($st = $x->seq($key, $value, R_FIRST) ; 1235b39c5158Smillert $st == 0 ; 1236b39c5158Smillert $st = $x->seq($key, $value, R_NEXT) ) 1237b39c5158Smillert 1238b39c5158Smillert { print "$key -> $value\n" } 1239b39c5158Smillert 1240b39c5158Smillert print "\nPARTIAL MATCH\n" ; 1241b39c5158Smillert 1242b39c5158Smillert match "Wa" ; 1243b39c5158Smillert match "A" ; 1244b39c5158Smillert match "a" ; 1245b39c5158Smillert 1246b39c5158Smillert undef $x ; 1247b39c5158Smillert untie %h ; 1248b39c5158Smillert 1249b39c5158Smillert unlink $filename ; 1250b39c5158Smillert 1251b39c5158Smillert } 1252b39c5158Smillert 1253b39c5158Smillert ok(153, docat_del($file) eq <<'EOM') ; 1254b39c5158SmillertIN ORDER 1255b39c5158SmillertSmith -> John 1256b39c5158SmillertWall -> Larry 1257b39c5158SmillertWalls -> Brick 1258b39c5158Smillertmouse -> mickey 1259b39c5158Smillert 1260b39c5158SmillertPARTIAL MATCH 1261b39c5158SmillertWa -> Wall -> Larry 1262b39c5158SmillertA -> Smith -> John 1263b39c5158Smillerta -> mouse -> mickey 1264b39c5158SmillertEOM 1265b39c5158Smillert 1266b39c5158Smillert} 1267b39c5158Smillert 1268b39c5158Smillert{ 1269b39c5158Smillert # Bug ID 20001013.009 1270b39c5158Smillert # 1271b39c5158Smillert # test that $hash{KEY} = undef doesn't produce the warning 1272b39c5158Smillert # Use of uninitialized value in null operation 1273b39c5158Smillert use warnings ; 1274b39c5158Smillert use strict ; 1275b39c5158Smillert use DB_File ; 1276b39c5158Smillert 1277b39c5158Smillert unlink $Dfile; 1278b39c5158Smillert my %h ; 1279b39c5158Smillert my $a = ""; 1280b39c5158Smillert local $SIG{__WARN__} = sub {$a = $_[0]} ; 1281b39c5158Smillert 1282b39c5158Smillert tie %h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0664, $DB_BTREE 1283b39c5158Smillert or die "Can't open file: $!\n" ; 1284b39c5158Smillert $h{ABC} = undef; 1285b39c5158Smillert ok(154, $a eq "") ; 1286b39c5158Smillert untie %h ; 1287b39c5158Smillert unlink $Dfile; 1288b39c5158Smillert} 1289b39c5158Smillert 1290b39c5158Smillert{ 1291b39c5158Smillert # test that %hash = () doesn't produce the warning 1292b39c5158Smillert # Argument "" isn't numeric in entersub 1293b39c5158Smillert use warnings ; 1294b39c5158Smillert use strict ; 1295b39c5158Smillert use DB_File ; 1296b39c5158Smillert 1297b39c5158Smillert unlink $Dfile; 1298b39c5158Smillert my %h ; 1299b39c5158Smillert my $a = ""; 1300b39c5158Smillert local $SIG{__WARN__} = sub {$a = $_[0]} ; 1301b39c5158Smillert 1302b39c5158Smillert tie %h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0664, $DB_BTREE 1303b39c5158Smillert or die "Can't open file: $!\n" ; 1304b39c5158Smillert %h = (); ; 1305b39c5158Smillert ok(155, $a eq "") ; 1306b39c5158Smillert untie %h ; 1307b39c5158Smillert unlink $Dfile; 1308b39c5158Smillert} 1309b39c5158Smillert 1310b39c5158Smillert{ 1311b39c5158Smillert # When iterating over a tied hash using "each", the key passed to FETCH 1312b39c5158Smillert # will be recycled and passed to NEXTKEY. If a Source Filter modifies the 1313b39c5158Smillert # key in FETCH via a filter_fetch_key method we need to check that the 1314b39c5158Smillert # modified key doesn't get passed to NEXTKEY. 1315b39c5158Smillert # Also Test "keys" & "values" while we are at it. 1316b39c5158Smillert 1317b39c5158Smillert use warnings ; 1318b39c5158Smillert use strict ; 1319b39c5158Smillert use DB_File ; 1320b39c5158Smillert 1321b39c5158Smillert unlink $Dfile; 1322b39c5158Smillert my $bad_key = 0 ; 1323b39c5158Smillert my %h = () ; 1324b39c5158Smillert my $db ; 1325b39c5158Smillert ok(156, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) ); 1326b39c5158Smillert $db->filter_fetch_key (sub { $_ =~ s/^Beta_/Alpha_/ if defined $_}) ; 1327b39c5158Smillert $db->filter_store_key (sub { $bad_key = 1 if /^Beta_/ ; $_ =~ s/^Alpha_/Beta_/}) ; 1328b39c5158Smillert 1329b39c5158Smillert $h{'Alpha_ABC'} = 2 ; 1330b39c5158Smillert $h{'Alpha_DEF'} = 5 ; 1331b39c5158Smillert 1332b39c5158Smillert ok(157, $h{'Alpha_ABC'} == 2); 1333b39c5158Smillert ok(158, $h{'Alpha_DEF'} == 5); 1334b39c5158Smillert 1335b39c5158Smillert my ($k, $v) = ("",""); 1336b39c5158Smillert while (($k, $v) = each %h) {} 1337b39c5158Smillert ok(159, $bad_key == 0); 1338b39c5158Smillert 1339b39c5158Smillert $bad_key = 0 ; 1340b39c5158Smillert foreach $k (keys %h) {} 1341b39c5158Smillert ok(160, $bad_key == 0); 1342b39c5158Smillert 1343b39c5158Smillert $bad_key = 0 ; 1344b39c5158Smillert foreach $v (values %h) {} 1345b39c5158Smillert ok(161, $bad_key == 0); 1346b39c5158Smillert 1347b39c5158Smillert undef $db ; 1348b39c5158Smillert untie %h ; 1349b39c5158Smillert unlink $Dfile; 1350b39c5158Smillert} 1351b39c5158Smillert 1352b39c5158Smillert{ 1353b39c5158Smillert # now an error to pass 'compare' a non-code reference 1354*256a93a4Safresh1 my $dbh = DB_File::BTREEINFO->new(); 1355b39c5158Smillert 1356b39c5158Smillert eval { $dbh->{compare} = 2 }; 1357b39c5158Smillert ok(162, $@ =~ /^Key 'compare' not associated with a code reference at/); 1358b39c5158Smillert 1359b39c5158Smillert eval { $dbh->{prefix} = 2 }; 1360b39c5158Smillert ok(163, $@ =~ /^Key 'prefix' not associated with a code reference at/); 1361b39c5158Smillert 1362b39c5158Smillert} 1363b39c5158Smillert 1364b39c5158Smillert 1365b39c5158Smillert#{ 1366b39c5158Smillert# # recursion detection in btree 1367b39c5158Smillert# my %hash ; 1368b39c5158Smillert# unlink $Dfile; 1369*256a93a4Safresh1# my $dbh = DB_File::BTREEINFO->new(); 1370b39c5158Smillert# $dbh->{compare} = sub { $hash{3} = 4 ; length $_[0] } ; 1371b39c5158Smillert# 1372b39c5158Smillert# 1373b39c5158Smillert# my (%h); 1374b39c5158Smillert# ok(164, tie(%hash, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $dbh ) ); 1375b39c5158Smillert# 1376b39c5158Smillert# eval { $hash{1} = 2; 1377b39c5158Smillert# $hash{4} = 5; 1378b39c5158Smillert# }; 1379b39c5158Smillert# 1380b39c5158Smillert# ok(165, $@ =~ /^DB_File btree_compare: recursion detected/); 1381b39c5158Smillert# { 1382b39c5158Smillert# no warnings; 1383b39c5158Smillert# untie %hash; 1384b39c5158Smillert# } 1385b39c5158Smillert# unlink $Dfile; 1386b39c5158Smillert#} 1387b39c5158Smillertok(164,1); 1388b39c5158Smillertok(165,1); 1389b39c5158Smillert 1390b39c5158Smillert{ 1391b39c5158Smillert # Check that two callbacks don't interact 1392b39c5158Smillert my %hash1 ; 1393b39c5158Smillert my %hash2 ; 1394b39c5158Smillert my $h1_count = 0; 1395b39c5158Smillert my $h2_count = 0; 1396b39c5158Smillert unlink $Dfile, $Dfile2; 1397*256a93a4Safresh1 my $dbh1 = DB_File::BTREEINFO->new(); 1398b39c5158Smillert $dbh1->{compare} = sub { ++ $h1_count ; $_[0] cmp $_[1] } ; 1399b39c5158Smillert 1400*256a93a4Safresh1 my $dbh2 = DB_File::BTREEINFO->new(); 1401b39c5158Smillert $dbh2->{compare} = sub { ;++ $h2_count ; $_[0] cmp $_[1] } ; 1402b39c5158Smillert 1403b39c5158Smillert 1404b39c5158Smillert 1405b39c5158Smillert my (%h); 1406b39c5158Smillert ok(166, tie(%hash1, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $dbh1 ) ); 1407b39c5158Smillert ok(167, tie(%hash2, 'DB_File',$Dfile2, O_RDWR|O_CREAT, 0640, $dbh2 ) ); 1408b39c5158Smillert 1409b39c5158Smillert $hash1{DEFG} = 5; 1410b39c5158Smillert $hash1{XYZ} = 2; 1411b39c5158Smillert $hash1{ABCDE} = 5; 1412b39c5158Smillert 1413b39c5158Smillert $hash2{defg} = 5; 1414b39c5158Smillert $hash2{xyz} = 2; 1415b39c5158Smillert $hash2{abcde} = 5; 1416b39c5158Smillert 1417b39c5158Smillert ok(168, $h1_count > 0); 1418b39c5158Smillert ok(169, $h1_count == $h2_count); 1419b39c5158Smillert 1420b39c5158Smillert ok(170, safeUntie \%hash1); 1421b39c5158Smillert ok(171, safeUntie \%hash2); 1422b39c5158Smillert unlink $Dfile, $Dfile2; 1423b39c5158Smillert} 1424b39c5158Smillert 1425b39c5158Smillert{ 1426b39c5158Smillert # Check that DBM Filter can cope with read-only $_ 1427b39c5158Smillert 1428b39c5158Smillert use warnings ; 1429b39c5158Smillert use strict ; 1430b39c5158Smillert my (%h, $db) ; 1431b39c5158Smillert unlink $Dfile; 1432b39c5158Smillert 1433b39c5158Smillert ok(172, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) ); 1434b39c5158Smillert 1435b39c5158Smillert $db->filter_fetch_key (sub { }) ; 1436b39c5158Smillert $db->filter_store_key (sub { }) ; 1437b39c5158Smillert $db->filter_fetch_value (sub { }) ; 1438b39c5158Smillert $db->filter_store_value (sub { }) ; 1439b39c5158Smillert 1440b39c5158Smillert $_ = "original" ; 1441b39c5158Smillert 1442b39c5158Smillert $h{"fred"} = "joe" ; 1443b39c5158Smillert ok(173, $h{"fred"} eq "joe"); 1444b39c5158Smillert 1445b39c5158Smillert eval { my @r= grep { $h{$_} } (1, 2, 3) }; 1446b39c5158Smillert ok (174, ! $@); 1447b39c5158Smillert 1448b39c5158Smillert 1449b39c5158Smillert # delete the filters 1450b39c5158Smillert $db->filter_fetch_key (undef); 1451b39c5158Smillert $db->filter_store_key (undef); 1452b39c5158Smillert $db->filter_fetch_value (undef); 1453b39c5158Smillert $db->filter_store_value (undef); 1454b39c5158Smillert 1455b39c5158Smillert $h{"fred"} = "joe" ; 1456b39c5158Smillert 1457b39c5158Smillert ok(175, $h{"fred"} eq "joe"); 1458b39c5158Smillert 1459b39c5158Smillert ok(176, $db->FIRSTKEY() eq "fred") ; 1460b39c5158Smillert 1461b39c5158Smillert eval { my @r= grep { $h{$_} } (1, 2, 3) }; 1462b39c5158Smillert ok (177, ! $@); 1463b39c5158Smillert 1464b39c5158Smillert undef $db ; 1465b39c5158Smillert untie %h; 1466b39c5158Smillert unlink $Dfile; 1467b39c5158Smillert} 1468b39c5158Smillert 1469b39c5158Smillert{ 1470b39c5158Smillert # Check low-level API works with filter 1471b39c5158Smillert 1472b39c5158Smillert use warnings ; 1473b39c5158Smillert use strict ; 1474b39c5158Smillert my (%h, $db) ; 1475b39c5158Smillert my $Dfile = "xxy.db"; 1476b39c5158Smillert unlink $Dfile; 1477b39c5158Smillert 1478b39c5158Smillert ok(178, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) ); 1479b39c5158Smillert 1480b39c5158Smillert 1481b39c5158Smillert $db->filter_fetch_key (sub { $_ = unpack("i", $_) } ); 1482b39c5158Smillert $db->filter_store_key (sub { $_ = pack("i", $_) } ); 1483b39c5158Smillert $db->filter_fetch_value (sub { $_ = unpack("i", $_) } ); 1484b39c5158Smillert $db->filter_store_value (sub { $_ = pack("i", $_) } ); 1485b39c5158Smillert 1486b39c5158Smillert $_ = 'fred'; 1487b39c5158Smillert 1488b39c5158Smillert my $key = 22 ; 1489b39c5158Smillert my $value = 34 ; 1490b39c5158Smillert 1491b39c5158Smillert $db->put($key, $value) ; 1492b39c5158Smillert ok 179, $key == 22; 1493b39c5158Smillert ok 180, $value == 34 ; 1494b39c5158Smillert ok 181, $_ eq 'fred'; 1495b39c5158Smillert #print "k [$key][$value]\n" ; 1496b39c5158Smillert 1497b39c5158Smillert my $val ; 1498b39c5158Smillert $db->get($key, $val) ; 1499b39c5158Smillert ok 182, $key == 22; 1500b39c5158Smillert ok 183, $val == 34 ; 1501b39c5158Smillert ok 184, $_ eq 'fred'; 1502b39c5158Smillert 1503b39c5158Smillert $key = 51 ; 1504b39c5158Smillert $value = 454; 1505b39c5158Smillert $h{$key} = $value ; 1506b39c5158Smillert ok 185, $key == 51; 1507b39c5158Smillert ok 186, $value == 454 ; 1508b39c5158Smillert ok 187, $_ eq 'fred'; 1509b39c5158Smillert 1510b39c5158Smillert undef $db ; 1511b39c5158Smillert untie %h; 1512b39c5158Smillert unlink $Dfile; 1513b39c5158Smillert} 1514b39c5158Smillert 1515b39c5158Smillert 1516b39c5158Smillert 1517b39c5158Smillert{ 1518b39c5158Smillert # Regression Test for bug 30237 1519b39c5158Smillert # Check that substr can be used in the key to db_put 1520b39c5158Smillert # and that db_put does not trigger the warning 1521b39c5158Smillert # 1522b39c5158Smillert # Use of uninitialized value in subroutine entry 1523b39c5158Smillert 1524b39c5158Smillert 1525b39c5158Smillert use warnings ; 1526b39c5158Smillert use strict ; 1527b39c5158Smillert my (%h, $db) ; 1528b39c5158Smillert my $Dfile = "xxy.db"; 1529b39c5158Smillert unlink $Dfile; 1530b39c5158Smillert 1531b39c5158Smillert ok(188, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE )); 1532b39c5158Smillert 1533b39c5158Smillert my $warned = ''; 1534b39c5158Smillert local $SIG{__WARN__} = sub {$warned = $_[0]} ; 1535b39c5158Smillert 1536b39c5158Smillert # db-put with substr of key 1537b39c5158Smillert my %remember = () ; 1538b39c5158Smillert for my $ix ( 10 .. 12 ) 1539b39c5158Smillert { 1540b39c5158Smillert my $key = $ix . "data" ; 1541b39c5158Smillert my $value = "value$ix" ; 1542b39c5158Smillert $remember{$key} = $value ; 1543b39c5158Smillert $db->put(substr($key,0), $value) ; 1544b39c5158Smillert } 1545b39c5158Smillert 1546b39c5158Smillert ok 189, $warned eq '' 1547b39c5158Smillert or print "# Caught warning [$warned]\n" ; 1548b39c5158Smillert 1549b39c5158Smillert # db-put with substr of value 1550b39c5158Smillert $warned = ''; 1551b39c5158Smillert for my $ix ( 20 .. 22 ) 1552b39c5158Smillert { 1553b39c5158Smillert my $key = $ix . "data" ; 1554b39c5158Smillert my $value = "value$ix" ; 1555b39c5158Smillert $remember{$key} = $value ; 1556b39c5158Smillert $db->put($key, substr($value,0)) ; 1557b39c5158Smillert } 1558b39c5158Smillert 1559b39c5158Smillert ok 190, $warned eq '' 1560b39c5158Smillert or print "# Caught warning [$warned]\n" ; 1561b39c5158Smillert 1562b39c5158Smillert # via the tied hash is not a problem, but check anyway 1563b39c5158Smillert # substr of key 1564b39c5158Smillert $warned = ''; 1565b39c5158Smillert for my $ix ( 30 .. 32 ) 1566b39c5158Smillert { 1567b39c5158Smillert my $key = $ix . "data" ; 1568b39c5158Smillert my $value = "value$ix" ; 1569b39c5158Smillert $remember{$key} = $value ; 1570b39c5158Smillert $h{substr($key,0)} = $value ; 1571b39c5158Smillert } 1572b39c5158Smillert 1573b39c5158Smillert ok 191, $warned eq '' 1574b39c5158Smillert or print "# Caught warning [$warned]\n" ; 1575b39c5158Smillert 1576b39c5158Smillert # via the tied hash is not a problem, but check anyway 1577b39c5158Smillert # substr of value 1578b39c5158Smillert $warned = ''; 1579b39c5158Smillert for my $ix ( 40 .. 42 ) 1580b39c5158Smillert { 1581b39c5158Smillert my $key = $ix . "data" ; 1582b39c5158Smillert my $value = "value$ix" ; 1583b39c5158Smillert $remember{$key} = $value ; 1584b39c5158Smillert $h{$key} = substr($value,0) ; 1585b39c5158Smillert } 1586b39c5158Smillert 1587b39c5158Smillert ok 192, $warned eq '' 1588b39c5158Smillert or print "# Caught warning [$warned]\n" ; 1589b39c5158Smillert 1590b39c5158Smillert my %bad = () ; 1591b39c5158Smillert $key = ''; 1592b39c5158Smillert for ($status = $db->seq($key, $value, R_FIRST ) ; 1593b39c5158Smillert $status == 0 ; 1594b39c5158Smillert $status = $db->seq($key, $value, R_NEXT ) ) { 1595b39c5158Smillert 1596b39c5158Smillert #print "# key [$key] value [$value]\n" ; 1597b39c5158Smillert if (defined $remember{$key} && defined $value && 1598b39c5158Smillert $remember{$key} eq $value) { 1599b39c5158Smillert delete $remember{$key} ; 1600b39c5158Smillert } 1601b39c5158Smillert else { 1602b39c5158Smillert $bad{$key} = $value ; 1603b39c5158Smillert } 1604b39c5158Smillert } 1605b39c5158Smillert 1606b39c5158Smillert ok 193, keys %bad == 0 ; 1607b39c5158Smillert ok 194, keys %remember == 0 ; 1608b39c5158Smillert 1609b39c5158Smillert print "# missing -- $key $value\n" while ($key, $value) = each %remember; 1610b39c5158Smillert print "# bad -- $key $value\n" while ($key, $value) = each %bad; 1611b39c5158Smillert 1612b39c5158Smillert # Make sure this fix does not break code to handle an undef key 1613b39c5158Smillert # Berkeley DB undef key is bron between versions 2.3.16 and 1614b39c5158Smillert my $value = 'fred'; 1615b39c5158Smillert $warned = ''; 1616b39c5158Smillert $db->put(undef, $value) ; 1617b39c5158Smillert ok 195, $warned eq '' 1618b39c5158Smillert or print "# Caught warning [$warned]\n" ; 1619b39c5158Smillert $warned = ''; 1620b39c5158Smillert 1621b39c5158Smillert my $no_NULL = ($DB_File::db_ver >= 2.003016 && $DB_File::db_ver < 3.001) ; 1622b39c5158Smillert print "# db_ver $DB_File::db_ver\n"; 1623b39c5158Smillert $value = '' ; 1624b39c5158Smillert $db->get(undef, $value) ; 1625b39c5158Smillert ok 196, $no_NULL || $value eq 'fred' or print "# got [$value]\n" ; 1626b39c5158Smillert ok 197, $warned eq '' 1627b39c5158Smillert or print "# Caught warning [$warned]\n" ; 1628b39c5158Smillert $warned = ''; 1629b39c5158Smillert 1630b39c5158Smillert undef $db ; 1631b39c5158Smillert untie %h; 1632b39c5158Smillert unlink $Dfile; 1633b39c5158Smillert} 16345759b3d2Safresh1 16355759b3d2Safresh1#{ 16365759b3d2Safresh1# # R_SETCURSOR 16375759b3d2Safresh1# use strict ; 16385759b3d2Safresh1# my (%h, $db) ; 16395759b3d2Safresh1# unlink $Dfile; 16405759b3d2Safresh1# 16415759b3d2Safresh1# ok 198, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) ; 16425759b3d2Safresh1# 16435759b3d2Safresh1# $h{abc} = 33 ; 16445759b3d2Safresh1# my $k = "newest" ; 16455759b3d2Safresh1# my $v = 44 ; 16465759b3d2Safresh1# my $status = $db->put($k, $v, R_SETCURSOR) ; 16475759b3d2Safresh1# print "status = [$status]\n" ; 16485759b3d2Safresh1# ok 199, $status == 0 ; 16495759b3d2Safresh1# $k = $v = ''; 16505759b3d2Safresh1# $status = $db->get($k, $v, R_CURSOR) ; 16515759b3d2Safresh1# ok 200, $status == 0 ; 16525759b3d2Safresh1# ok 201, $k eq 'newest'; 16535759b3d2Safresh1# ok 202, $v == 44; 16545759b3d2Safresh1# $status = $db->del($k, R_CURSOR) ; 16555759b3d2Safresh1# print "status = [$status]\n" ; 16565759b3d2Safresh1# ok(203, $status == 0) ; 16575759b3d2Safresh1# $k = "newest" ; 16585759b3d2Safresh1# ok(204, $db->get($k, $v, R_CURSOR)) ; 16595759b3d2Safresh1# 16605759b3d2Safresh1# ok(205, keys %h == 1) ; 16615759b3d2Safresh1# 16625759b3d2Safresh1# undef $db ; 16635759b3d2Safresh1# untie %h; 16645759b3d2Safresh1# unlink $Dfile; 16655759b3d2Safresh1#} 16665759b3d2Safresh1 1667b39c5158Smillertexit ; 1668