2010-03-22

『売上猫くん on MySQL』開発日記 - 番外3 - 0を書き込みできない

売上明細テーブル( vw_salesdtls)のInt型のフィールド(balanceFlg)に値を書き込もうとする。他の値は書き込みできるのだが、“0”の書き込みが実行できない。 ログで何が起こっているのか確認する。

Commitに失敗している場合はバイナリログには記録されないので、mysqlbinlog は使えない。 そこで、一般ログというものを、

mysql> set global general_log="ON";

で作成してみる。 以下、1を立てて成功したログと、0で失敗したログ(一部抜粋)。

【1立てで成功】
9 Query SELECT ID,`売上番号`,balanceFlg, ~略~ FROM vw_salesdtls WHERE ID=8340 FOR UPDATE
9 Query UPDATE vw_salesdtls SET balanceFlg=1 WHERE ID=8340

【0立てで失敗】
8 Query SELECT ID,`売上番号`,balanceFlg, ~略~ FROM vw_salesdtls WHERE ID=8341

失敗したほうでは、なぜか FOR UPDATE 以下が発行されず、当然これでは更新できない。 当初はInnoDB側に何か問題があるのかと疑ったが、FileMakerが適切なクエリを発行していないことがわかった。 ちなみに、類似した他のテーブルでは、1、0の値に関係なく、更新(Update)は成功する。

いろいろとやってみた。FMのファイルを修復したり、レイアウトモードにして数字の書式を変更してみたり、フィールド定義を眺めてみたり。 そして、これが FileMaker のバグだと判明。 なんと、FileMaker は 空欄(null)→0 への変更は変更と認識しない、null=0 と認識するのである。 更新と認識しないので、 Update が発行されない。 恐ろしい。

結論
ということで、null と 0 を区別して扱う必要がある場合は、非常に注意が必要だ。 0 を参照キーするのは極力避けるべきた。 MySQL側で初期値を0に設定しておく、というのは一案かもしれない。
ちなみに、上述のように「null=0 と認識」するので、0→空欄lに変更を行っても、コミットすると 0 のままである。



関連リンク:『売上猫くん on MySQL』開発日記の記事一覧

7 件のコメント:

  1. 私の手元では、InnoDB 内の int, tinyint などのデータ型のフィールドで、null→0、0→null の更新は正常に行われるようです。すっぴんのデータベースで再現するかを確認すると良いのではないかと思います。

    返信削除
  2. まっさらなレイアウト上にフィールドを配置してコミットしても、別のテーブルのInt/Tinyで試しても、結果は同じ=更新されないですね。

    木下さんのFMのVerはおいくつですか?
    うちは、10.0v1です。

    返信削除
  3. FileMaker Pro Advanced 10.0v3 です。まずはアップデータを当ててみる方が良いかもしれません。

    その上で、新規に空のファイルを作成して、外部データソースの定義、という流れでさらの状態で試してみると良いかもしれません。

    返信削除
  4. なるほど、おそらく、v3あたりでこそっと修正したんですね。あとでアップグレードしてみます。

    猫は不特定多数ユーザを想定してるので、一番低いVer=v1で開発・テストしてます。

    返信削除
  5. アップデータの Read Me の「FileMaker Pro 10.0v3 の新機能」に下記の記載がありました。

    8. 外部データソース
     •外部データソーステーブルに追加された FileMaker ベースの数字フィールドが 0 を表示しない問題を解決しました。

    ESS を使うなら、アップデートは必須ですね。

    返信削除
  6. 最新のパッチを当てたいのはわかるのですが、不特定多数ユーザの使用を前提とすると、支障が無い範囲でバージョンの低いところからサポートするのがユーザにはよろしいかと。

    今回の場合、元記事にも書きましたが、0とnullを区別する必要がないのであれば、MySQLあるいはFM側で初期値を0と設定すればこのバグは回避できるかと。

    返信削除
  7. >ESS を使うなら、アップデートは必須ですね。
    これは一般論です。

    製品のサポート条件は各社のポリシーですから、そのことについてコメントすることはありません。

    返信削除