木曜日, 3月 05, 2009

Perl学習中 ここ数週間の成果

ここ数週間の頑張りの成果。
CSVから配列を作るサブロジックと、配列からハッシュを作るサブロジック。
最終的にハッシュからDBにinsertするものを作りたかったけど、そこはDBIx::Classにお任せすることにした。
一応インサート文を組み立てるサブロジックも作ったけど、使うのはちょっとどうかと思う作り。手元のソースからはあとで消そう。
そうなるとモジュール名も変えなきゃ。

Csv2Db.pm


#!/usr/bin/perl -Ilib
package Csv2Db;
use strict;
use warnings;

use IO::File;
use Text::CSV_XS;

sub csv2array {
shift;
my $file = shift;

my $csv_reader = new Text::CSV_XS( { binary => 1 } );
my @_line = ();
my @csv_lines = ();

while (<$file>) {

#CSV_XSを利用し、カラムを分解する
$csv_reader->parse($_)
|| die "error: " . $csv_reader->error_input() . "\n";
@_line = $csv_reader->fields();
push( @csv_lines, [@_line] );

}
return @csv_lines;
}

sub array2hash {
shift;
my ( $schema, $csvlist ) = @_;

_check_hash_refference($schema);
_check_array_refference($csvlist);

my %hash = ();

foreach my $key ( keys %$schema ) {
$hash{$key} = @$csvlist[ $schema->{$key} ];
}
return %hash;
}

sub createInsertSql {
shift;
my ( $table, $valueHash ) = @_;

_check_hash_refference($valueHash);

my $fields = '';
my $sql = "INSERT $table SET ";

foreach my $key ( sort keys %$valueHash ) {
$fields = $fields . "$key='$valueHash->{$key}', ";
}
$fields = substr( $fields, 0, -2 );

$sql = $sql . $fields . ";";

return $sql;
}

sub _check_hash_refference {
my $hash = shift;
die 'Undefined Hash..' unless defined $hash;
die 'Not a HASH refernce..' unless ref $hash eq 'HASH';
die 'Empty Hash..' unless keys(%$hash) > 0;
}

sub _check_array_refference {
my $array = shift;
die 'Undefined Array..' unless defined $array;
die 'Not a ARRAY refernce..' unless ref $array eq 'ARRAY';
die 'Empty Array..' unless $#$array > -1;
}
1;



ここからテストコード。

01_csv2db_csv2array.t


use strict;
use warnings;
use Test::More;
use File::Temp qw( tempfile );

use Csv2Db::Csv2Db;

plan( tests => 2 );

#test1
{
my ( $tmp, $filename ) = tempfile();
print {$tmp} "0,k,hiro,m\n1,k,mai,f";
close($tmp);

my @result_arr
= ( [ ( '0', 'k', 'hiro', 'm' ) ], [ ( '1', 'k', 'mai', 'f' ) ] );

open( $tmp, "<", $filename );
my @res = Csv2Db->csv2array($tmp);
ok( eq_array( \@res, \@result_arr ), 'normal pattern' );
close($tmp);
}

#test2
{
my ( $tmp, $filename ) = tempfile();
close($tmp);

open( $tmp, "<", $filename );
my @res = Csv2Db->csv2array($tmp);
ok( eq_array( \@res, [ () ] ), 'empty file' );
close($tmp);
}



02_csv2db_array2hash.t


use strict;
use warnings;
use Test::More;

use Csv2Db::Csv2Db;

plan( tests => 7 );

#normal
{
my %schema = ( 'id' => 0, 'fname' => 2 );
my @arr = ( '000', 'k', 'name' );
my %result = ( 'id' => '000', 'fname' => 'name' );
my %test = Csv2Db->array2hash( \%schema, \@arr );
ok( eq_hash( \%test, \%result ), 'normal case' );
}

#undef hash
{
my @arr = ( '000', 'k', 'name' );
my %result = ( 'id' => '000', 'fname' => 'name' );

eval { my %test = Csv2Db->array2hash( undef, \@arr ); };
like( $@, qr/Undefined/, 'undef schema' );
}

#empty hash
{
my %schema = ();
my @arr = ( '000', 'k', 'name' );
my %result = ( 'id' => '000', 'fname' => 'name' );

eval{my %test = Csv2Db->array2hash( \%schema, \@arr )};
like( $@, qr/Empty/, 'empty schema' );
}

#not hash
{
my @schema = ();
my @arr = ( '000', 'k', 'name' );
my %result = ( 'id' => '000', 'fname' => 'name' );

eval{my %test = Csv2Db->array2hash( \@schema, \@arr )};
like( $@, qr/HASH/, 'not a hash' );
}

#undef arr
{
my %schema = ( 'id' => 0, 'fname' => 2 );

my %result = ( 'id' => '000', 'fname' => 'name' );

eval { my %test = Csv2Db->array2hash( \%schema, undef ); };
like( $@, qr/Undefined/, 'undef array' );
}

#empty arr
{
my %schema = ( 'id' => 0, 'fname' => 2 );
my @arr = ();
my %result = ( 'id' => '000', 'fname' => 'name' );

eval{my %test = Csv2Db->array2hash( \%schema, \@arr )};
like( $@, qr/Empty/, 'empty array' );
}

#not hash
{
my %schema = ( 'id' => 0, 'fname' => 2 );
my $arr = 'not a array';
my %result = ( 'id' => '000', 'fname' => 'name' );

eval{my %test = Csv2Db->array2hash( \%schema, \$arr )};
like( $@, qr/ARRAY/, 'not a array' );
}



03_csv2db_createInsert.t


use strict;
use warnings;
use Test::More;

use Csv2Db::Csv2Db;

plan( tests => 1 );

#createInsertSql
my $table1 = 'main_table';
my %values1 = ( 'id' => "000", 'fname' => "hiro" );
my $sql1 = Csv2Db->createInsertSql( $table1, \%values1 );
is( $sql1, "INSERT main_table SET fname='hiro', id='000';" );



PODを一切書いていないので、書かなきゃですね。
とりあえず目標期間内にここまで作れたのでOKとしよう。

0 件のコメント: