最近はmysqlでデータベースを作ることが多かったんだけど、ちょっとしたもの作るのにmysqlはでかすぎるなあとSQLite+DBICをさわり始めてる。
サンプルはPerl/DBIC - Nekokak's core dumpが、よくまとまっていて非常にわかりやすかったので、これの流れで書いた。が、二箇所ほど悩んだのでメモ。ちなみに、SQLiteのせいかどうかはわかりません。
ちなみに、
- DBIx::Class 0.07003
- SQLite version 3.3.5
というバージョン。
last_insert_id
1:多の関係を試す をSQLiteで試す。
まずsqlはこんな感じ
create table user (
id integer PRIMARY KEY not null,
name varchar(256) not null,
time date
);
create table bookmark (
id integer NOT NULL PRIMARY KEY,
user_id integer NOT NULL,
url text NOT NULL,
FOREIGN KEY (user_id) REFERENCES user(id)
);
CREATE INDEX user_id_idx ON bookmark (user_id);
で、データベース作成
sqlite3 kzfm.db < test.sql
Schema,User,Bookmarkモジュールはほとんど同じだがload_componentsにPK::Auto::SQLiteを使う。
use strict;
use warnings;
use base 'DBIx::Class';
__PACKAGE__->load_components(qw/ PK::Auto::SQLite Core/);
__PACKAGE__->table('user');
__PACKAGE__->add_columns(qw/id name/);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many(bookmark => 'Kzfm::Schema::Bookmark', 'user_id');
1;
こんな感じ。
で、実行してみると、、、
my $i = $schema->resultset('User')->create({name => 'kzfm'});
$schema->resultset('Bookmark')->create({
user_id => $i->last_insert_id ,
url => 'http://test.com/'}
);
last_insert_idがないと言われた。単にidだけでよいのか?
might_have
loginテーブルにマッピングさせるモジュール
のとこでUser,Loginお互いにmight_haveを指定すると->idでIDがゲットできなかった。
use strict;
use warnings;
use base 'DBIx::Class';
__PACKAGE__->load_components(qw/ PK::Auto::SQLite Core/);
__PACKAGE__->table('user');
__PACKAGE__->add_columns(qw/id name/);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many(bookmark => 'Kzfm::Schema::Bookmark', 'user_id');
#__PACKAGE__->might_have(id => 'Kzfm::Schema::Login');
1;
package Kzfm::Schema::Login;
use strict;
use warnings;
use base 'DBIx::Class';
use DateTime::Format::MySQL;
__PACKAGE__->load_components(qw/PK::Auto::SQLite Core/);
__PACKAGE__->table('login');
__PACKAGE__->add_columns(qw/id login_time/);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->might_have(id => 'Kzfm::Schema::User');
__PACKAGE__->inflate_column('login_time', {
inflate => sub { DateTime::Format::MySQL->parse_datetime(shift); },
deflate => sub { DateTime::Format::MySQL->format_datetime(shift); },
});
幾つかのパターンを試した結果、参照するほうにmight_haveをつけるらしい。あと、SQLiteの場合日付まわりをどう処理すればいいのかよくわかってない。とりあえずMySQLのフォーマットでも動くような気がするんだけど。
というわけで、時間のあるうち(気力のあるうち?)に、多対多まではいっときたい。