Perl referencing and deferencing hash values when passing to subroutine?
I've been banging my head over this issue for about 5 hours now, I'm really frustrated and need some assistance.
I'm writing a Perl script that pulls jobs out of a MySQL table and then preforms various database admin tasks. The current task is "creating databases". The script successfully creates the database(s), but when I got to generating the config file for PHP developers it blows up.
I believe it is an issue with referencing and dereferencing variables, but I'm not quite sure what exactly is happening. I think after this function call, something happens to
$$result{'databaseName'}. This is how I get result: $result = $select->fetchrow_hashref()
Here is my function call, and the function implementation:
Function call (line 127):
generateConfig($$result{'databaseName'}, $newPassword, "php");
Function implementation:
sub generateConfig {
my($inName) = $_[0];
my($inPass) = $_[1];
my($inExt) = $_[2];
my($goodData) = 1;
my($select) = $dbh->prepare("SELECT id FROM $dat开发者_C百科abasesTableName WHERE name = '$inName'");
my($path) = $documentRoot.$inName."_config.".$inExt;
$select->execute();
if ($select->rows < 1 ) {
$goodData = 0;
}
while ( $result = $select->fetchrow_hashref() )
{
my($insert) = $dbh->do("INSERT INTO $configTableName(databaseId, username, password, path)".
"VALUES('$$result{'id'}', '$inName', '$inPass', '$path')");
}
return 1;
}
Errors:
Use of uninitialized value in concatenation (.) or string at ./dbcreator.pl line 142.
Use of uninitialized value in concatenation (.) or string at ./dbcreator.pl line 154.
Line 142:
$update = $dbh->do("UPDATE ${tablename}
SET ${jobStatus}='${newStatus}'
WHERE id = '$$result{'id'}'");
Line 154:
print "Successfully created $$result{'databaseName'}\n";
The reason I think the problem comes from the function call is because if I comment out the function call, everything works great!
If anyone could help me understand what's going on, that would be great.
Thanks,
p.s. If you notice a security issue with the whole storing passwords as plain text in a database, that's going to be addressed after this is working correctly. =P
Dylan
You do not want to store a reference to the $result returned from fetchrow_hashref, as each subsequent call will overwrite that reference.
That's ok, you're not using the reference when you are calling generate_config, as you are passing data in by value.
Are you using the same $result variable in generate_config and in the calling function? You should be using your own 'my $result' in generate_config.
while ( my $result = $select->fetchrow_hashref() )
# ^^ #add my
That's all that can be said with the current snippets of code you've included.
Some cleanup:
- When calling generate_config you are passing by value, not by reference. This is fine.
- you are getting an undef warning, this means you are running with 'use strict;'. Good!
- create lexical $result within the function, via my.
- While $$hashr{key} is valid code, $hashr->{key} is preferred.
you're using dbh->prepare, might as well use placeholders.
sub generateConfig { my($inName, inPass, $inExt) = @_; my $goodData = 1; my $select = $dbh->prepare("SELECT id FROM $databasesTableName WHERE name = ?"); my $insert = $dbh->prepare(" INSERT INTO $configTableName( databaseID ,username ,password ,path) VALUES( ?, ?, ?, ?)" ); my $path = $documentRoot . $inName . "_config." . $inExt; $select->execute( $inName ); if ($select->rows < 1 ) { $goodData = 0; } while ( my $result = $select->fetchrow_hashref() ) { insert->execute( $result->{id}, $inName, $inPass, $path ); } return 1;
}
EDIT: after reading your comment
I think that both errors have to do with your using $$result
. If $result
is the return value of fetchrow_hashref
, like in:
$result = $select->fetchrow_hashref()
then the correct way to refer to its values should be:
print "Successfully created " . $result{'databaseName'} . "\n";
and:
$update = $dbh->do("UPDATE ${tablename}
SET ${jobStatus}='${newStatus}'
WHERE id = '$result{'id'}'");
OLD ANSWER:
In function generateConfig
, you can pass a reference in using this syntax:
generateConfig(\$result{'databaseName'},$newPassword, "php");
($$
is used to dereference a reference to a string; \
gives you a reference to the object it is applied to).
Then, in the print statement itself, I would try:
print "Successfully created $result->{'databaseName'}->{columnName}\n";
indeed, fetchrow_hashref
returns a hash (not a string).
This should fix one problem.
Furthermore, you are using the variable named $dbh
but you don't show where it is set. Is it a global variable so that you can use it in generateConfig
? Has it been initialized when generateConfig
is executed?
This was driving me crazy when I was running hetchrow_hashref from Oracle result set. Turened out the column names are always returned in upper case. So once I started referencing the colum in upper case, problem went away: insert->execute( $result->{ID}, $inName, $inPass, $path );
精彩评论