2006-05-21
■[Perl]icdbi - Class::DBIを使った対話型のSQLクライアント
だいぶ前に作って放置してたやつ。
id:secondlife さんの iar - ActiveRecordを使った対話型のSQLクライアント - coリ・ー・ン<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__
あと、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 しないと動かないっぽい。いつからだろ。
トラックバック - http://d.hatena.ne.jp/spiritloose/20060521/1148142835


