Perl/DBIC
- DBIx::Class::Schemaを使ってみる
- アプリで使うDBスキーマの定義
- テーブルにマッピングさせるモジュールの定義
- データのinsert/select/update/delete
- searchメソッドで
- コネクションを分ける
- searchメソッドで色々
- nextメソッド/allメソッド
- search_likeメソッド
- searchメソッドでページング
- insertメソッドで色々
- 毎回のresultsetがうざい
- countメソッドで
- search_literalメソッドで
- resetメソッドで
- find_or_createメソッドで
- update_or_createメソッドで
- 1:多の関係を試す
- こんな感じでinsertもOK
- inflate/deflateを試す
- エラー発生ウワァァァァァァヽ(`Д´)ノァァァァァァン!な時
- SQLiteを使うときの注意
- DBIx::Class::Schema::Loaderを使ってみる
- 課題
- 参考
- とりあえず作ったモジュール
VERSION-0.05000での記述。http://search.cpan.org/~mstrout/DBIx-Class/
ドキュメントも当初に比べれば増えてきたし、そっち見たほうがよかばい。
まあ以下は簡単なまとめで。一通り使えるくらいは書きたい。
このサイトはWikiなので途中途中に色々追加したり修正したりしますからご注意を
DBIx::Class::Schemaを使ってみる
これからDBICではSchemaメインらしい。
使うテーブル作成SQL
1 |
create table user ( id int(10) NOT NULL auto_increment, name varchar(256) NOT NULL, PRIMARY KEY (id) ) ENGINE = InnoDB; |
アプリで使うDBスキーマの定義
下の例ではUserテーブルをこのアプリケーションで使うよって感じかね。
1 |
package Neko::Schema; use strict; use warnings; use base 'DBIx::Class::Schema'; __PACKAGE__->load_classes(qw/User/); 1; |
load_classesにテーブル指定しないと、Neko::Schema::*が指定されたとみなす。
1 |
__PACKAGE__->load_classes(); |
複数に分かれたスキーマを扱いたい場合はこんな感じ。
1 |
__PACKAGE__->load_classes( { 'Neko::Schema' => qw/ User /, 'Neko::OtherSchema' => qw/ Item / } ); |
テーブルにマッピングさせるモジュールの定義
1 |
package Neko::Schema::User; use strict; use warnings; use base 'DBIx::Class'; __PACKAGE__->load_components(qw/ PK::Auto::MySQL Core/); __PACKAGE__->table('user'); __PACKAGE__->add_columns(qw/id name/); __PACKAGE__->set_primary_key('id'); 1; |
データのinsert/select/update/delete
1 |
#! /usr/bin/perl use strict; use warnings; use Neko::Schema; my $schema = Neko::Schema->connect('dbi:mysql:nekodb','nekokak','******'); # insert $schema->resultset('User')->create({id => 1, name => 'nekokak'}); # select my $user = $schema->resultset('User')->find(1); print $user->id,"\n"; print $user->name,"\n"; # update $user->name('nomaneko'); $user->update; # select $user = $schema->resultset('User')->find(1); print $user->id,"\n"; print $user->name,"\n"; # delete $user->delete; |
これでUserテーブルに対して操作可能でつ。
searchメソッドで
findはプライマリキーに対してのselectなので、searchメソッドで
検索条件を指定してみる。
1 |
#! /usr/bin/perl use strict; use warnings; use Neko::Schema; my $schema = Neko::Schema->connect('dbi:mysql:nekodb','nekokak','******'); my $it = $schema->resultset('User')->search({name => 'nekokak'}); while ( my $user = $it->next ) { print $user->id,':',$user->name,"\n"; } |
イテレータで受け取った場合は、nextメソッドとかfirstメソッドでデータを取り出す。
CDBIと同じだけど、返りをスカラーで受け取るとイテレータに、配列で受け取ると
配列にしたデータを返してくれる。
1 |
#! /usr/bin/perl use strict; use warnings; use Neko::Schema; my $schema = Neko::Schema->connect('dbi:mysql:nekodb','nekokak','******'); #my $it = $schema->resultset('User')->search({name => 'nekokak'}); my @no_it = $schema->resultset('User')->search({name => 'nekokak'}); for my $user ( @no_it ) { print $user->id,':',$user->name,"\n"; } |
でも、これは必要ないデータまでとってきてくれたりするので、イテレータ使うべし。
コネクションを分ける
複数のコネクションが必要なら、
1 |
my $schema = Neko::Schema->connect('dbi:mysql:nekodb','nekokak','******'); my $schema2 = Neko::Schema->connect('dbi:mysql:nekodb','nekokak','******'); |
と、するだけぽい。
searchメソッドで色々
例えばidが5以上のデータをとりたいな〜って思った時なんか、
1 |
my $it = $schema->resultset('User')->search({id => { '>' => 5}}); |
例えばidが5以上でnameがnomanekoのデータがほしいなぁと思ったとき、
1 |
my $it = $schema->resultset('User')->search({id => { '>' => 5},name => 'nomaneko'}); |
例えばidが1,3,5,7,9のデータがほしいなぁと思ったとき、
1 |
my $it = $schema->resultset('User')->search({id => [1,3,5,7,9]}); |
これ、ちゃんとid in (1,3,5,7,9)にしてくれるっぽい。
してくれないみたい。。
1 |
SELECT me.id, me.name FROM test me WHERE ( ( ( id = ? ) OR ( id = ? ) OR ( id = ? ) OR ( id = ? ) OR ( id = ? ) ) ) : 1 3 5 7 9 |
こんなSQLにされてた。
↓(追記)
hideさんからの情報で、
1 |
$it = $schema->resultset('User')->search({id => {'in' =>[1,2,3,4,5]}}) |
とすれば、
1 |
SELECT me.id, me.name, me.passwd FROM user me WHERE ( id IN ( ?, ?, ?, ?, ? ) ): 1 2 3 4 5 |
このようなSQLが実行されました。
hideさんthanks!
例えばnameがnekokakでないデータがほしいなぁと思ったとき、
1 |
my $it = $schema->resultset('User')->search({name => {'!=' , 'nekokak'}}); |
例えばorder byでidのでかい順番にデータ取得したいなぁと思ったとき、
1 |
my $it = $schema->resultset('User')->search({},{order_by => 'id DESC'}); |
ポイントは初めの引数は検索条件になるからorder_byは第二引数にすっこと。
例えばgroup byでnameカラムの同一データを絞り込みたいなぁと思ったとき、
1 |
my $it = $schema->resultset('User')->search({},{group_by => 'name'}); |
例えばnameにnekoが含まれ、idが10以上のデータがほしいなぁと思ったとき、
1 |
my $it = $schema->resultset('User')->search({id => {'>' => 10},name => {'like', '%neko%'}}); |
(id = 1 and name = 'nekokak') or name = 'nomaneko'みたいなWhere句もOK
1 |
my $it = $schema->resultset('User')->search({ -or => [ -and => [id => 1,name=>'nekokak'], name => 'nomaneko', ], }); |
こんな感じで複雑な検索条件も指定できまつ
nextメソッド/allメソッド
nextメソッドはイテレータ的使い方をする
searchメソッドで複数レコード取ってきて、updateかます例。
1 |
my $it = $schema->resultset('User')->search(); while ( my $user = $it->next ) { $user->name('nomaneko2'); $user->update; } |
allメソッドの場合はこんなの
1 |
my $it = $schema->resultset('User')->search(); for my $user ( $it->all ) { $user->name('nomaneko2'); $user->update; } |
allメソッドの場合は検索結果の配列を返す。
search_likeメソッド
例えばnameにnekoが含まれるものがほしいなぁと思ったとき、
1 |
my $it = $schema->resultset('User')->search_like({name => '%neko%'}); |
でも、基本的にsearchメソッドでもできるしsearch使えばいいっぽい。
searchメソッドでページング
10件ずつ表示みたいな、
1 |
my $it = $schema->resultset('User')->search({},{row => 10}); my $p = $it->page(1); while ( my $user = $p->next ) { print $user->id,':',$user->name,"\n"; } |
$it->page(1);をせずに$itをnextメソッドでガリガリまわすと全て取れる罠。
それが嫌な場合はページを指定するべし。
1 |
my $it = $schema->resultset('User')->search({},{page => 1,row => 10}); |
2ページ目に進みたい時は
1 |
my $p = $it->page(2); |
とセットするだけ。
insertメソッドで色々
例えば、
1 |
my $l = $schema->resultset('User')->create({id => 25, name => "nomaneko"}); |
こんな感じで、データをinsertした時、戻りを受け取っておくと、
1 |
print $l->last_insert_id,"\n"; |
と、最後にinsertかましたプライマリキーの値をとれる。
意地悪的に、こうする、
1 |
my $l = $schema->resultset('User')->create({id => 26, name => "nomaneko"}); $schema->resultset('User')->create({id => 27, name => "nomaneko"}); print $l->last_insert_id,"\n"; |
するとちゃんと27が取れてくる。負けますた。
コネクションを分けてみる、
1 |
my $schema = Neko::Schema->connect('dbi:mysql:nekodb','nekokak','******'); my $schema2 = Neko::Schema->connect('dbi:mysql:nekodb','nekokak','******'); my $l = $schema->resultset('User')->create({id => 28, name => "nomaneko"}); $schema->resultset('User')->create({id => 29, name => "nomaneko"}); $schema2->resultset('User')->create({id => 30, name => "nomaneko"}); print $l->last_insert_id,"\n"; |
当然29が取れますた。
毎回のresultsetがうざい
1 |
my $u = $schema->resultset('User'); |
こうすりゃ$u経由でsearchとかでける。
countメソッドで
単純にUserテーブルのカウントをとりたい場合、
1 |
my $n = $schema->resultset('User'); my $count = $n->count({}); print $count,"\n"; |
これだけ。
nameがnomanekoのユーザのカウントをとりたい場合、
1 |
my $count = $n->count({name => 'nomaneko'}); |
そう、これだけ。
nameでnomaが頭につくユーザのカウントをとりたい場合、
1 |
my $count = $n->count({name => {'like','noma%'}}); |
ただ、これだけ。
search_literalメソッドで
自分でBind条件設定したい場合、
1 |
my $n = $schema->resultset('User'); my $where = 'id = ? AND name = ?'; my @bind = (9,'nekokak'); my $it = $n->search_literal($where,@bind); while ( my $user = $it->next ) { print $user->id,':',$user->name,"\n"; } |
こんな感じでOK。でも、あんまり使わない希ガス。
resetメソッドで
イテレータで行をすすめててはじめに戻したい場合、
1 |
my $it = $n->search(); my $i; while ( my $user = $it->next ) { if ( $i == 2 ) { $it->reset; } print $user->id,':',$user->name,"\n"; $i++; } |
ひそかに便利かも。
find_or_createメソッドで
アプリ作ってたら絶対にこの手のシチュエーション発生するよね、
あればselectしてなければinsert
1 |
my $user = $n->find_or_create({id => 23,name=>"mogeneko"}); print $user->id,':',$user->name,"\n"; |
update_or_createメソッドで
むしろこっちの方がfind_or_createよりも頻度高し
1 |
$n->update_or_create({id => 24,name=>"mogeneko1"}); |
レコードが存在しなければinsertしてあればupdateしてくれるスグレモノ。
1:多の関係を試す
当然これができないと問題外。ちなみにDBIx::ClassのPODは分かりにくかったりする。
試すテーブルは初めのuserテーブルとこのbookmarkテーブル。
1 |
create table bookmark ( id int(10) NOT NULL auto_increment, user_id int(10) NOT NULL, url text NOT NULL, PRIMARY KEY (id), INDEX (user_id), FOREIGN KEY (user_id) REFERENCES user(id) ) ENGINE = InnoDB; |
user:bookmark=1:nの関係でつ。
bookmarkテーブルにマッピングさせるモジュール
Bookmarkテーブルは1userテーブルに属する為、belongs_toでリレーションを設定
1 |
package Neko::Schema::Bookmark; use strict; use warnings; use base 'DBIx::Class'; __PACKAGE__->load_components(qw/ PK::Auto::MySQL Core/); __PACKAGE__->table('bookmark'); __PACKAGE__->add_columns(qw/id user_id url/); __PACKAGE__->set_primary_key('id'); __PACKAGE__->belongs_to(user_id => 'Neko::Schema::User'); 1; |
userテーブルにマッピングしてたモジュールにリレーションの追加
userテーブルはbookmarkを多数もつ為、Neko::Schema::Userモジュールにhas_manyで設定
1 |
__PACKAGE__->has_many(bookmark => 'Neko::Schema::Bookmark', 'user_id'); |
スキーマの修正
Bookmarkテーブルが追加されたから、Neko::Schemaのload_classesの部分を
1 |
__PACKAGE__->load_classes(qw/User Bookmark/); |
こうする。
Userからのselect
Userからbookmarkを検索する場合、
1 |
my $schema = Neko::Schema->connect('dbi:mysql:nekodb','nekokak','******'); my $userit = $schema->resultset('User')->search({name => 'nekokak'}); while ( my $user = $userit->next ) { my $bookmark = $user->bookmark; while ( my $bkit = $bookmark->next ) { print $bkit->id,':',$user->id,':',$bkit->url,"\n"; } } |
Bookmarkからのselect
BookmarkからUserを検索する場合、
1 |
my $bkit = $schema->resultset('Bookmark')->search(); while ( my $bookmark = $bkit->next ) { my $user = $bookmark->user_id; print $user->id,':',$bookmark->id,':',$user->name,':',$bookmark->url,"\n"; } |
Userからの検索とは異なりBookmarkには1つのUserしか存在しない為、
$bookmark->user_id;
とするだけで、該当のデータが取得される。
こんな感じでinsertもOK
1 |
my $i = $schema->resultset('User')->create({name => 'nomaneko'}); $schema->resultset('Bookmark')->create({ user_id => $i->last_insert_id , url => 'http://d.hatena.ne.jp/nomaneko/'} ); |
inflate/deflateを試す
loginテーブルを作ります。このテーブルはuserテーブルと1対1の関係です。
1 |
create table login ( id int(10) NOT NULL, login_time DATETIME, PRIMARY KEY (id), FOREIGN KEY (id) REFERENCES user(id) ) ENGINE = InnoDB; |
loginテーブルにマッピングさせるモジュール
might_haveメソッドでloginテーブルのidとuserテーブルのリレーションを構築
inflate_columnメソッドでlogin_timeのinflateとdeflateを設定
1 |
package Neko::Schema::Login; use strict; use warnings; use base 'DBIx::Class'; use DateTime::Format::MySQL; __PACKAGE__->load_components(qw/PK::Auto::MySQL Core/); __PACKAGE__->table('login'); __PACKAGE__->add_columns(qw/id login_time/); __PACKAGE__->set_primary_key('id'); __PACKAGE__->might_have(id => 'Neko::Schema::User'); __PACKAGE__->inflate_column('login_time', { inflate => sub { DateTime::Format::MySQL->parse_datetime(shift); }, deflate => sub { DateTime::Format::MySQL->format_datetime(shift); }, }); |
userテーブルにマッピングしてたモジュールにリレーションの追加
Neko::Schema::Userにmight_haveを追加します。
1 |
__PACKAGE__->might_have(id => 'Neko::Schema::Login'); |
スキーマの修正
Neko::SchemaにLoginを追加
1 |
__PACKAGE__->load_classes(qw/User Bookmark Login/); |
userテーブルとloginテーブルへのinsert
userテーブルにデータをつっこんでついでにloginテーブルにもデータつっこみます。
1 |
my $i = $schema->resultset('User')->create({name => 'nekokak'}); $schema->resultset('Login')->create({id => $i->last_insert_id, login_time => '2006-02-03'}); |
loginテーブルのselect
loginテーブルをselectしてそこからついでにuserのデータも引っぱってます。
1 |
my $it = $schema->resultset('Login')->search(); while ( my $login = $it->next ) { my $u = $login->user_id; print $login->id,':',$u->name,':',$login->login_time,"\n"; } |
inflate/deflateにはTime::Pieceとかも当然使えます。
エラー発生ウワァァァァァァヽ(`Д´)ノァァァァァァン!な時
1 |
$schema->storage->debug(1); $schema->storage->debugfh(IO::File->new('/tmp/trace.out', 'w')); |
で/tmp/trace.outにログが出力されまつ。
ログの内容はこんな感じ。
1 |
SELECT me.id, me.login_time FROM login me WHERE ( naem = ? ): nomaneko |
SQLiteを使うときの注意
MySQLでも駄目だったのでプライマリのないテーブルの場合は要注意
typesterさんがDBICのMLにDBD::SQLiteの制限に関するやり取りやってたので参考にすべし。
たとえばこんな感じで、
1 |
my $schema = Neko::Schema->connect('dbi:SQLite:/home/nekokak/dbix/nekodb.db'); my $n = $schema->resultset('User'); my $it = $n->search(); while ( my $user = $it->next ) { print $user->id,':',$user->name,"\n"; } |
問題なくデータ取れます。
そこでupdateと絡めてやると、たとえばこんなの。
1 |
my $schema = Neko::Schema->connect('dbi:SQLite:/home/nekokak/dbix/nekodb.db'); my $n = $schema->resultset('User'); my $it = $n->search(); while ( my $user = $it->next ) { $user->name('mogeneko'); $user->update; } |
DBD::SQLite::st execute failed: database table is locked(1) at dbdimp.c line 398 at /usr/lib/perl5/site_perl/5.8.6/DBIx/Class/Storage/DBI.pm line 305. Use of uninitialized value in numeric eq (==) at /usr/lib/perl5/site_perl/5.8.6/DBIx/Class/Row.pm line 103. DBIx::Class::Relationship::CascadeActions::update(): Can't update Neko::Schema::User=HASH(0x8d9f010): row not found at ./test.pl line 17
こんな感じのエラーになった。
なのでこうする、
1 |
my $schema = Neko::Schema->connect('dbi:SQLite:/home/nekokak/dbix/nekodb.db'); my $n = $schema->resultset('User'); my $it = $n->search(); #while ( my $user = $it->next ) { foreach my $user ( $it->all ) { $user->name('mogeneko'); $user->update; } |
すると、
DBIx::Class::Relationship::CascadeActions::update(): Can't update Neko::Schema::User=HASH(0x9b01cb0): updated more than one row at ./test.pl line 17
なんじゃこのエラーは。と思ったらどうも、一発目のupdateで一気に全部アップデートかまされてる模様。
レコードが
id | name |
---|---|
1 | nekokak |
2 | nomaneko |
3 | mogeneko |
こんな感じであるとして、
1 |
my $n = $schema->resultset('User'); my $it = $n->search({id => [1,2]}); while ( my $user = $it->next ) { print $user->id,':',$user->name,"\n"; } |
これを実行すると、
$ ./test.pl 1:nekokak 2:nomaneko $
とちゃんと想定したデータが取れてきます。
んが!!
1 |
my $n = $schema->resultset('User'); my $it = $n->search({id => [1,2]}); foreach my $user ( $it->all ) { $user->name('hogeneko'); $user->update; } |
こんな感じでidが1,2のものだけhogenekoにupdateしようとしたら、、、
1 |
sqlite> select * from user; 1|hogeneko 2|hogeneko 3|hogeneko sqlite> |
こんな感じにされてしまいますた。要注意!!
MLの回答を元に
オイラの質問:
http://lists.rawmode.org/pipermail/dbix-class/2006-February/000672.html
回答:
http://lists.rawmode.org/pipermail/dbix-class/2006-February/000681.html
DBICのMLでも、プライマリの無いテーブルは良くないと指摘しつつ、
DBICでは現状対応していないと言われました。
プライマリキーの無いテーブルの場合は例えばこんな風に同一内容にはupdateは正常に実行される
1 |
$schema->resultset('Test')->search({id => [1,2,3],name =>'test'})->update({ name => 'test 1'}); |
プライマリーの無いテーブルの場合、下の例は有効には動作せず、
現状全カラム初回のupdateで更新されてしまう。
1 |
my $it = $t->search({id => [1,2,3],name => 'test'}); my $i=1; for ($it->all) { $_->name("test $i"); $_->update; $i++; } |
あと、もう一つの回避策としては、
こんなテーブル構成で、
1 |
CREATE TABLE test ( id INTEGER NOT NULL, name TEXT NOT NULL, foo TEXT ); |
こんなデータの場合
1 |
sqlite> select * from test; 1|test|hoge 1|sub_test|hoge 2|sub_test|hoge 2|test|hoge 3|test|hoge 3|sub_test|hoge sqlite> |
testテーブルへのマッピングをこんな感じにidとnameでプライマリ指定します。
1 |
package Neko::Schema::Test; use strict; use warnings; use base 'DBIx::Class'; __PACKAGE__->load_components(qw/Core/); __PACKAGE__->table('test'); __PACKAGE__->add_columns(qw/id name foo/); #__PACKAGE__->set_primary_key('id'); __PACKAGE__->set_primary_key(qw/id name/); 1; |
で、こんな感じのスクリプトを実行すると、
1 |
my $it = $schema->resultset('Test')->search({id => [1,2,3] , name => 'test'}); my $i=0; for ($it->all) { $_->foo("test $i"); $_->update; $i++; } |
こんな感じでupdateされます。
1 |
sqlite> select * from test; 1|test|test 0 1|sub_test|hoge 2|sub_test|hoge 2|test|test 1 3|test|test 2 3|sub_test|hoge sqlite> |
でも、(いい例ではない&分かりにくいですが)
1 |
my $it = $schema->resultset('Test')->search({id => 1 , name => 'sub_test'}); my $i=0; for ($it->all) { $_->name("sub_test2"); $_->update; $i++; } |
こんな感じでプライマリの一つであるnameを更新しようとすると、
1 |
UPDATE test SET name = ? WHERE ( id = ? AND name = ? ): sub_test2 1 sub_test2 |
こんなSQLが実行されてしまいます。これは微妙。。。
バージョン0.05003
プライマリーの無いテーブルについては一部制限を設けられました。
まあ、意図しないテーブルのupdateを回避できるのですが。
プライマリーの無いテーブルに対し、こういう形でupdateをかけると、
1 |
my $it = $schema->resultset('Test')->search({id => [1,2,3] , name => 'sub test'}); for ($it->all) { $_->foo("fixed"); $_->update; } |
こういうエラーがでます。
DBIx::Class::Relationship::CascadeActions::update(): Cannot safely update a row in a PK-less table at ./test.pl line 49
そして、全カラムupdateは防がれるようになりました。
プライマリの無いテーブルってのも確かにおかしな話なのですが、ありえなくはないので、
そういうテーブルをupdateする時は、search()->update();でやりましょう。
DBIx::Class::Schema::Loaderを使ってみる
PODをほぼそのまま実験してみた
DBIx::Class::Schema::Loaderを継承して、DBの設定をする。
1 |
package Neko::SchemaLoader; use strict; use warnings; use base 'DBIx::Class::Schema::Loader'; __PACKAGE__->load_from_connection( dsn => "dbi:mysql:nekodb", user => "nekokak", password => "******", relationships => 1, options => { AutoCommit => 1 }, debug => 1, ); 1; |
どんな感じになるのかダンプしてみた。
1 |
#! /usr/bin/perl use strict; use warnings; use Neko::SchemaLoader; use Data::Dumper; my $schema = "Neko::SchemaLoader"; my @tables = $schema->loader->tables; print Dumper(\@tables); |
そしたらこんなんでますた
### START DBIx::Class::Schema::Loader dump ### # Initializing table "login" as "Neko::SchemaLoader::Login" Neko::SchemaLoader::Login->table('login'); Neko::SchemaLoader::Login->add_columns('id', 'login_time') Neko::SchemaLoader::Login->set_primary_key('id') # Initializing table "user" as "Neko::SchemaLoader::User" Neko::SchemaLoader::User->table('user'); Neko::SchemaLoader::User->add_columns('id', 'name') Neko::SchemaLoader::User->set_primary_key('id') # Belongs_to relationship Neko::SchemaLoader::Login->belongs_to( 'id' => 'Neko::SchemaLoader::User',{ id => id }); # Has_many relationship Neko::SchemaLoader::User->has_many( 'logins' => 'Neko::SchemaLoader::Login',{ id => id }); ); ### END DBIx::Class::Schema::Loader dump ### $VAR1 = [ 'login', 'user' ];
スバラシス。
ただ、リレーションの部分がこちらの想定している形でないので、
DBの設定のrelationshipsをやめてみるとこんなんになった。
### START DBIx::Class::Schema::Loader dump ### # Initializing table "login" as "Neko::SchemaLoader::Login" Neko::SchemaLoader::Login->table('login'); Neko::SchemaLoader::Login->add_columns('id', 'login_time') Neko::SchemaLoader::Login->set_primary_key('id') # Initializing table "user" as "Neko::SchemaLoader::User" Neko::SchemaLoader::User->table('user'); Neko::SchemaLoader::User->add_columns('id', 'name') Neko::SchemaLoader::User->set_primary_key('id') ### END DBIx::Class::Schema::Loader dump ### $VAR1 = [ 'login', 'user' ];
これはDB設計の問題かなぁ。
リレーションの追加は後で考えよう。
どのテーブルがどんな名前のモジュールにされているのかを引っぱりたい場合は、
1 |
my $monikers = $schema->loader->monikers; print Dumper($monikers); |
$VAR1 = { 'user' => 'User', 'login' => 'Login' };
モジュールのフルネームが知りたい場合は、
1 |
my $classes = $schema->loader->classes; print Dumper($classes); |
$VAR1 = { 'user' => 'Neko::SchemaLoader::User', 'login' => 'Neko::SchemaLoader::Login' };
Userテーブルにselectかます
1 |
my $it = $schema->resultset($monikers->{'user'})->search; while ( my $user = $it->next ) { print $user->id,':',$user->name,"\n"; } |
細かい設定をなんとかできたら激しく便利ですな!
で、とりあえずこんな感じでリレーション設定できる。
1 |
$classes->{'user'}->might_have(login_id => $classes->{'login'}); my $it = $schema->resultset($monikers->{'user'})->search({id => 1}); while ( my $user = $it->next ) { my $login = $user->login_id; print $user->id,':',$login->login_time,':',$user->name,"\n"; } |
課題
- might_haveとhas_oneの違いがよーわからんので調べる。
- many_to_manyを試す。
- DBIx::Class::Validationを見る。
- DBIx::Class::Loaderを試す。
- むしろDBIx::Class::Schema::Loaderか?
参考
ほとんどhttp://search.cpan.org/~mstrout/DBIx-Class/lib/DBIx/Class/Manual/SchemaIntro.podからのパクリw
とりあえず作ったモジュール
- DigestColumns::DBIx-Class-DigestColumns-0.01.tar.gz(170)
とりあえず作ったから残しておく。↓
- MD5Columns(必要無し)::DBIx-Class-MD5Columns-0.01.tar.gz(125)
- EscapeSearch(必要無し)::DBIx-Class-EscapeSearch-0.01.tar.gz(127)
Last update time:2006/11/07 08:48:06