DBM::Deep: Cannot store something that is tied

brian_d_foy on 2007-08-14T04:18:09

I ran into this problem and it's plagued me for a couple weeks. I was playing with with stuff to store a bunch of stuff in a DBM::Deep file, and I'd do something to cause an error "DBM::Deep: Cannot store something that is tied". I'd change around some syntax and it would disappear. I've sorta solved the problem, but it doesn't really look like a real solution.

I figured that some other module I was using was supplying a tied object. Config::IniFiles seemed a likely candidate because it has tie methods inside it, so for awhile I blamed it and thought I had a workaround.

But the problem came back, this time without Config::IniFiles. Damn you Karl Rove!

It turns out that I was taking some data out of a DBM::Deep object and either moving it back into the object in a different form or trying to put it in a different DBM::Deep object:

#!/usr/bin/perl

use Data::Dumper; use DBM::Deep;

my $db = DBM::Deep->new( 'foo.db' );

$db->{'foo'} = [ qw(a b c) ];

my $array = $db->{'foo'};

print Dumper( $array );

$db->{'bar'} = $array;

__END__


Okay, that's no good. This eluded me for a while because tied doesn't work on $array, so when I was trying debugging statements such as print ... if tied $array, I never saw that output. I was just guessing about who was causing the problem.

I read through the DBM::Deep docs a couple of times looking for a warning about this, but I didn't find it. I figured that there must be a way to untie or de-objectify $array, so I started trying things. It turns out export will turn the DBM::Deep thingy into a regular thingy. I got sidetracked by the line in the docs that said 'Calling the "export()" method on an existing DBM::Deep object will return a reference to a new in-memory copy of the database.' I figured that meant that I'd just get another DBM::Deep object. However, the next sentence has "...are all exported to standard Perl objects."

#!/usr/bin/perl

use Data::Dumper; use DBM::Deep;

my $db = DBM::Deep->new( 'foo.db' );

$db->{'foo'} = [ qw(a b c) ];

my $array = $db->{'foo'}->export;

print Dumper( $array );

$db->{'bar'} = $array;

__END__


It gets trickier though. Watch this problem barge back into the program. I export to get the stuff back into a regular Perl data structure, then store it in the DBM::Deep object. I try to take that same reference and store it again, but it's been re-blessed into DBM::Deep!

#!/usr/bin/perl

use Data::Dumper; use DBM::Deep;

my $db = DBM::Deep->new( 'foo.db' );

$db->{'foo'} = [ qw(a b c) ];

my $array = $db->{'foo'}->export;

$db->{'bar'} = $array; # this works

$db->{'baz'} = $array; # it's a DBM::Deep thingy again


So, I could get rid of the temporary variable:

$db->{'bar'} = $db->{'foo'}->export;

$db->{'baz'} = $db->{'foo'}->export;


That seems like it works, but it doesn't really work. Everyone of those references are deep copies, meaning that when I meant to store the data once, I'm actually recreating it. Worse than that, it's only going ot update in one place.

I haven't worked around that last bit yet, and it will probably mean I'll have to think a lot harder about the program.