I ran into a problem when running code similar to the following example:
my $rows = $dbh->do('UPDATE table SET deleted=NOW() WHERE id=?', undef, $id)
or die $dbh->errstr;
if (!$rows) {
# do something else
}
Since the docs state that do
returns the number of rows affected, I thought that would work.
Prepare and execute a single statement. Returns the number of rows affected or
undef
on error. A return value of-1
means the number of rows is not known, not applicable, or not available.
As it turns out, I was mistaken. When I debugged it, I saw that $rows
in fact holds the string 0E0
, which of course is a true-ish value. I dug in the docs further and saw this piece of code:
The default do method is logically similar to:
sub do { my($dbh, $statement, $attr, @bind_values) = @_; my $sth = $dbh->prepare($statement, $attr) or return undef; $sth->execute(@bind_values) or return undef; my $rows = $sth->rows; ($rows == 0) ? "0E0" : $rows; # always return true if no error }
There it is. It returns 0E0
. I just don't get why it would do that. Does anyone know?
It's a true value, so you can distinguish it from the false value it returns on error, yet it's numerically equal to zero (without warning), so it's still equal to the number of records affected.
$ perl -e'
for (undef, "0E0", 4) {
if ($_) {
printf "Success: %d rows affected\n", $_;
} else {
print "Error!\n";
}
}
'
Error!
Success: 0 rows affected
Success: 4 rows affected
If 0
was returned on success when no records are affected, you'd be forced to check errors using defined
, which is far less convenient than testing for truth (e.g. foo() or die;
).
Other true zeroes. (Ignore "0x0"
; it warns.)