2

I have the following procedure, which I'm using to synchronize two MySQL tables:

sub sync{
    my %tables = (
        'sitematrix_test' => 'sitematrix_sites'
    );

    while(($key, $value) = each(%tables)){
        print "Matching columns $key : $value\n";

        my @data;
        my $query = $db->prepare("
            SELECT $key.* FROM $key LEFT JOIN $value ON 
            $key.site_id = $value.site_id WHERE $value.site_id IS NULL;
        ") 
            or die "Couldn't prepare statement: " . $db->errstr;

        $query->execute() 
            or die "Couldn't execute statement: " . $query->errstr;

        if($query->rows == 0){
            print "No updates have been made for $key : $value";
        }
        else{
            #read the matching records and print them out
            while(@data = $query->fetchrow_array()){
                print "@data\n";
            }
        }

        $query->finish;
    }

    $db->disconnect;    
}

It's giving the following error:

Use of uninitialized value $data[3] in join or string at C:/Users/souzamor/workspace/Parser/synchronizer.pl line 69.
Use of uninitialized value $data[4] in join or string at C:/Users/souzamor/workspace/Parser/synchronizer.pl line 69.
Use of uninitialized value $data[5] in join or string at C:/Users/souzamor/workspace/Parser/synchronizer.pl line 69.
Use of uninitialized value $data[6] in join or string at C:/Users/souzamor/workspace/Parser/synchronizer.pl line 69.

Could someone please explain why is it going beyond the array's bound?

1 Answer 1

5

You have NULLs in your data coming from the database; these get converted to undef in Perl. The warning is coming from this line:

print "@data\n";

where you stringify the array. Example:

perl -Mwarnings -e '@foo=(1, 2, undef, 3); print "@foo\n"'
Use of uninitialized value $foo[2] in join or string at -e line 1.
1 2  3

If you really want to stringify the whole array and print it each time, a simple fix would be to convert undefs to empty strings:

while( my @data = map { defined($_) ? $_ : '' } $query->fetchrow_array() ) {

Alternatively, if you don't need to print all the data for every row, just print a primary key or something that you know will not be NULL.

Sign up to request clarification or add additional context in comments.

4 Comments

You could also use the logical defined or operator // instead of the ternary with defined.
I don't think this like is corret: while( my @data = map { defined ? $_ : '' } $query->fetchrow_array() )
@simbabque Could you demonstrate?
@philippe, I updated the answer to fix a syntax issue in the map. You could also used map { $_ // '' } as simbabque points out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.