miau's blog?

CakePHP + PostgreSQL の環境で test suite を実行すると warning が出る件

今回の CakePHP 案件では、ライセンスの問題なんかもあって元々インストールされている PostgreSQL 7.4 を利用することになりました。

CakePHP って MySQL 以外の対応がいいかげんだったりするからどうだろうなー?と思いつつ開発を始めようとしたら、いきなり test suite の実行で warning が出たのでその対応について。(PostgreSQL 8.2.0 以降限定ですが。)




■現象

cake bake で作ったモデル&テストケースを実行すると、以下のような warning が発生。

>cake testsuite app all


Welcome to CakePHP v1.2.1.8004 Console
---------------------------------------------------------------
App : app
Path: E:/Workspace/XXXXXX/pleiades/xampp/htdocs/workspace/cms/app
---------------------------------------------------------------
CakePHP Test Shell
---------------------------------------------------------------
Running app all
All App Tests
<pre><p style = "text-align:left"><b>Query:</b> DROP TABLE "test_suite_users";
</p></pre>Exception 1!
Unexpected PHP error [pg_query(): Query failed: ERROR: table "test_suite_users" does not exist] severity [E_WARNING] in [E:\Workspace\XXXXXX\pleiades\xampp\htd
ocs\workspace\cms\cake\libs\model\datasources\dbo\dbo_postgres.php line 148]
in start
in userTestCase
in E:/Workspace/XXXXXX/pleiades/xampp/htdocs/workspace/cms\app\tests\cases\models\user.test.php
Exception 2!
Unexpected PHP error [<span style = "color:Red;text-align:left"><b>SQL Error:</b> ERROR: table "test_suite_users" does not exist</span>] severity [E_USER_WARNING] in [E:\Workspace\XXXXXX\pleiades\xampp\htdocs\workspace\cms\cake\libs\model\datasources\dbo_source.php line 514]
in start
in userTestCase
in E:/Workspace/XXXXXX/pleiades/xampp/htdocs/workspace/cms\app\tests\cases\models\user.test.php
1/1 test cases complete: 3 passes, 2 exceptions.

なんだかテスト開始時に DROP TABLE にコケている様子。

これはただの Warning で、テスト自体は実行されているので気にしなくていいといえばいいんですが・・・今回はレポートもちゃんと出したいので Warning は取り除いておきたいところ。

■調査

たぶん MySQL だと発生しないエラーなんだろうなー、ということで、
・cake/libs/model/datasources/dbo/dbo_mysql.php(DboMysqlBase クラス)
・cake/libs/model/datasources/dbo/dbo_postgres.php(DboPostgres クラス)
のを見比べてみると、dropSchema() という怪しげなメソッドが DboMysqlBase クラスだけで定義されている状態。DboPostgres は DboSource を継承しているので、DboMysqlBase と DboSource の dropSchema() を見比べると・・・MySQL のほうだけ DROP TABLE の部分が DROP TABLE IF EXISTS になっているっぽい。だから MySQL だと存在しないテーブルでもエラーにならないのね。

PostgreSQL だと IF EXISTS って使えないのかなー?と調べてみると、8.2.0 から使えるようになっている様子。今回は開発環境と CI 環境は 8.3 系でいこうと思ってるから、とりあえず IF EXISTS で対策しちゃおう。

ということで、dbo_postgres.php に以下のメソッドを追加。(dbo_mysql.php と場所をそろえるなら alterSchema() の後あたりに。)

/**
* Generate a PostgreSQL "drop table" statement for the given Schema object
*
* @param object $schema An instance of a subclass of CakeSchema
* @param string $table Optional. If specified only the table name given will be generated.
* Otherwise, all tables defined in the schema are generated.
* @return string
*/
function dropSchema($schema, $table = null) {
if (!is_a($schema, 'CakeSchema')) {
trigger_error(__('Invalid schema object', true), E_USER_WARNING);
return null;
}
$out = '';
$v = pg_version($this->connection);
foreach ($schema->tables as $curTable => $columns) {
if (!$table || $table == $curTable) {
if ((bool)version_compare($v['client'], "8.2", ">=")) {;
$out .= 'DROP TABLE IF EXISTS ' . $this->fullTableName($curTable) . ";\n";
} else {
$out .= 'DROP TABLE ' . $this->fullTableName($curTable) . ";\n";
}
}
}
return $out;
}

一応バージョンが 8.2 以上だったら〜、というチェックも入れているので、8.2 未満でもエラーにはならないはずです。pg_version() でクライアント側のバージョンしか取れていなかったので、そこで判定している手抜きですが。

で、テストを実行すると・・・。

>cake testsuite app all


Welcome to CakePHP v1.2.1.8004 Console
---------------------------------------------------------------
App : app
Path: E:/Workspace/XXXXXX/pleiades/xampp/htdocs/workspace/cms/app
---------------------------------------------------------------
CakePHP Test Shell
---------------------------------------------------------------
Running app all
All App Tests
1/1 test cases complete: 3 passes.

まあ OK だけど、いきなりこれじゃあ先が思いやられるなぁ。
posted at 03:57:33 on 2009-02-23 by miau - Category: PHP No Trackbacks - Permalink

TrackBack

このエントリにトラックバックはありません
現在トラックバックは受け付けていません。

Comments

No comments yet

Add Comments

現在コメントは受け付けていません。
お手数ですが、 こちら のコメント欄にでも記載していただければと思います。