App-BigQuery-Importer-MySQL
view release on metacpan or search on metacpan
lib/App/BigQuery/Importer/MySQL.pm view on Meta::CPAN
use File::Temp qw(tempfile);
use File::Basename;
use DBI;
use Carp qw(croak);
our $VERSION = "0.024";
sub new {
my ($class, $args) = @_;
my @required_list = qw/ src dst mysqlhost mysqluser mysqlpassword project_id progs /;
my $obj_data = +{};
for my $required (@required_list) {
if( ! defined $args->{$required} ) { croak "$required is required"};
$obj_data->{$required} = $args->{$required};
}
$obj_data->{dryrun} = $args->{dryrun},
$obj_data->{allow_text_type} = $args->{allow_text_type},
bless $obj_data, $class;
}
sub run {
my $self = shift;
my $db_host = $self->{'mysqlhost'};
my ($src_schema, $src_table) = split /\./, $self->{'src'};
my ($dst_schema, $dst_table) = split /\./, $self->{'dst'};
# check the table does not have BLOB or TEXT
my $dbh = DBI->connect("dbi:mysql:${src_schema}:${db_host}", $self->{'mysqluser'}, $self->{'mysqlpassword'});
$self->_check_columns(
+{
dbh => $dbh,
src_schema => $src_schema,
src_table => $src_table,
allow_text_type => $self->{'allow_text_type'},
}
);
lib/App/BigQuery/Importer/MySQL.pm view on Meta::CPAN
my $bucket_name = $src_table . '_' . time;
unless ($self->{'dryrun'}) {
my $mb_command = "$self->{'progs'}->{'gsutil'} mb -p $self->{'project_id'} gs://$bucket_name";
my $result_create_bucket = system($mb_command);
if ($result_create_bucket != 0) {
die "${mb_command} : failed";
}
}
# dump table data
my $dump_command = "$self->{'progs'}->{'mysql'} -u$self->{'mysqluser'} -p'$self->{'mysqlpassword'}' -h$self->{'mysqlhost'} ${src_schema} -Bse'SELECT * FROM ${src_table}'";
my $dump_result = `$dump_command`;
if ($? != 0) {
die "${dump_command} : failed";
}
$dump_result =~ s/\"//g;
$dump_result =~ s/NULL//g;
my($src_dump_fh, $src_dump_filename) = tempfile(UNLINK => 1);
unless ($self->{'dryrun'}) {
print {$src_dump_fh} $dump_result;
}
script/mysqlbq view on Meta::CPAN
my @progs = qw(mysql gsutil bq);
for my $prog (@progs) {
my $path = `which $prog 2> /dev/null` or pod2usage(2);
chomp $path if $path;
$pathes->{$prog} = $path;
}
# check config
defined RC->{'default.project_id'} or pod2usage(2);
defined RC->{'client.user'} or pod2usage(2);
defined RC->{'client.password'} or pod2usage(2);
# get options
my %opt;
GetOptions(
\%opt,
qw(db_host=s src=s dst=s allow_text_type dryrun)
) or pod2usage(2);
my @required_options = qw(db_host src dst);
pod2usage(2) if grep {!exists $opt{$_}} @required_options;
my $app = App::BigQuery::Importer::MySQL->new({
dryrun => $opt{dryrun},
src => $opt{src},
dst => $opt{dst},
allow_text_type => $opt{allow_text_type},
mysqlhost => $opt{db_host},
mysqluser => RC->{'client.user'},
mysqlpassword => RC->{'client.password'},
project_id => RC->{'default.project_id'},
progs => $pathes,
});
$app->run;
__END__
=head1 NAME
mysqlbq - cli tool for App::BigQuery::Importer::MySQL
script/mysqlbq view on Meta::CPAN
--src MySQL Schema and Table name(ex: schema_name.table_name)
--dst BigQuery Dataset and Table name(ex: dataset_name.table_name)
--allow_text_type Import MySQL TEXT type columns to BigQuery as STRING type
--dryrun dry run mode. not run the side-effects operation.(ex: gsutil mk/rm, bq load/rm)
-h(--help) show this help
Requirement Programs: mysql cli and gcloud package
Requirement Files: this script needs ~/.my.cnf and ~/.bigqueryrc files
~/.my.cnf:
[client]
user = user
password = pass
~/.bigqueryrc:
project_id = pj_id
credential_file = /path/to/credential.json
use Test::Fatal;
use App::BigQuery::Importer::MySQL;
our $origin_args = {
src => 'src.table',
dst => 'dst.table',
allow_text_type => 0,
mysqlhost => 'localhost',
mysqluser => 'user',
mysqlpassword => 'pass',
project_id => 'pjid',
progs => {
mysql => '/path/to/mysql',
gsutil => '/path/to/gsutil',
bq => '/path/to/bq',
}
};
subtest 'all_args' => sub {
my $args = { %$origin_args };
$args->{mysqluser} = undef;
like(
exception {
my $mysqlbq = App::BigQuery::Importer::MySQL->new($args);
},
qr/mysqluser is required/,
"no mysqluser in args died as expected",
);
};
subtest 'no mysqlpassword' => sub {
my $args = { %$origin_args };
$args->{mysqlpassword} = undef;
like(
exception {
my $mysqlbq = App::BigQuery::Importer::MySQL->new($args);
},
qr/mysqlpassword is required/,
"no mysqlpassword in args died as expected",
);
};
subtest 'no project_id' => sub {
my $args = { %$origin_args };
$args->{project_id} = undef;
like(
exception {
my $mysqlbq = App::BigQuery::Importer::MySQL->new($args);
},
( run in 0.688 second using v1.01-cache-2.11-cpan-49f99fa48dc )