理系学生日記

おまえはいつまで学生気分なのか

忍者TOOLS

MySQL で DBIC (DBIx::Class) の Example を実行するまで

Perl の ORM として大人気の DBIx::Class を試そうと思ったところ,わりと苦戦したので,その苦戦記なのです.

DBIC のインストール

DBIx::Class のインストールは非常に簡単でした.

$ sudo cpanp i DBIx::Class

DBD::mysql

今回は MySQL を使用するので DBD::mysql が必要です.しかし,cpanp からインストールしようとすると make test で,具体的に言うと t/10connect.t のこの行でコケていました.

eval {$dbh= DBI->connect($test_dsn, $test_user, $test_password,
                      { RaiseError => 1, PrintError => 1, AutoCommit => 0 });};

要するに MySQL に接続できていないようで,原因は $test_user,$test_password の指定が間違っているのでしょう.
これらの指定方法については perl Makefile.PL --help で分かるので,それに従って Makefile を生成してやります.

$ sudo perl Makefile.PL --testdb test --testuser <you> --testpassword=<your password>

これで make test をパスできるようになりました.後はインストールするだけです.

$ make test
$ sudo make install

DBIx::Class::Manual::Example

後は http://search.cpan.org/~ash/DBIx-Class-0.08010/lib/DBIx/Class/Manual/Example.pod に沿って進めていこうとしていたのですが,insertdb.pl を実行すると下の部分でエラーとなります.

  my @artists = (['Michael Jackson'], ['Eminem']);
  $schema->populate('Artist', [
     [qw/name/],
     @artists,
  ]);

エラーは以下.

$ ./insertdb.pl 
DBIx::Class::Schema::populate(): DBI Exception: DBD::mysql::st execute failed: Duplicate entry '0' for key 1 [for Statement "INSERT INTO artist (name) VALUES (?)" with ParamValues: 0='Eminem'] at ./insertdb.pl line 10

どうも主キーが被っているようです.DBIC::PK::Auto (今は DBIC::Core に統合されたらしいが) がよしなにやってくれると思っていたのですが...
原因は,スキーマを定義した SQL に auto_increment が付いていないことでしょう.

  CREATE TABLE artist (
    artistid INTEGER PRIMARY KEY,
    name TEXT NOT NULL 
  );

  CREATE TABLE cd (
    cdid INTEGER PRIMARY KEY,
    artist INTEGER NOT NULL REFERENCES artist(artistid),
    title TEXT NOT NULL
  );

  CREATE TABLE track (
    trackid INTEGER PRIMARY KEY,
    cd INTEGER NOT NULL REFERENCES cd(cdid),
    title TEXT NOT NULL
  );

今から drop table するのも悔しいので,alter table して対応します.

mysql> alter table artist modify artistid int(11) auto_increment;
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0

これで insertdb.pl が正常に終了するようになります.よかったよかった.