-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
327 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,321 @@ | ||
package MySQL::Util::Protected; | ||
|
||
use Modern::Perl; | ||
use Moose::Role; | ||
use namespace::autoclean; | ||
use Smart::Args; | ||
use DBI; | ||
use Try::Tiny; | ||
|
||
################################################################# | ||
#################### PROTECTED METHODS ########################## | ||
################################################################# | ||
|
||
sub _get_attributes { | ||
my $self = shift; | ||
|
||
my $attr = { | ||
RaiseError => 1, | ||
FetchHashKeyName => 'NAME_uc', | ||
AutoCommit => 0, # dbd::mysql workaround | ||
PrintError => 0 | ||
}; | ||
|
||
if ( $self->attr ) { | ||
foreach my $key ( keys %{ $self->attr } ) { | ||
$attr->{$key} = $self->attr->{$key}; | ||
} | ||
} | ||
|
||
return $attr; | ||
} | ||
|
||
sub _hashkeys_to_lc { | ||
args_pos | ||
|
||
# required | ||
my $self => 'Object', | ||
my $href => 'HashRef'; | ||
|
||
my %tmp; | ||
foreach my $key (%$href) { | ||
$tmp{ lc($key) } = $href->{$key}; | ||
} | ||
|
||
return \%tmp; | ||
} | ||
|
||
sub _read_netrc { | ||
my $self = shift; | ||
|
||
my $netrc_error; | ||
|
||
try { | ||
$self->_verbose( $self->host); | ||
$self->_verbose($self->user) if $self->user; | ||
$self->_verbose( my $out = `cat $ENV{HOME}/.netrc` ); | ||
|
||
my $netrc = Net::Netrc->lookup( $self->host, $self->user ); | ||
my ( $login, $password, $account ) = $netrc->lpa; | ||
$self->_set_user($login) if !$self->user; | ||
$self->_set_pass($password) if !$self->pass; | ||
} | ||
catch { | ||
|
||
# still a chance a login will work with env vars so hold onto | ||
# the error | ||
$netrc_error = $_; # uncoverable statement | ||
}; | ||
|
||
return $netrc_error; | ||
} | ||
|
||
sub _config_verbose_funcs { | ||
|
||
# uncoverable subroutine | ||
my $self = shift; | ||
|
||
my $vf = $self->_verbose_funcs; | ||
|
||
foreach my $func ( split /[,|:]/, $ENV{VERBOSE_FUNCS} ) { | ||
$vf->{$func} = 1; | ||
} | ||
|
||
$self->_verbose_funcs($vf); | ||
} | ||
|
||
sub _show_create_table { | ||
args_pos | ||
|
||
# required | ||
my $self => 'Object', | ||
my $table => 'Str'; | ||
|
||
my $aref = $self->_dbh->selectall_arrayref("show create table $table"); | ||
my $show_create = $aref->[0]->[1]; | ||
|
||
return $show_create; | ||
} | ||
|
||
sub _get_fk_column { | ||
my $self = shift; | ||
my %a = @_; | ||
|
||
my $table = $a{table} || confess "missing table arg"; | ||
my $column = $a{column} || confess "missing column arg"; | ||
|
||
my $fks_href = $self->get_fk_constraints($table); | ||
|
||
foreach my $fk_name ( keys %$fks_href ) { | ||
|
||
foreach my $fk_href ( @{ $fks_href->{$fk_name} } ) { | ||
|
||
if ( $fk_href->{COLUMN_NAME} eq $column ) { | ||
return $fk_href; | ||
} | ||
} | ||
} | ||
|
||
confess "couldn't find where $table.$column is part of an fk?"; | ||
} | ||
|
||
sub _get_indexes_arrayref { | ||
my $self = shift; | ||
my $table = shift; | ||
|
||
my $cache = '_index_cache'; | ||
|
||
if ( defined( $self->$cache->{$table} ) ) { | ||
return $self->$cache->{$table}->data; | ||
} | ||
|
||
my $dbh = $self->_dbh; | ||
my $sth = $dbh->prepare("show indexes in $table"); | ||
$sth->execute; | ||
|
||
my $aref = []; | ||
while ( my $href = $sth->fetchrow_hashref ) { | ||
push( @$aref, {%$href} ); | ||
} | ||
|
||
$self->$cache->{$table} = MySQL::Util::Data::Cache->new( data => $aref ); | ||
return $aref; | ||
} | ||
|
||
sub _fq { | ||
args | ||
|
||
# required | ||
my $self => 'Object', | ||
my $table => 'Str', | ||
|
||
# optional | ||
my $fq => { isa => 'Int', optional => 1, default => 1 }, | ||
my $schema => { isa => 'Str|Undef', optional => 1 }; | ||
|
||
if ($fq) { | ||
if ( $table =~ /\w\.\w/ ) { | ||
return $table; | ||
} | ||
elsif ($schema) { | ||
return "$schema.$table"; | ||
} | ||
|
||
return $self->_schema . ".$table"; | ||
} | ||
|
||
if ( $table =~ /^(\w+)\.(\w+)$/ ) { | ||
my $curr = $self->_schema; | ||
|
||
confess "can't remove schema name from table name $table because we " | ||
. "are not in the same db context (incoming fq table = $table, " | ||
. "current schema = $curr" | ||
if $curr ne $1; | ||
|
||
return $2; | ||
} | ||
|
||
return $table; | ||
} | ||
|
||
sub _un_fq { | ||
args_pos | ||
|
||
# required | ||
my $self => 'Object', | ||
my $table => 'Str'; | ||
|
||
if ( $table =~ /^(\w+)\.(\w+)$/ ) { | ||
return ( $1, $2 ); | ||
} | ||
|
||
return ( $self->_schema, $table ); | ||
} | ||
|
||
sub _get_fk_ddl { | ||
my $self = shift; | ||
my $table = shift; | ||
my $fk = shift; | ||
|
||
my $sql = "show create table $table"; | ||
my $sth = $self->_dbh->prepare($sql); | ||
$sth->execute; | ||
|
||
while ( my @a = $sth->fetchrow_array ) { | ||
|
||
foreach my $data (@a) { | ||
my @b = split( /\n/, $data ); | ||
|
||
foreach my $item (@b) { | ||
if ( $item =~ /CONSTRAINT `$fk` FOREIGN KEY/ ) { | ||
$item =~ s/^\s*//; # remove leading ws | ||
$item =~ s/\s*//; # remove trailing ws | ||
$item =~ s/,$//; # remove trailing comma | ||
return "alter table $table add $item"; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
sub _column_exists { | ||
my $self = shift; | ||
my %a = @_; | ||
|
||
my $table = $a{table} or confess "missing table arg"; | ||
my $column = $a{column} or confess "missing column arg"; | ||
|
||
my $desc_aref = $self->describe_table($table); | ||
|
||
foreach my $col_href (@$desc_aref) { | ||
|
||
if ( $col_href->{FIELD} eq $column ) { | ||
return 1; | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
sub _verbose { | ||
my $caller_func = ( caller(1) )[3]; | ||
my $caller_line = ( caller(0) )[2]; | ||
|
||
args_pos | ||
|
||
# required | ||
my $self => 'Object', | ||
my $msg => 'Str', | ||
|
||
# optional | ||
my $func_counter => { isa => 'Str', default => 0, optional => 1 }; | ||
|
||
my @caller_func = split( /\::/, $caller_func ); | ||
my $key = pop @caller_func; | ||
|
||
# uncoverable branch true | ||
if ( $self->_verbose_funcs->{$key} ) { | ||
print STDERR "[VERBOSE] $caller_func ($caller_line) "; | ||
print STDERR "[cnt=$func_counter]" if $func_counter; | ||
print STDERR "\n"; | ||
|
||
chomp $msg; | ||
foreach my $nl ( split /\n/, $msg ) { | ||
print STDERR "\t$nl\n"; | ||
} | ||
} | ||
} | ||
|
||
sub _verbose_sql { | ||
args_pos | ||
|
||
# required | ||
my $self => 'Object', | ||
my $sql => 'Str', | ||
|
||
# optional | ||
my $func_counter => { isa => 'Int', default => 0, optional => 1 }; | ||
|
||
my $caller_func = ( caller(1) )[3]; | ||
my $caller_line = ( caller(0) )[2]; | ||
|
||
my @caller_func = split( /\::/, $caller_func ); | ||
my $key = pop @caller_func; | ||
|
||
if ( $self->_verbose_funcs->{$key} ) { | ||
print STDERR "[VERBOSE] $caller_func ($caller_line) "; | ||
print STDERR "[cnt=$func_counter]" if $func_counter; | ||
print STDERR "\n"; | ||
|
||
$sql = SQL::Beautify->new( query => $sql )->beautify; | ||
foreach my $l ( split /\n/, $sql ) { | ||
print STDERR "\t$l\n"; | ||
} | ||
} | ||
} | ||
|
||
sub _map_columns_to_fk_names { | ||
args_pos | ||
|
||
# required | ||
my $self => 'Object', | ||
my $table => 'Str'; | ||
|
||
# local variables | ||
my $fk_href = $self->get_fk_constraints($table); | ||
my %map; | ||
|
||
foreach my $fk_name ( keys %$fk_href ) { | ||
|
||
my $fk_aref = $fk_href->{$fk_name}; | ||
|
||
foreach my $col_href (@$fk_aref) { | ||
my $col_name = $col_href->{COLUMN_NAME}; | ||
push( @{ $map{$col_name} }, $fk_name ); | ||
} | ||
} | ||
|
||
return %map; | ||
} | ||
|
||
1; |