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 件のコメント:

木下雄一朗 さんのコメント...

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

tsuchiya さんのコメント...

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

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

木下雄一朗 さんのコメント...

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

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

tsuchiya さんのコメント...

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

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

木下雄一朗 さんのコメント...

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

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

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

tsuchiya さんのコメント...

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

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

木下雄一朗 さんのコメント...

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

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