Can't use an undefined value as an ARRAY reference at search.cgi line 139.

J

JimJx

Hi all,

I have what seems to me to be a strange problem....

I have the script below:

<code>
if ($type eq 'alpha') {
$query = sprintf (
"SELECT name, address, city, phone
FROM valley
where name like '$search%'
ORDER BY name LIMIT %d,%d",
$start - 1, # number of records to skip
$per_page + 1); # number of records to select
} elsif ($type eq '') {
$query = sprintf (
"SELECT name, address, city, phone
FROM valley
where keywords like '%$search%'
ORDER BY name LIMIT %d,%d",
$start - 1, # number of records to skip
$per_page + 1); # number of records to select
}
my $tbl_ref = $dbh->selectall_arrayref ($query);

$dbh->disconnect ( );

# Display results as HTML table

for (my $i = 0; $i < $per_page && $i < @{$tbl_ref}-1; $i+=2) {
# get data values in row $i
my @cells = @{$tbl_ref->[$i]}; # get data values in row $i
my @cells2 = @{$tbl_ref->[$i+1]}; # get data values in row $i+1
# map values to HTML-encoded values, or to &nbsp; if null/empty
@cells = map {
defined ($_) && $_ ne "" ? escapeHTML ($_) : "&nbsp;"
} @cells;
@cells2 = map {
defined ($_) && $_ ne "" ? escapeHTML ($_) : "&nbsp;"
} @cells2;
# add cells to table
my @cells = "<b>$cells[0]</b><br>$cells[1]<br>$cells[2]<br>
$cells[3]<br>";
my @cells2 = "<b>$cells2[0]</b><br>$cells2[1]<br>$cells2[2]<br>
$cells2[3]<br>";
push (@rows, Tr (td (\@cells),(td (\@cells2))));
}
</code>

It works great. However if I change it to:
<code>
if ($search = '#') {
$query = sprintf (
"SELECT name, address, city, phone
FROM valley where REGEXP '^[0-9]'
ORDER BY name LIMIT %d,%d",
$start - 1,
$per_page + 1);
} elsif ($type eq 'alpha') {
$query = sprintf (
"SELECT name, address, city, phone
FROM valley
where name like '$search%'
ORDER BY name LIMIT %d,%d",
$start - 1, # number of records to skip
$per_page + 1); # number of records to select
} elsif ($type eq '') {
$query = sprintf (
"SELECT name, address, city, phone
FROM valley
where keywords like '%$search%'
ORDER BY name LIMIT %d,%d",
$start - 1, # number of records to skip
$per_page + 1); # number of records to select
}
my $tbl_ref = $dbh->selectall_arrayref ($query);

$dbh->disconnect ( );

# Line 139 is the FOR below......

for (my $i = 0; $i < $per_page && $i < @{$tbl_ref}-1; $i+=2) {
# get data values in row $i
my @cells = @{$tbl_ref->[$i]}; # get data values in row $i
my @cells2 = @{$tbl_ref->[$i+1]}; # get data values in row $i+1
# map values to HTML-encoded values, or to &nbsp; if null/empty
@cells = map {
defined ($_) && $_ ne "" ? escapeHTML ($_) : "&nbsp;"
} @cells;
@cells2 = map {
defined ($_) && $_ ne "" ? escapeHTML ($_) : "&nbsp;"
} @cells2;
# add cells to table
my @cells = "<b>$cells[0]</b><br>$cells[1]<br>$cells[2]<br>
$cells[3]<br>";
my @cells2 = "<b>$cells2[0]</b><br>$cells2[1]<br>$cells2[2]<br>
$cells2[3]<br>";
push (@rows, Tr (td (\@cells),(td (\@cells2))));
}
</code>
I get the error 'Can't use an undefined value as an ARRAY reference at
search.cgi line 139.'

My questions, why would adding that code at the beginning cause that
error and how can I fix it?

Any ideas/suggestions greatly appreciated.
Jim
 
J

J. Gleixner

JimJx said:
Hi all,

I have what seems to me to be a strange problem....

I have the script below:

Which isn't terribly helpful, because you don't say what $type,
$start, etc. is so we have no idea what SQL is being tried.
[...]
My questions, why would adding that code at the beginning cause that
error and how can I fix it?

Any ideas/suggestions greatly appreciated.

Look at your SQL and the results.

use Data::Dumper;

#... your code
print "SQL=$query\n";
my $tbl_ref = $dbh->selectall_arrayref ($query);
print 'Results:', Dumper( $tbl_ref );

Something isn't what you think it is.
 
P

Paul Lalli

It works great. However if I change it to:
<code>
if ($search = '#') {

You realize of course that this line *assigns* $search to be equal to
'#', and then returns true, meaning that this if statement (and none
of the else clauses) will ALWAYS be executed, right?

You meant to have an 'eq' here, just like all the other if conditions
had, not an '='.
my $tbl_ref = $dbh->selectall_arrayref ($query);

$dbh->disconnect ( );

# Line 139 is the FOR below......

for (my $i = 0; $i < $per_page && $i < @{$tbl_ref}-1; $i+=2) {
I get the error 'Can't use an undefined value as an ARRAY
reference at search.cgi line 139.'

You are not checking your DBI calls for errors. You are assuming they
all work fine. Perl doesn't tell you there's a problem unless you ask
it to. I recommend turning on RaiseError in your connect statement

my $dbh = DBI->connect($dsn, $user, $pass, { RaiseError => 1} );

Or you can turn it on after the fact:
$dbh->{RaiseError} = 1;

Or you can manually check the results of every single database call:
my $tbl_ref = $dbh->selectall_arrayref($query);
die $dbh->errstr if $dbh->err();


Paul Lalli
 
J

John W. Krahn

JimJx said:
I have what seems to me to be a strange problem....

I have the script below:

<code>
if ($type eq 'alpha') {
$query = sprintf (
"SELECT name, address, city, phone
FROM valley
where name like '$search%'
ORDER BY name LIMIT %d,%d",
$start - 1, # number of records to skip
$per_page + 1); # number of records to select
} elsif ($type eq '') {
$query = sprintf (
"SELECT name, address, city, phone
FROM valley
where keywords like '%$search%'
ORDER BY name LIMIT %d,%d",
$start - 1, # number of records to skip
$per_page + 1); # number of records to select
}
my $tbl_ref = $dbh->selectall_arrayref ($query);

[ SNIP ]

</code>

It works great.

Are you sure that that "works great"?

You have variable interpolation inside sprintf() format strings and you are
using '%' without properly escaping it. You probably want this instead:

if ( $type eq 'alpha' ) {
$query = sprintf
"SELECT name, address, city, phone
FROM valley
where name like '%s%%'
ORDER BY name LIMIT %d,%d",
$search,
$start - 1, # number of records to skip
$per_page + 1; # number of records to select
} elsif ( $type eq '' ) {
$query = sprintf
"SELECT name, address, city, phone
FROM valley
where keywords like '%%%s%%'
ORDER BY name LIMIT %d,%d",
$search,
$start - 1, # number of records to skip
$per_page + 1; # number of records to select
}
my $tbl_ref = $dbh->selectall_arrayref( $query );



John
 
J

JimJx

JimJx said:
I have what seems to me to be a strange problem....
I have the script below:
<code>
if ($type eq 'alpha') {
$query = sprintf (
"SELECT name, address, city, phone
FROM valley
where name like '$search%'
ORDER BY name LIMIT %d,%d",
$start - 1, # number of records to skip
$per_page + 1); # number of records to select
} elsif ($type eq '') {
$query = sprintf (
"SELECT name, address, city, phone
FROM valley
where keywords like '%$search%'
ORDER BY name LIMIT %d,%d",
$start - 1, # number of records to skip
$per_page + 1); # number of records to select
}
my $tbl_ref = $dbh->selectall_arrayref ($query);
[ SNIP ]

It works great.

Are you sure that that "works great"?

You have variable interpolation inside sprintf() format strings and you are
using '%' without properly escaping it. You probably want this instead:

if ( $type eq 'alpha' ) {
$query = sprintf
"SELECT name, address, city, phone
FROM valley
where name like '%s%%'
ORDER BY name LIMIT %d,%d",
$search,
$start - 1, # number of records to skip
$per_page + 1; # number of records to select
} elsif ( $type eq '' ) {
$query = sprintf
"SELECT name, address, city, phone
FROM valley
where keywords like '%%%s%%'
ORDER BY name LIMIT %d,%d",
$search,
$start - 1, # number of records to skip
$per_page + 1; # number of records to select}

my $tbl_ref = $dbh->selectall_arrayref( $query );

John

John, the %$search and %$search% that I think you are referring to are
correct in this case. The $search% means match anything with the
search term at the beginning, and similarly, the %$search% means match
if the term is found anywhere.....

Paul, good catch on the eq, guess that is what happens after looking
at code for so long, it all starts to look the same.... I turned on
the error checking and did not get any errors there so the eq was it.

Thanks guys for taking the time to help me out, I really appreciate
it.

Jim
 
P

Paul Lalli

JimJx said:
I have what seems to me to be a strange problem....
I have the script below:
<code>
if ($type eq 'alpha') {
$query = sprintf (
"SELECT name, address, city, phone
FROM valley
where name like '$search%'
ORDER BY name LIMIT %d,%d",
$start - 1, # number of records to skip
$per_page + 1); # number of records to select
} elsif ($type eq '') {
$query = sprintf (
"SELECT name, address, city, phone
FROM valley
where keywords like '%$search%'
ORDER BY name LIMIT %d,%d",
$start - 1, # number of records to skip
$per_page + 1); # number of records to select
}
my $tbl_ref = $dbh->selectall_arrayref ($query);
[ SNIP ]

It works great.

Are you sure that that "works great"?

You have variable interpolation inside sprintf() format strings

Nothing about Perl prevents that. There's no reason to think that
wouldn't "work great"
and you are using '%' without properly escaping it.

Yes, but if the character following the % isn't a valid format
specifier, it prints out as a % literal anyway:

printf "%d, %'\n", 5; #prints 5, %'

In short, there's nothing "wrong" with that part of the OP's code. It
could be made to look better, as you suggest, but there's nothing
about it that suggests it doesn't work.

Paul Lalli
 
J

John W. Krahn

Paul said:
JimJx said:
I have what seems to me to be a strange problem....
I have the script below:
<code>
if ($type eq 'alpha') {
$query = sprintf (
"SELECT name, address, city, phone
FROM valley
where name like '$search%'
ORDER BY name LIMIT %d,%d",
$start - 1, # number of records to skip
$per_page + 1); # number of records to select
} elsif ($type eq '') {
$query = sprintf (
"SELECT name, address, city, phone
FROM valley
where keywords like '%$search%'
ORDER BY name LIMIT %d,%d",
$start - 1, # number of records to skip
$per_page + 1); # number of records to select
}
my $tbl_ref = $dbh->selectall_arrayref ($query);
[ SNIP ]
</code>
It works great.
Are you sure that that "works great"?

You have variable interpolation inside sprintf() format strings

Nothing about Perl prevents that. There's no reason to think that
wouldn't "work great"
and you are using '%' without properly escaping it.

Yes, but if the character following the % isn't a valid format
specifier, it prints out as a % literal anyway:

printf "%d, %'\n", 5; #prints 5, %'

And a warning message:

$ perl -Mwarnings -Mstrict -e "my \$x = q[aa]; printf qq[variable '%\$x%' five
%d seven %d\n], 5, 7"
Invalid conversion in printf: "%a" at -e line 1.
Invalid conversion in printf: "%'" at -e line 1.
variable '%aa%' five 5 seven 7


And if it is valid then you get uninitialized values at the end of the list:

$ perl -Mwarnings -Mstrict -e "my \$x = q[dd]; printf qq[variable '%\$x%' five
%d seven %d\n], 5, 7"
Invalid conversion in printf: "%'" at -e line 1.
Use of uninitialized value in printf at -e line 1.
variable '5d%' five 7 seven 0

In short, there's nothing "wrong" with that part of the OP's code. It
could be made to look better, as you suggest, but there's nothing
about it that suggests it doesn't work.



John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top