[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

Re: [MacPerl] How to store hash of hashes



blowery@dal_cps.bozell.com (Baron Lowery) qrites:
>I would like to store a hash of hashes along the lines of the following:
>
>%subscribers = (
>                 "name\@company.com" => {
>                        "first_name" => "John",
>                        "last_name"  => "Doe",
>                        "checkbox_1" => "1",
>                        "checkbox_2" => "0",
>                (
>                 "name2\@aCompany.com" => {
>                        "first_name"   => "Jane",
>                        "last_name"    => "Smith",
>                        "checkbox_1"   => "0",
>                        "checkbox_2"   => "1",
>                 },
>);
>
>Writing %subscribers to file stores references not the value what is
>referenced.
>How do I save the values to file, instead of the references?

what you want is the MLDBM module from the CPAN archives. It stores
non-scalar values in a db file in an ASCIIfied representation. However
things aren't quite as simple as using "MLDBM" in the tie statement. You
have to write code slightly differently: basically you have to load a
record into a local record, work on it and then save it back if it was
changed. The pod doc has more info:

BUGS

1. Adding or altering substructures to a hash value is not entirely
transparent in current perl.  If you want to store a reference or modify an
existing reference value in the DBM, it must first be retrieved and stored
in a temporary variable for further modifications.  In particular,
something like this will NOT work properly:

    $mldb{key}{subkey}[3] = 'stuff';  # won't work

Instead, that must be written as:

    $tmp = $mldb{key};                # retrieve value
    $tmp->{subkey}[3] = 'stuff';
    $mldb{key} = $tmp;                # store value

This limitation exists because the perl TIEHASH interface currently has no
support for multidimensional ties.

2. MLDBM was first released along with the Data::Dumper package as an
example.  If you got serious with that and have a DBM file from that
version, you can do something like this to convert the old records to the
new format:

    use MLDBM (DB_File);              # be sure it's the new MLDBM
    use Fcntl;
    tie %o, MLDBM, 'oldmldbm.file', O_RDWR, 0640 or die $!;
    for $k (keys %o) {
       my $v = $o{$k};
       if ($v =~ /^\$CrYpTiCkEy/o) {
       $v = eval $v;
       if ($@) { warn "Error: $@\twhile evaluating $v\n"; }
           else    { $o{$k} = $v; }
        }
     }

performance is lost during the conversion of the dump-formatted
representation, but I was going to ask someone's help at compiling the XS
version of dumper.

Within the limitations of how you access records, I've used it for quite
complex data structures.

cheers,
Danny Thomas  <D.Thomas@vthrc.uq.edu.au>