Catalyst::Model::DBIC で View が扱えない話。
素の DBIx::Class ならば特に問題はない。
package PgTables;
use base qw/DBIx::Class/;
__PACKAGE__->load_components(qw/Core DB/);
__PACKAGE__->connection('dbi:Pg:dbname=template1', 'fujiwara', '');
__PACKAGE__->table('pg_tables');
__PACKAGE__->add_columns( qw( schemaname tablename tableowner ));
__PACKAGE__->set_primary_key('tablename');
package main;
my $it = PgTables->search();
while(my $t = $it->next){
print $t->tablename, '|', $t->tableowner, "\n";
}
Catalyst::Model::DBIC では、view は扱えない。というのは、更にその親の DBIx::Class::Loader が view の定義を読み込んでくれないから。
具体的には、 DBIx::Class::Loader::Pg の _tables メソッド内で
my @tables = $is_dbd_pg_gte_131 ?
$dbh->tables( undef, $self->{_schema}, "", "table", { noprefix => 1, pg_noprefix => 1 } )
: $dbh->tables;
としている部分。ここで DBD::Pg::tables メソッドの第 4引数に 'table' を渡しているため。 '' を渡せば view も返ってくる。
@INC の先に上記の部分を改造した DBIx/Class/Loader/Pg.pm を置いてやれば、 view も読み込んで扱えるようになることは確認した。 ……とはいえ、ローカルな改造を施したモジュールを使うのも気持ち悪いし (バージョンアップなどへの追従も問題だし)、どうしたものか。
_tables メソッドを ovreride した自前クラスを作り、そっちを使うのが正統なんだろうが、 DBIx::Class::Loader は dsn から自動的に Loader::* (実装クラス) をロードするので 自前のクラスを使わせることができないという罠。
……もの凄く BK (Bad Knowhow) なやりかたは思いついた。マネしないでください。
あらかじめ、view と同じ構造の table を作っておく。
CREATE TABLE foo AS SELECT * FROM foo_v LIMIT 0;
で、DBIx::Class::Loader が foo の定義を読んでクラスを作ってくれた後で、
package Bar::Model::DBIC::Foo;
__PACKAGE__->table('foo_v');
table メソッドを使って、見に行くテーブル名を view にすげ替える。 ちゃんと使える.