Initializing a database with DBIx::Class and CSV Files.
Here is a recipe I cooked up a while back and have been refining it ever since. The general idea is to use CSV files to populate your database. DBIx::Class, with SQL::Translator, can generate your table definitions and populate the data. It's very easy to use, you just have to call $schema->deploy on a connected schema.
The usage is very easy, you just modify your existing deploy call and point it to the CSV files:
$schema->deploy({
import => {
'SomeRS' => 'data/somefile.csv',
'OneMoreRS' => 'data/moredata.csv',
'YetAnotherRS' => 'data/moar.csv',
}
});
The code is quite simply, and you just have to place it in your Schema.pm file:
use Text::xSV;
sub deploy {
my ( $self, $properties ) = @_;
my $data_import = delete $properties->{import};
my $key_check_off;
my $key_check_on;
if ( $self->storage->isa('DBIx::Class::Storage::DBI::mysql') ) {
$key_check_off = "SET FOREIGN_KEY_CHECKS = 0";
$key_check_on = "SET FOREIGN_KEY_CHECKS = 1";
}
my $populate_txn = sub {
# It is better to use Class::C3's ->next::method here, but
# since that confuses people who haven't seen it before I
# opted to use SUPER::
$self->SUPER::deploy($properties, @_);
return unless $data_import and ref $data_import eq 'HASH';
$self->storage->dbh->do($key_check_off) if $key_check_off;
foreach my $data ( keys %$data_import ) {
my $rs = $self->resultset($data);
unless ( $rs ) {
carp "Unknown result set in import: $data"
}
my $csv = Text::xSV->new;
$csv->open_file($data_import->{$data});
$csv->read_header;
foreach my $field ( $csv->get_fields ) {
if ( lc($field) ne $field ) {
$csv->alias($field, lc($field));
}
}
while ( my $row = $csv->fetchrow_hash ) {
eval { $rs->create($row); };
if ( $@ ) {
die "Unable to insert row from data: " . join(', ', values %$row) . "\n";
}
}
}
$self->storage->dbh->do($key_check_on) if $key_check_on;
};
$self->txn_do( $populate_txn );
if ( $@ ) {
die "Unable to deploy and populate data: $@";
}
}
(As a note, I opted to not use populate but the slower 'create' because if you have an error in your CSV file it is easier to debug. If someone has an idea on how to do this better please comment!)
Comments