icdbi - Class::DBIを使った対話型のSQLクライアント
だいぶ前に作って放置してたやつ。
id:secondlife さんの iar - ActiveRecordを使った対話型のSQLクライアント - 2nd lifeを見てClass::DBIでも作って(パクって)みた。
Class::DBIだと、標準でActiveRecord みたいに便利じゃないので、あんまり意味ないかも。
ソースは以下。
#!/usr/local/bin/perl use strict; use warnings; use Data::Dumper; use Term::ReadLine; use Getopt::Long; use Class::DBI; use Class::DBI::Loader; my $USAGE = <<'END_USAGE'; usage: icdbi [-a adapter] [-h host] [-P port] [-u user] [-p password] database END_USAGE local $Data::Dumper::Terse = 1; local $Data::Dumper::Indent = 1; Getopt::Long::Configure qw(bundling no_ignore_case); my $opt = {}; GetOptions($opt, 'h|host=s', 'D|database=s', 'u|user=s', 'p|password=s', 'P|port=s', 'a|adapter=s', 'help!', ); print $USAGE and exit if exists $opt->{help}; my ($host, $database, $user, $password, $port, $adapter) = map { $opt->{$_} || '' } qw(h D u p P a); $database ||= pop or die $USAGE; $user ||= 'root'; $password ||= ''; $adapter ||= 'mysql'; my $dsn = "dbi:$adapter:$database"; $dsn .= ";host=$host" if $host; $dsn .= ";port=$port" if $port; my $loader = Class::DBI::Loader->new( dsn => $dsn, user => $user, password => $password, options => { RaiseError => 1, AutoCommit => 1 }, relationships => 1, ); for ($loader->classes) { $_->columns(Essential => $_->columns('All')); print "$_ loaded.\n"; } print "\n"; my $term = Term::ReadLine->new('icdbi'); my $prompt = 'icdbi[%d]$ '; my $line = 0; my $code = ''; while (defined(my $input = $term->readline($code ? '> ' : sprintf($prompt, $line)))) { next unless $input; quit() if $input eq 'quit' or $input =~ /\\q$/; if ($input =~ /\\c$/) { clear(); next; } $line++; $code .= $input; next unless $code =~ /;$/; execute(); clear(); } sub execute { my @ret; { package ICDBI; no strict; no warnings; @ret = eval $code; } print Dumper @ret; warn $@ if $@; print "\n"; } sub clear { $code = ''; } sub quit { print "Bye\n" and exit; } __END__
Class::DBI::Loader が必要。
あと、Term::ReadLine::Gnuを入れておくと操作が快適。
DBIx::Classな人は
my $loader = DBIx::Class::Loader->new( dsn => $dsn, user => $user, password => $password, options => { RaiseError => 1, AutoCommit => 1 }, relationships => 1, namespace => 'Data', ); for ($loader->classes) { print "$_ loaded.\n"; }
にすれば使えるはず。
使い方は、上のコードをicdbi とかの名前でPATHの通ったところにおいて
icdbi -u user -p password hoge_db
とすると、こんな感じに
icdbi[1]> $hoge = Hoge->retrieve(1); icdbi[2]> $hoge->body('hogehoge'); idbic[3]> $hoge->update;
とかできる。
Class::DBI::Loaderが対応してるやつなら使えるはず。
実行しているスコープが微妙なのと、コードがいまいちなのが問題・・・
#最近のClass::DBI::Loader が、Class::DBI を use しないと動かないっぽい。いつからだろ。