Can BerkeleyDB in perl handle a hash of hashes of hashes (up to n)? Can BerkeleyDB in perl handle a hash of hashes of hashes (up to n)? database database

Can BerkeleyDB in perl handle a hash of hashes of hashes (up to n)?


Use DBM::Deep.

my $db = DBM::Deep->new( "foo.db" );$db->{mykey} = "myvalue";$db->{myhash} = {};$db->{myhash}->{subkey} = "subvalue";print $db->{myhash}->{subkey} . "\n";

The code I provided yesterday would work fine with this.

sub get_node {   my $p = \shift;   $p = \( ($$p)->{$_} ) for @_;   return $p;}my @seqs = qw( CG CA TT CG );my $tree = DBM::Deep->new("foo.db");++${ get_node($tree, split //) } for @seqs;


No. BerkeleyDB stores pairs of one key and one value, where both are arbitrary bytestrings. If you store a hashref as the value, it'll store the string representation of a hashref, which isn't very useful when you read it back (as you noticed).

The MLDBM module can do something like you describe, but it works by serializing the top-level hashref to a string and storing that in the DBM file. This means it has to read/write the entire top-level hashref every time you access or change a value in it.

Depending on your application, you may be able to combine your keys into a single string, and use that as the key for your DBM file. The main limitation with that is that it's difficult to iterate over the keys of one of your interior hashes.

You might use the semi-obsolete multidimensional array emulation for this. $foo{$a,$b,$c} is interpreted as $foo{join($;, $a, $b, $c)}, and that works with tied hashes also.


No; it can only store strings. But you can use the →filter_fetch_value and →filter_store_value to define "filters" that will automatically freeze arbitrary structures to strings before storing, and to convert back when fetching. There are analogous hooks for marshalling and unmarshalling non-string keys.

Beware though: using this method to store objects that share subobjects will not preserve the sharing. For example:

$a = [1, 2, 3];$g = { array => $a };$h = { array => $a };$db{g} = $g;$db{h} = $h;@$a = ();push @{$db{g}{array}}, 4;print @{$db{g}{array}};  # prints 1234, not 4print @{$db{h}{array}};  # prints 123, not 1234 or 4

%db here is a tied hash; if it were an ordinary hash the two prints would both print 4.