PHP adodbのレコードセットオブジェクトが終端に移動する
PHP5.3にバージョンアップ後、動いていないバッチを発見。
動作していないコード部分
<?php class Foo{ protected $_db; protected $_record_set; function hoge(){ $this->_db = ADONewConnection( DB_DSN ); $this->_record_set = $this->_db->Execute( "select * from hoge" ); if( $this->_record_set == "" ){ return false; } while(true){ if( $this->_record_set->EOF ){ return; } $array = $this->_record_set->FetchRow(); } } } ?>
どうやら、取得レコードがあっても、カーソルがEOFとなっていてる模様です。
if( $this->_record_set->EOF ){ //検索結果があっても必ずEOFになっている return false; }
デバッグでEOFの状態を出力してみる。
function hoge(){ $this->_db = ADONewConnection( DB_DSN ); $this->_record_set = $this->_db->Execute( "select * from hoge" ); error_log( var_export($this->_record_set->EOF,1) ); if( $this->_record_set == "" ){ } error_log( var_export($this->_record_set->EOF,1) ); … }
false
true
、、、
以下のオブジェクトと空文字列の比較演算後にEOF状態が変わることがわかりました。
if( $this->_record_set == "" ){
return false;
}
オブジェクトの変化内容を調べてみると
'fields' => (array) → 'fields' => false,
'EOF' => false, → 'EOF' => true,
'_currentRow' => 0, → '_currentRow' => 2,
の3つのプロパティの状態が変化。レコードcursorが終端になっっているようです。
巻き戻すと、、、
$record = $this->_record_set->FetchRow();
'fields' => (array)
'EOF' => false,
'_currentRow' => 0,
正常にレコードを取得できます。
IS_OBJECT == IS_STRINGが問題と踏んだので、少しだけインタプリタを調べました。
Zend/zend_operators.c
if (Z_TYPE_P(op1) == IS_OBJECT) { if (Z_OBJ_HT_P(op1)->get) { op_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC); ret = compare_function(result, op_free, op2 TSRMLS_CC); zend_free_obj_get_result(op_free TSRMLS_CC); return ret; }
何やらオブジェクト側を操作しているようなので、おとなしくこちらが通るようにしてみる。
case TYPE_PAIR(IS_OBJECT, IS_NULL): ZVAL_LONG(result, 1); return SUCCESS;
if( $this->_record_set == NULL ){
return false;
}
とりあえず、以上で修正できました。
チラ裏
is_object()を利用したり、=== で型チェックしても正常に動作しました。
if( $object == "a" ) や if( "" == $object )にしてももちろん動作しません。
adodbのバージョンが古すぎる。。。最新のものでも試してみたい。