N
niall.macpherson
I have a sub which calls the fetchall_hashref method from the DBI
module. I like to have all my subs return either 0 (success) or -1
(failure) and if the sub need to return some data to the caller I
always pass a variable by reference and populate that variable . I tend
to try to think of refs the same way as I did with pointers in 'C'
which I am more familiar with. What I am trying to do here is pass a
reference to a reference to a hash to the sub.
I do not want to retrun anything by value as potentially I could be
dealing with some very large hashes here
Normally passing references works fine - e.g the Connect() sub here
takes a ref to a scalar and populates it with the connection handle so
this value can then be passed to another sub. However I am having real
problems with the GetTableValues() sub. This calls
$sth->fetchall_hashref() from DBI which returns a reference to a hash.
I can't seem to get this back to my main code body so that I can then
pass it to the ProcessTableValues() sub . The current code compiles and
produces no errors but ProcessTableValues() produces no output.
I'd would be grateful if someone could tell me what I am doing wrong .
Thanks
##-------------------------------------------------------------------
## sqlhashref.pl
## Test passing ref to hash between subs
use strict;
use warnings;
use File::Spec::Functions;
use Data:
umper;
use DBI;
##------------------------------------------------------------------
sub Connect
{
## Works as expected
my ($dsn, $r_conn) = @_;
my %attr = ( RaiseError => 1, AutoCommit => 0);
$$r_conn = DBI->connect("dbi:ODBC:" . $dsn , undef, undef, \%attr);
if(!defined($$r_conn))
{
print STDERR "\n", 'Failed to connect ' , $DBI::errstr;
return(-1);
}
return(0);
}
##------------------------------------------------------------------
sub GetTableValues
{
## Cannot seem to get reference to results back to main section
my ($conn, $rrh_results) = @_;
my $rh_results = undef;
my $sth = $conn->prepare('select tabid, tabname from systables where
tabid < 5');
if(!defined($sth))
{
print STDERR "\n", 'Failed to prepare ' , $DBI::errstr;
return(-1);
}
$sth->execute();
$rh_results = $sth->fetchall_hashref('tabid');
$$rrh_results = $rh_results;
return(0);
}
##------------------------------------------------------------------
sub ProcessTableValues
{
my($rh_results) = @_;
foreach my $key (keys %{$rh_results})
{
print "\n", $key, $rh_results->($key);
}
return(0);
}
##------------------------------------------------------------------
my $conn = undef;
my %results = ();
if(Connect('sysmaster', \$conn) < 0)
{
exit(-1);
}
if(GetTableValues($conn, \\%results) < 0)
{
$conn->disconnect;exit(-1);
}
#print Dumper %results; - No output produced by this print
if(ProcessTableValues(\%results) < 0)
{
$conn->disconnect;exit(-1);
}
$conn->disconnect;
exit(0);
module. I like to have all my subs return either 0 (success) or -1
(failure) and if the sub need to return some data to the caller I
always pass a variable by reference and populate that variable . I tend
to try to think of refs the same way as I did with pointers in 'C'
which I am more familiar with. What I am trying to do here is pass a
reference to a reference to a hash to the sub.
I do not want to retrun anything by value as potentially I could be
dealing with some very large hashes here
Normally passing references works fine - e.g the Connect() sub here
takes a ref to a scalar and populates it with the connection handle so
this value can then be passed to another sub. However I am having real
problems with the GetTableValues() sub. This calls
$sth->fetchall_hashref() from DBI which returns a reference to a hash.
I can't seem to get this back to my main code body so that I can then
pass it to the ProcessTableValues() sub . The current code compiles and
produces no errors but ProcessTableValues() produces no output.
I'd would be grateful if someone could tell me what I am doing wrong .
Thanks
##-------------------------------------------------------------------
## sqlhashref.pl
## Test passing ref to hash between subs
use strict;
use warnings;
use File::Spec::Functions;
use Data:
use DBI;
##------------------------------------------------------------------
sub Connect
{
## Works as expected
my ($dsn, $r_conn) = @_;
my %attr = ( RaiseError => 1, AutoCommit => 0);
$$r_conn = DBI->connect("dbi:ODBC:" . $dsn , undef, undef, \%attr);
if(!defined($$r_conn))
{
print STDERR "\n", 'Failed to connect ' , $DBI::errstr;
return(-1);
}
return(0);
}
##------------------------------------------------------------------
sub GetTableValues
{
## Cannot seem to get reference to results back to main section
my ($conn, $rrh_results) = @_;
my $rh_results = undef;
my $sth = $conn->prepare('select tabid, tabname from systables where
tabid < 5');
if(!defined($sth))
{
print STDERR "\n", 'Failed to prepare ' , $DBI::errstr;
return(-1);
}
$sth->execute();
$rh_results = $sth->fetchall_hashref('tabid');
$$rrh_results = $rh_results;
return(0);
}
##------------------------------------------------------------------
sub ProcessTableValues
{
my($rh_results) = @_;
foreach my $key (keys %{$rh_results})
{
print "\n", $key, $rh_results->($key);
}
return(0);
}
##------------------------------------------------------------------
my $conn = undef;
my %results = ();
if(Connect('sysmaster', \$conn) < 0)
{
exit(-1);
}
if(GetTableValues($conn, \\%results) < 0)
{
$conn->disconnect;exit(-1);
}
#print Dumper %results; - No output produced by this print
if(ProcessTableValues(\%results) < 0)
{
$conn->disconnect;exit(-1);
}
$conn->disconnect;
exit(0);