web-dev-qa-db-ja.com

影響を受けた行がゼロの場合、DBIのdoメソッドが「0E0」を返すのはなぜですか?

次の例のようなコードを実行すると、問題が発生しました。

my $rows = $dbh->do('UPDATE table SET deleted=NOW() WHERE id=?', undef, $id) 
  or die $dbh->errstr;
if (!$rows) {
  # do something else
}

docs は、doが影響を受ける行数を返すと述べているので、それでうまくいくと思いました。

単一のステートメントを準備して実行します。影響を受けた行数、またはエラーの場合はundefを返します。戻り値-1は、行数が不明、適用不可、または使用不可であることを意味します。

結局のところ、私は間違っていました。デバッグしたところ、$rowsが実際には文字列0E0を保持していることがわかりました。これは、もちろん真の値です。私はさらにドキュメントを掘り下げて、このコードを見ました:

デフォルトのdoメソッドは、論理的に次のようになります。

  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
  }

そこにそれがある。 0E0を返します。なぜそうなるのかわかりません。誰か知っている?

20
simbabque

これは真の値であるため、エラー時に返される偽の値と区別できますが、数値的にはゼロ(警告なし)であるため、影響を受けるレコードの数と同じです。

_$ 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
_

レコードが影響を受けていないときに成功時に_0_が返された場合、definedを使用してエラーをチェックする必要があります。これは、真実をテストするよりもはるかに便利ではありません(例:foo() or die; )。

その他の真のゼロ 。 (_"0x0"_を無視します;警告します。)

28
ikegami