Jason Andresen
Jason Andresen

Reputation: 21

Passing tied hashes using BerkelyDB to subroutines

I'm trying to pass a tied hash using BerkeleyDB to a subroutine and modifying the contents of the database in the routine, but it's not working.

#!/usr/bin/perl

use warnings;
use strict;
use BerkeleyDB;

sub testdb($)
{
    my $dbptr = shift;
    my %db = %{$dbptr};

    print("inside foo: ", $db{'foo'}, "\n");

    $db{'biz'} = "baz";
    return 0;
}

my %database;
my $dbhand = tie %database, 'BerkeleyDB::Hash', -Filename => "test.db";

print "outside foo: ", $database{'foo'}, "\n";

testdb(\%database);
print "returned: ", $database{'biz'}, "\n";

$dbhand->db_close();
undef($dbhand);
untie %database;

exit(0);

But when I run it:

./dbtie
outside foo: foobar
inside foo: foobar
Use of uninitialized value in print at ./dbtie line 24.
returned:

So it appears that I can read from the database, but I cannot write to it. Why?

I tried doing a db_sync() at the end of the subroutine, but it made no difference.

This is Perl 5.14 using BerkeleyDB version 0.54. It is in turn using Berkeley DB version 6, creating a version 9 hashtable.

Upvotes: 2

Views: 73

Answers (1)

Miller
Miller

Reputation: 35208

Don't dereference your tied hash in your sub. Instead work with the reference:

sub testdb
{
    my $dbptr = shift;

    print("inside foo: ", $dbptr->{'foo'}, "\n");

    $dbptr->{'biz'} = "baz";
    return 0;
}

When you assign my %hash = %$dbptr you're creating a copy of all of your data and assigning it to a new basic hash data structure. Once the subroutine exits, any changes you made to %hash will be lost unless you intentionally do something with it.

Upvotes: 1

Related Questions