ハマったので。
PHP 5.1.6
Oracle 10.2.3
にて。
PDO_OCIでPHPとOracleとを繋いでる環境でエラーじゃないけど、Warningが出た。
Warning: PDOStatement::fetch(): column X data was too large for buffer and was truncated to fit it in test.php on line XXX
VARCHAR2のカラムからデータを取得すると出た。
正常にデータが取得出来てるっぽかったけど、おしりの何バイトかが切れてた。
おぉ、trancateされてる。
色々調べてみたところ、全角文字が入ってるとダメだった。
さらに調べてみると、原因が分かった。
Oracle:SJIS
PHP:UTF-8
これが原因だった。
OracleはSJISなので、全角文字は2バイト。
PHPはUTF-8なので、全角文字は3バイト。
PDO_OCIの場合、テーブルのカラムの型と長さを参照してバッファを決めるようで。
全角文字が入っていた場合、そのバッファが溢れる事があるのです。
なんせ、2バイトだと思っていた全角文字が3バイトだったので。
VARCHAR2(20)のカラムに、全角文字が10文字入っていた場合、SJISならば20バイトなので、OK。
しかし、UTF-8だと30バイトになってしまうので、受け取る側のバッファが溢れてしまう、という事。
対応どうしようか・・・
と考え、
/etc/sysconfig/httpd
をちょっと編集してみた。
# cd /etc/sysconfig/
# vi httpd
export NLS_LANG=Japanese_Japan.UTF8
↓に変更
export NLS_LANG=Japanese_Japan.JA16SJIS
# /etc/rc.d/init.d/httpd restart
Warnningは出なくなったけど、文字化けした。
DBから取得してる根っこの部分でSJIS→UTF-8の変換をかけようかと考えたのですが、symfony+doctorineという事もあり、断念。
だって、調べるの面倒だから・・・
テーブルのカラム長の定義を1.5倍すれば回避出来るけど、運用案件では無理なので断念。
結果、PDO_OCIのソースをちょっと直して対応する事に。
# cd /usr/local/src
# cd PDO_OCI-1.0
# vi oci_statement.c
510行目付近に有る記述
col->maxlen = data_size;
↓
col->maxlen = data_size*1.5;
# ./configure
# make
# make install
PDOがOracleのテーブルのカラムの長さを取得してる部分で、その長さを1.5倍してあげれば大丈夫。
この対応方法が良いかどうかは疑問が残るが、とりあえずはこれで回避しよう。
でわ。