App-csv2sqlite
view release on metacpan or search on metacpan
lib/App/csv2sqlite.pm view on Meta::CPAN
}
# git description: v0.003-3-g85d53f9
BEGIN {
$App::csv2sqlite::AUTHORITY = 'cpan:RWSTAUNER';
}
# ABSTRACT: Import CSV files into a SQLite database
use Moo 1;
use DBI 1.6 ();
use DBD::SQLite 1 ();
use DBIx::TableLoader::CSV 1.102 (); # catch csv errors and close transactions; file_encoding
use Getopt::Long 2.34 ();
sub new_from_argv {
my ($class, $args) = @_;
$class->new( $class->getopt($args) );
}
around BUILDARGS => sub {
my ($orig, $self, @args) = @_;
my $args = $self->$orig(@args);
if( my $enc = delete $args->{encoding} ){
($args->{loader_options} ||= {})->{file_encoding} ||= $enc;
}
return $args;
};
has csv_files => (
is => 'ro',
coerce => sub { ref $_[0] eq 'ARRAY' ? $_[0] : [ $_[0] ] },
);
has csv_options => (
is => 'ro',
default => sub { +{} },
);
has loader_options => (
is => 'ro',
default => sub { +{} },
);
has dbname => (
is => 'ro',
);
has dbh => (
is => 'lazy',
);
sub _build_dbh {
my ($self) = @_;
# TODO: does the dbname need to be escaped in some way?
my $dbh = DBI->connect('dbi:SQLite:dbname=' . $self->dbname, undef, undef, {
RaiseError => 1,
PrintError => 0,
sqlite_unicode => $self->encoding ? 1 : 0,
});
return $dbh;
}
sub encoding {
return $_[0]->loader_options->{file_encoding};
}
sub help { Getopt::Long::HelpMessage(2); }
sub getopt {
my ($class, $args) = @_;
my $opts = {};
{
local @ARGV = @$args;
my $p = Getopt::Long::Parser->new(
config => [qw(pass_through auto_help auto_version)],
);
$p->getoptions($opts,
'csv_files|csv-file|csvfile|csv=s@',
# TODO: 'named_csv_files=s%'
# or maybe --csv and --named should be subs that append to an array ref to keep order?
'csv_options|csv-opt|csvopt|o=s%',
# TODO: tableloader options like 'drop' or maybe --no-create
'loader_options|loader-opt|loaderopt|l=s%',
'dbname|database=s',
'encoding|enc|e=s',
) or $class->help;
$args = [@ARGV];
}
# last arguments
$opts->{dbname} ||= pop @$args;
# first argument
if( @$args ){
push @{ $opts->{csv_files} ||= [] }, @$args;
}
return $opts;
}
sub load_tables {
my ($self) = @_;
# TODO: option for wrapping the whole loop in a transaction rather than each table
foreach my $file ( @{ $self->csv_files } ){
my %opts = (
%{ $self->loader_options },
csv_opts => { %{ $self->csv_options } },
file => $file,
);
# TODO: This could work but i hate the escaping thing.
# Allow table=file (use "=file" for files with an equal sign).
#if( $file =~ /^([^=:]*)[=:](.+)$/ ){ $opts{name} = $1 if $1; $opts{file} = $2; }
( run in 2.471 seconds using v1.01-cache-2.11-cpan-8f98c5d2c55 )