Re: Store Object Class in DBM Hash



On 05/16/2007 11:41 AM, michael.shnitzer@xxxxxxxxx wrote:
It was my understanding that once a DBM hash was tied to a file, it
can be accessed using the same methods as a regular hash. For
simplicities sake I created a small perl program to demonstrate what I
am trying to do:

***********************************
#! /usr/bin/perl -w
use warnings;

my %hash = ( );
dbmopen(%hash, ".data/documents", 0777);
$hash{mike} = new Document;

print $hash{mike}->docno;

package Document;

sub new
{
my $self = {
document_number => "DOC123",
};
bless $self;
}

sub docno
{
my $self = shift;
return $self->{document_number};
}
**************************************

If I run this program with the DBM hash it returns "Can't locate
object method "docno" via package "Document=HASH(0x4001d0cc)" (perhaps
you forgot to load "Document=HASH(0x4001d0cc)"?) at read.pl line 11."

But if I run this program without opening the DBM hash, then the
program returns the expected result of DOC123.

Obviously there is a difference in accessing the hash data when it is
being read from a DBM hash that I am missing.

Any suggestions would be appreciated.

Thanks,

--Mike


A couple of limitations in Perl and dbmopen expose the fact that DBM-hashes are not real hashes; to store objects in a DBM, you'd probably have to Serialize the data. You can either serialize it yourself, or you can let MLDBM serialize it for you:

#!/usr/bin/perl
use strict;
use warnings;

my $use_mldbm = 1;

if (! $use_mldbm)
{
use Storable qw(freeze thaw);
my $file = 'dfiles/documents';
my %hash;
dbmopen %hash, $file, 0644 or die("Oops: $!");

my $obj = Document->new;
$obj->increment_docno;
$obj->increment_docno;
$obj->increment_docno;
$obj->increment_docno;
$hash{mike} = freeze($obj);
print thaw($hash{mike})->docno, "\n"; # prints "DOC127"

dbmclose %hash;
exit;
}

if ($use_mldbm)
{
use MLDBM qw(DB_File Storable);
my $file = 'dfiles/docs.db';
my %hash;

tie %hash, 'MLDBM', $file;

my $obj = Document->new;
$obj->increment_docno;
$obj->increment_docno;
$obj->increment_docno;
$obj->increment_docno;
$hash{mike} = $obj;
print $hash{mike}->docno, "\n";

untie %hash;
exit;
}

package Document;

sub new
{
my $self = {
document_number => "DOC123",
};
bless $self;
}

sub docno
{
my $self = shift;
return $self->{document_number};
}

sub increment_docno {
my $self = shift;
$self->{document_number} =~ s/(\d+)$/$1 + 1/e;
$self->{document_number};
}

__END__

Be sure to read the admonition in the BUGS section of MLDBM's pod; it indirectly applies to dbmopen also.



.



Relevant Pages

  • Re: looking for help with a counting algorithm
    ... >> subcategory is counted, the code goes back up the tree to the root, adding ... >> involve retrieving all the category memberships from the database, ... sub ReadCategories{ ... ReadCategories is called with two empty hash pointers by any of the ...
    (comp.lang.perl.misc)
  • Re: Packages and returning errors
    ... >>of instance data. ... >>sub rtnError { ... its a reference to a hash. ... functions in the package to see it. ...
    (comp.lang.perl.misc)
  • Re: Any suggestions for my programming style?
    ... Also, add "use strict". ... Better use a lexical hash instead of the package variables ... > sub get_century_code ... "Reply" at the bottom of the article headers. ...
    (comp.lang.perl.misc)
  • Questions on Perl Syntax from queue.pm
    ... I don't see an array defined ... When we bless an object, we basically have hash table, correct? ... 87 sub enqueue { ... must be a bug in line 76 because it never returns from a call to dequeue. ...
    (perl.beginners)
  • Re: how to define a layer between data and functions
    ... Let me give you a sample of some of the data as it would be in my hash ... function between several layers. ... you can get the prototype of a sub with the prototype ...
    (comp.lang.perl.misc)