Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does DBI's do method return "0E0" if zero rows were affected?

Tags:

perl

dbi

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?

like image 636
simbabque Avatar asked Nov 13 '12 10:11

simbabque


1 Answers

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.)

like image 118
ikegami Avatar answered Oct 27 '22 09:10

ikegami