CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
Traversing a hash of arrays

 



kencl
User

Jan 20, 2001, 5:11 PM

Post #1 of 6 (727 views)
Traversing a hash of arrays Can't Post

I've created a hash of arrays from the results of a database query. The query is performed by DBI using the DBD::CSV driver.


Code
sub Query {  # Just the relevant snippet 
$x = 0;
while ($ListPointer = $sth->fetchrow_arrayref) {
$x++;
$Data{$x} = @$ListPointer; # This builds the hash of arrays
}
$Data{0} = $x; # number of rows in the result set
return %Data # after some error checking
}

The hash contents will then be:

$Data{0} holds an integer representing the number of results
$Data{1} to $Data{$x} contain arrays, each array containing one row of the result set

The code then tests to see if there were any results with:


Code
local $GetIDsSQL = "SELECT id FROM tablename WHERE id > 0"; 
my %IDs = &Query(\$GetIDsSQL);
$AutoID = 1; # This handles new tables with zero entries
if ($IDs{0} > 0) { # If at least 1 response row was returned
for ($x = 1; $x <= $IDs{0}; $x++) {
$AutoID = $IDs{$x}[0] if ($AutoID < $IDs{$x}[0]); # This doesn't seem to work
print "autoid is: $AutoID and x is $x and first array value is -$IDs{$x}[0]-"; # Debugging
}
$AutoID++;
}

At the end of it, $AutoID is supposed to be one greater than the highest ID field, but the print debugging statement shows that $IDs{$x}[0] is empty, nothing, nada, not even null, so I must be referencing it wrong.

Any help is appreciated.



(This post was edited by kencl on Jan 20, 2001, 4:34 PM)


BigRich
Novice

Jan 21, 2001, 9:07 AM

Post #2 of 6 (714 views)
Re: Traversing a hash of arrays [In reply to] Can't Post

The problem isn't where you think it is.

$Data{$x} = @$ListPointer; Doesn't create a hash of arrays because you are assigning an array to a scalar so the keys do not refer to arrays but rather to the number of elements in the array.

A hash of arrays would look something like:

%Hash (

key1 => ['val1', 'val2', 'val3'],
key2 => ['val4', 'val5', 'val6'],
key3 => ['val7', 'val8', 'val9'],

);

so $HASH{key3}[1] would be "val8";

What you have done is:

%Hash (

key1 => @one,
key2 => @two,
key3 => @three,

);

So, assuming there are three elements in each array, key1 would equal the number 3 not the elements of the array so $HASH{key3} would be 3 but $HASH{key3}[0] would give you nothing because there is no array reference for that key.

That is the only thing I see wrong with your code so if you change $Data{$x} = @$ListPointer; to $Data{$x} = [@$ListPointer]; it should work.


BigRich





japhy
Enthusiast

Jan 21, 2001, 10:45 AM

Post #3 of 6 (709 views)
Re: Traversing a hash of arrays [In reply to] Can't Post

Your code has multiple points of error:


Code
sub Query { 
$x = 0;
while ($ListPointer = $sth->fetchrow_arrayref) {
$x++;
$Data{$x} = @$ListPointer;
}
$Data{0} = $x;
return Úta;
}

First problem: all these variables are global. This is rather poor coding style, and leads to lots of problems down the road later on. Next problem, using a hash instead of an array. Next problem, you're assigning an array to a hash value, which has to get a scalar value, which means you're assigning the SIZE of the array, not the array. Next problem, you're returning an awfully large set of data, and you should be returning it by reference.

Then your other code.


Code
local $GetIDsSQL = "SELECT id FROM tablename WHERE id > 0"; 
my %IDs = &Query(\$GetIDsSQL);
$AutoID = 1;

if ($IDs{0} > 0) {
for ($x = 1; $x <= $IDs{0}; $x++) {
$AutoID = $IDs{$x}[0] if $AutoID < $IDs{$x}[0];
print "autoid is: $AutoID and x is $x and first array value is -$IDs{$x}[0]-";
}
$AutoID++;
}

Why are you passing a $GetIDsSQL to the function? You never use it. And why a reference to it?

The biggest problem here is that you never actually MAKE the SQL query. You need to do that. Other than that, here's some corrected code for you:


Code
# my $data_array_ref = Query($sth,$SQL); 
sub Query {
my ($sth, $sql) = @_;

# I am not familiar with DBI, but I believe the
# following two lines do what you were missing
$sth->prepare($sql);
$sth->execute;

my @data;
while (my $ref = $sth->fetchrow_arrayref) {
push @data, $ref;
}
return \@data;
}

# ...

my $results = query($sth, "SOME SQL STRING HERE");
if (@$results) {
# not empty
}
else {
# empty
}

I hope this helps you.

Jeff "japhy" Pinyan -- accomplished hacker, teacher, lecturer, and author


BigRich
Novice

Jan 21, 2001, 2:11 PM

Post #4 of 6 (704 views)
Re: Traversing a hash of arrays [In reply to] Can't Post

I assumed that, since you included the phrase # Just the relevant snippet in your code at sub Query { # Just the relevant snippet, you were not having problems with the query, just assigning the row arrays to the hash and therefore you did not include all of the code associated with that subroutine.

I applied my fix to your code, inserted a few lines for the query, then used it on one of my databases and it worked fine (as far as creating a hash of arrays, there were some questions about other parts of your code). The script I used is attached here if you'd like to take a look.


BigRich



kencl
User

Jan 22, 2001, 11:44 PM

Post #5 of 6 (690 views)
Re: Traversing a hash of arrays [In reply to] Can't Post

Thanks both of you. BigRich you're example worked great!

What I'm doing is building a set of subroutines to handle all the DB stuff. This script of subroutines will then be used or included (I'll have to look that up) in other scripts. In the attached script, think of the Initialization and Subroutine sections as the finished script, and think of the Main Program section as any other script. See how easy it now becomes to write scripts? I don't have to keep writing all the db connection, errorhandling etc.

It still needs refinement (better error checking, UPDATE and DELETE subroutines...) and I've got to learn more about scoping so that the variable spaces don't leak over into the calling scripts, but I'm getting there.

Any more pointers you folks have are greatly appreciated. I love this forum. Kudos to Jaz and Japh for building such a valuable community :)



kencl
User

Jan 22, 2001, 11:52 PM

Post #6 of 6 (690 views)
Re: Traversing a hash of arrays [In reply to] Can't Post

Guess the server didn't like the .pl extension. Take two.


 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives