テーブルを動的に扱う方法について #18B!

こんにちは。モバイルファクトリーの千葉と申します。

今回DBIx::Skinnyを仕事で使わせてもらっている縁でエントリを担当させていただくことになりました。

18日目はDBIx::Skinnyでテーブルを動的に扱う方法について説明します。

DBの分割をする際などに、テーブルの構成は固定されているが、テーブル名は動的に指定したいという場合があると思います。

しかしDBIx::Skinnyでは使用するテーブルの名前や構成をあらかじめスキーマで定義しておく必要があるため、標準では未定義のテーブルに対して問い合わせをすることはできません(search_by_sqlについてはその限りではありませんが)。

そんなときは共通のスキーマをあらかじめ定義しておいて、実行時にそれを関連付けるという方法をとることができます。

package Proj::DB;
use DBIx::Skinny setup => +{
   dsn => 'dbi:SQLite:',
   username => '',
   password => '',
};

package Proj::DB::Schema;
use DBIx::Skinny::Schema;

# 共通スキーマの定義
install_table 'access_log' => schema {
   pk 'id';
   columns qw/id domain remote_host request status created_at/;
};

package main;

my $db = Proj::DB->new;

# テーブル作成
$db->do(q{ CREATE TABLE IF NOT EXISTS access_log_20091218 LIKE access_log });

# 作成したテーブルに共通スキーマの適用
$db->schema->schema_info->{access_log_20091218} = $db->schema->schema_info->{access_log};

# 通常のテーブルと同じように扱うことができる
$db->create('access_log_20091218', { id => 1, domain => 'example.com',
remote_host => '127.0.0.1', request => '/', status => 200 });
$db->update('access_log_20091218', { status => 500 }, { id => 1 });
$db->search('access_log_20091218', { id => 1 });
$db->delete('access_log_20091218', { id => 1 });

さらにこのテーブルのRowクラスも指定したいという場合はこのようにすることができます。

my $db = Proj::DB->new;

# あらかじめ定義しておいた共通Rowクラスと作成したテーブルをマッピング
$db->{row_class_map}->{access_log_20091218} = 'Proj::DB::Row::AccessLog';

my $row = $db->search('access_log_20091218', { id => 1 })->first;
print ref $row #=> 'Proj::DB::Row::AccessLog'

現在これらの処理をまとめたDBIx::Skinny::Mixin::ProxyTableというモジュールを開発中ですのでよろしくお願いします。

http://github.com/daijirow/p5-dbix-skinny-mixin-proxy_table

以上、簡単ですがDBIx::Skinnyでテーブルを動的に扱う方法について説明しました。

ありがとうございました。