ようこそゲストさん

mitc - 日記

2007/05/16(水) dBugをPostgreSQLに対応させてみた

はてブ 2007/05/16 15:15 PHPmiff
昨日からdBugを使っていますが,やっぱりPostgreSQLのリソースが表示できないのは気持ち悪いです.
私の環境が悪いのかわかりませんが,とにかくエラーメッセージが表示されていることですしソースコードを覗いてみました.
その結果,dBug*1のデータベース表示機能は,そもそもMySQL用に書かれていて他のDBのはオマケであることがわかりました.

簡単に書くと,関数の使用時に
// $dbには,MySQLなら"mysql",PostgreSQLなら"pg"が入っている
call_user_func($db."_data_seek",$var,0);
こんな感じで接頭辞だけ変えて関数を呼び出すことで対応させようとしているんですが,
PHPのMySQL関数とPostgreSQL関数には,名前レベルでそれほど互換性があるわけではなく,
存在しない関数を呼び出そうとしてしまっているのです.
この問題を完全に解決するには,dBug内でラッパ関数を作って差異を吸収するか,
関数のネームテーブルを作ってそれ経由で呼び出すか*2しないといけませんが,
とりあえずそれほど元コードを変えないで対応してみました*3

PostgreSQL関数
MySQL関数

dBug公式
This software is distributed under the GNU General Public License
とのことなので,公式に対応されるまでの繋ぎとして改変版をここに置いときます*4
お約束ですが,このコードを用いて起こった一切の損害は保証しません.
GPLの改変なので,これもGPLですね.
公式ですら
dBug has been downloaded 5855 times*5
なので需要があるのか無いのか謎ですが.

dBug.zip

*1 : 書いた時点のバージョンは1.2

*2 : 両者にそれほど違いはありませんが

*3 : PostgreSQLに対応させただけですよ.

*4 : 拙い英語ですが作者の方にはメール送りました.元々対応させるつもりだったのかよくわからないので迷惑だったかも…….

*5 : 2007/5/16 15:09現在

ソースコード改変

pg_data_seekは存在しないので,代わりにpg_result_seekを使う
pg_result_seek
// 313行
// ここでは,表示するためにシークしたデータベースリソースのカレント行を頭に戻している
 - call_user_func($db."_data_seek",$var,0);

 + if ($db == "pg") {
 + 	call_user_func($db."_result_seek",$var,0);
 + } else {
 + 	call_user_func($db."_data_seek",$var,0);
 + }

pg_fetch_arrayにPG_ASSOCという定数は使えないので,代わりにPGSQL_ASSOCを使う.
pg_fetch_array
// 300行
// $iで読み込む行番号の指定も行う
 - $row=call_user_func($db."_fetch_array",$var,constant(strtoupper($db)."_ASSOC"));

 + if ($db == "pg"){
 + 	$row=call_user_func($db."_fetch_array",$var,$i,constant("PGSQL_ASSOC"));
 + } else {
 + 	$row=call_user_func($db."_fetch_array",$var,constant(strtoupper($db)."_ASSOC"));
 + }
pg_fetch_fieldという関数は存在しないので,
代わりにpg_field_nameを使う.
pg_field_name
// 295行
 - $field[$i]=call_user_func($db."_fetch_field",$var,$i);

 + if($db == "pg") {
 + 	$field[$i]->name=call_user_func($db."_field_name",$var,$i);
 + } else {
 + 	$field[$i]=call_user_func($db."_fetch_field",$var,$i);
 + }

$field[$i]について

元々のmysql_fetch_fieldは,フィールド情報を構造体で返している.
$field[$i]の値は,フィールド名をpg_fetch_arrayのキーにアクセスするためだけに使っていて,
アクセスしているメンバは$field[$i]->nameのみ.
// 303-308行
for($k=0;$k<$numfields;$k++) {
	$tempField=$field[$k]->name;
	$fieldrow=$row[($field[$k]->name)];
	$fieldrow=($fieldrow=="") ? "[empty string]" : $fieldrow;
	echo "<td>".$fieldrow."</td>\n";
}
PostgreSQLには,全く同じような値を返す関数が無いので,
上のコードでは,勝手にnameをでっちあげてそこにフィールド名を入れてます.
この操作は,文法的に正しくない気がします*6
とりあえず元ソースからの変更箇所を多くしたくなかったので.

二箇所変更で多分文法的に問題無い方法

// 295行ら辺をこんな感じに書き換え
$tmpFieldName = "";

if($db == "pg") {
	$tmpFieldName = call_user_func($db."_field_name",$var,$i);
} else {
	$tmpFieldName = call_user_func($db."_fetch_field",$var,$i);
	$tmpFieldName = $tmpFieldName->name;
}
$field[$i] = $tmpFieldName;
下側
// 303-308行をこんな感じに書き換え
for($k=0;$k<$numfields;$k++) {
	$tempField=$field[$k];
	$fieldrow=$row[($field[$k])];
	$fieldrow=($fieldrow=="") ? "[empty string]" : $fieldrow;
	echo "<td>".$fieldrow."</td>\n";
}

*6 : 詳しくはわからないですが,少なくとも感覚的にはおかしな操作です

その他メモ

関係ありませんが,
* NOTE!
* ==============
* forceType is REQUIRED for dumping an xml string or xml file
* new dBug ( $strXml, "xml" );
らしいです.


名前:  非公開コメント   

E-Mail(任意/非公開):
URL(任意):
  • TB-URL  http://mitc.s279.xrea.com/adiary.cgi/026/tb/