Perl referencing and dereferencing hash values ​​when switching to the subroutine?

advertisements

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 $databasesTableName 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:

  1. When calling generate_config you are passing by value, not by reference. This is fine.
  2. you are getting an undef warning, this means you are running with 'use strict;'. Good!
  3. create lexical $result within the function, via my.
  4. While $$hashr{key} is valid code, $hashr->{key} is preferred.
  5. 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;
    
    

    }