App-Sqitch
view release on metacpan or search on metacpan
lib/App/Sqitch/Engine/mysql.pm view on Meta::CPAN
LIMIT 1
});
while ($dbh->selectcol_arrayref($sth, undef, $change->project)->[0]) {
# Sleep for 100 ms.
require Time::HiRes;
Time::HiRes::sleep(0.1);
}
return $self;
}
sub _set_vars {
my %vars = shift->variables or return;
return 'SET ' . join(', ', map {
(my $k = $_) =~ s/"/""/g;
(my $v = $vars{$_}) =~ s/'/''/g;
qq{\@"$k" = '$v'};
} sort keys %vars) . ";\n";
}
sub _source {
my ($self, $file) = @_;
my $set = $self->_set_vars || '';
return ('--execute' => "${set}source $file");
}
sub _run {
my $self = shift;
my $sqitch = $self->sqitch;
my $pass = $self->password or return $sqitch->run( $self->mysql, @_ );
local $ENV{MYSQL_PWD} = $pass;
return $sqitch->run( $self->mysql, @_ );
}
sub _capture {
my $self = shift;
my $sqitch = $self->sqitch;
my $pass = $self->password or return $sqitch->capture( $self->mysql, @_ );
local $ENV{MYSQL_PWD} = $pass;
return $sqitch->capture( $self->mysql, @_ );
}
sub _spool {
my $self = shift;
my @fh = (shift);
my $sqitch = $self->sqitch;
if (my $set = $self->_set_vars) {
open my $sfh, '<:utf8_strict', \$set;
unshift @fh, $sfh;
}
my $pass = $self->password or return $sqitch->spool( \@fh, $self->mysql, @_ );
local $ENV{MYSQL_PWD} = $pass;
return $sqitch->spool( \@fh, $self->mysql, @_ );
}
sub run_file {
my $self = shift;
$self->_run( $self->_source(@_) );
}
sub run_verify {
my $self = shift;
# Suppress STDOUT unless we want extra verbosity.
my $meth = $self->can($self->sqitch->verbosity > 1 ? '_run' : '_capture');
$self->$meth( $self->_source(@_) );
}
sub run_upgrade {
my ($self, $file) = @_;
my @cmd = $self->mysql;
if ((my $idx = firstidx { $_ eq '--database' } @cmd) > 0) {
# Replace the database name with the registry database.
$cmd[$idx + 1] = $self->registry;
} else {
# Append the registry database name.
push @cmd => '--database', $self->registry;
}
return $self->sqitch->run(
@cmd,
$self->_source($self->_prepare_registry_file($file)),
);
}
# Prepares $file for execution, editing its contents for various MySQL
# configurations.
sub _prepare_registry_file {
my ($self, $file) = @_;
my $has_frac = $self->_fractional_seconds;
return $file if $has_frac;
# Read in the file to modify it.
my $sql = $file->slurp;
if (!$has_frac) {
# Need to strip out datetime precision.
$sql =~ s{DATETIME\(\d+\)}{DATETIME}g;
# Strip out 5.5 stuff on earlier versions.
$sql =~ s/-- ## BEGIN 5[.]5.+?-- ## END 5[.]5//ms
if $self->dbh->{mariadb_serverversion} < 50500;
}
# Write out a temp file and return it.
require File::Temp;
my $fh = File::Temp->new;
print $fh $sql;
close $fh;
return $fh;
}
sub _create_check_function {
# The checkit() function works sort of like a CHECK: if the first argument
# is 0 or NULL, it throws the second argument as an exception.
# Conveniently, verify scripts can also use it to ensure an error is
# thrown when a change cannot be verified. Requires MySQL 5.5.0 and
# permission to create an immutable function, so ignore failures in those
# situations.
my $self = shift;
return if $self->dbh->{mariadb_serverversion} < 50500;
try {
$self->dbh->do(q{
CREATE FUNCTION checkit(doit INTEGER, message VARCHAR(256)) RETURNS INTEGER DETERMINISTIC
BEGIN
IF doit IS NULL OR doit = 0 THEN
SIGNAL SQLSTATE 'ERR0R' SET MESSAGE_TEXT = message;
END IF;
RETURN doit;
END;
});
} catch {
# 1419: You do not have super user privilege and binary logging is
# enabled.
die $_ if !$DBI::err || $DBI::err != 1419;
$self->sqitch->warn(__(
'Insufficient permissions to create the checkit() function; skipping.',
));
}
}
sub run_handle {
my ($self, $fh) = @_;
$self->_spool($fh);
}
sub _cid {
my ( $self, $ord, $offset, $project ) = @_;
my $offexpr = $offset ? " OFFSET $offset" : '';
return try {
return $self->dbh->selectcol_arrayref(qq{
SELECT change_id
FROM changes
WHERE project = ?
ORDER BY committed_at $ord
LIMIT 1$offexpr
}, undef, $project || $self->plan->project)->[0];
} catch {
# MySQL error code 1049 (ER_BAD_DB_ERROR): Unknown database '%-.192s'
# MySQL error code 1146 (ER_NO_SUCH_TABLE): Table '%s.%s' doesn't exist
return if $DBI::err && ($DBI::err == 1049 || $DBI::err == 1146);
die $_;
};
}
1;
__END__
=head1 Name
App::Sqitch::Engine::mysql - Sqitch MySQL Engine
=head1 Synopsis
( run in 0.722 second using v1.01-cache-2.11-cpan-5a3173703d6 )