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 )