Revision history for DBM::Deep.
+0.983 Mar 25 08:00:00 2006 Pacific
+ - Added patch inspired by Jeff Janes (Thanks!)
+ - Autovivification now works correctly
+ - The following now works correctly
+ my %hash = ( a => 1 );
+ $db->{hash} = \%hash;
+ $hash{b} = 2;
+ cmp_ok( $db->{hash}{b}, '==', 2 );
+ - NOTE: This patch works by tying the underlying datastructure that was
+ passed in. There are currently no checks to see if the datastructure was
+ previously tied.
+
0.982 Mar 08 11:00:00 2006 Pacific
- Fixed smoketests that were failing on Win32
- Added restriction for Perl 5.6.0 or higher.
# pass each key or element to it.
##
if ($r eq 'HASH') {
- my $branch = DBM::Deep->new(
+ my %x = %$value;
+ tie %$value, 'DBM::Deep', {
type => TYPE_HASH,
base_offset => $location,
root => $root,
- );
- foreach my $key (keys %{$value}) {
- $branch->STORE( $key, $value->{$key} );
- }
+ };
+ %$value = %x;
}
elsif ($r eq 'ARRAY') {
- my $branch = DBM::Deep->new(
+ my @x = @$value;
+ tie @$value, 'DBM::Deep', {
type => TYPE_ARRAY,
base_offset => $location,
root => $root,
- );
- my $index = 0;
- foreach my $element (@{$value}) {
- $branch->STORE( $index, $element );
- $index++;
- }
+ };
+ @$value = @x;
}
return $result;
make sure there are no child references lying around. DBM::Deep keeps a reference
counter, and if it is greater than 1, optimize() will abort and return undef.
-=head2 AUTOVIVIFICATION
-
-Unfortunately, autovivification doesn't work with tied hashes. This appears to
-be a bug in Perl's tie() system, as I<Jakob Schmidt> encountered the very same
-issue with his I<DWH_FIle> module (see L<http://search.cpan.org/search?module=DWH_File>),
-and it is also mentioned in the BUGS section for the I<MLDBM> module <see
-L<http://search.cpan.org/search?module=MLDBM>). Basically, on a new db file,
-this does not work:
-
- $db->{foo}->{bar} = "hello";
-
-Since "foo" doesn't exist, you cannot add "bar" to it. You end up with "foo"
-being an empty hash. Try this instead, which works fine:
-
- $db->{foo} = { bar => "hello" };
-
-As of Perl 5.8.7, this bug still exists. I have walked very carefully through
-the execution path, and Perl indeed passes an empty hash to the STORE() method.
-Probably a bug in Perl.
-
=head2 FILE CORRUPTION
The current level of error handling in DBM::Deep is minimal. Files I<are> checked
return wantarray ? @old_elements : $old_elements[-1];
}
-#XXX We don't need to define it, yet.
-#XXX It will be useful, though, when we split out HASH and ARRAY
-#sub EXTEND {
+sub EXTEND {
##
# Perl will call EXTEND() when the array is likely to grow.
# We don't care, but include it for compatibility.
##
-#}
+}
##
# Public method aliases
# DBM::Deep Test
##
use strict;
-use Test::More tests => 29;
+use Test::More tests => 33;
use Test::Exception;
use_ok( 'DBM::Deep' );
($first_key ne $next_key)
,"keys() still works if you replace long values with shorter ones"
);
+
+my %hash = ( a => 1 );
+$db->{hash} = \%hash;
+$hash{b} = 2;
+cmp_ok( $db->{hash}{b}, '==', 2 );
+
+# Test autovivification
+
+$db->{unknown}{bar} = 1;
+ok( $db->{unknown} );
+cmp_ok( $db->{unknown}{bar}, '==', 1 );
+
+$db->clear;
+$db->{foo}->{bar} = 'baz';
+is( $db->{foo}{bar}, 'baz' );
# DBM::Deep Test
##
use strict;
-use Test::More tests => 107;
+use Test::More tests => 110;
use Test::Exception;
use_ok( 'DBM::Deep' );
is($db->[1], "elem last");
is($returned[0], "middle ABC");
-# These tests verify that the hash methods cannot be called on arraytypes.
-# They will be removed once the ARRAY and HASH types are refactored into their own classes.
+my %hash = ( a => 'foo' );
$db->[0] = [ 1 .. 3 ];
-$db->[1] = { a => 'foo' };
+$db->[1] = \%hash;
is( $db->[0]->length, 3, "Reuse of same space with array successful" );
is( $db->[1]->fetch('a'), 'foo', "Reuse of same space with hash successful" );
+
+$hash{b} = '2';
+cmp_ok( $db->[1]{b}, '==', 2 );
+
+# Test autovivification
+
+$db->[9999]{bar} = 1;
+ok( $db->[9999] );
+cmp_ok( $db->[9999]{bar}, '==', 1 );
# DBM::Deep Test
##
use strict;
-use Test::More tests => 5;
+use Test::More tests => 15;
use_ok( 'DBM::Deep' );
##
$db2->{copy} = $db->{hash1};
+$db->{hash1}{subkey3} = 'where does this go?';
+is( $db->{hash1}{subkey3}, 'where does this go?' );
+
+$db2->{copy}{subkey4} = 'from the other side';
+is( $db2->{copy}{subkey4}, 'from the other side' );
+
+########
+# This is the failure case
+#
+{
+ my $left = $db->{hash1};
+ $db2->{right} = $left;
+
+ $db2->{right}{rightward} = 'floober';
+ is( $db2->{right}{rightward}, 'floober' );
+ isnt( $db->{hash1}{rightward}, 'floober' );
+}
+#
+#
+########
+
##
# close, delete $db
##
undef $db;
+
+{
+ my $db3 = DBM::Deep->new( 't/test.db' );
+ if ($db3->error()) {
+ die "ERROR: " . $db3->error();
+ }
+ is( $db3->{hash1}{subkey1}, 'subvalue1' );
+ is( $db3->{hash1}{subkey2}, 'subvalue2' );
+ is( $db3->{hash1}{subkey3}, 'where does this go?' );
+ isnt( $db3->{hash1}{subkey4}, 'from the other side' );
+}
+
unlink "t/test.db";
##
##
is( $db2->{copy}{subkey1}, 'subvalue1', "Value copied correctly" );
is( $db2->{copy}{subkey2}, 'subvalue2', "Value copied correctly" );
+isnt( $db2->{copy}{subkey3}, 'where does this go?' );
+is( $db2->{copy}{subkey4}, 'from the other side' );