Canclování dotazu s DBI - ukázka testu
Skočit na navigaci
Skočit na vyhledávání
use DBI;
use Perl::Unsafe::Signals;
use IO::Handle;
sub execute_with_reflect_term {
my ($dbh, $sql) = @_;
my $sth = $dbh->prepare( $sql );
local $SIG{ TERM } = sub {
print "sending cancel signal to database\n";
$sth->cancel;
print "cancel emmited\n";
};
UNSAFE_SIGNALS { $sth->execute };
}
sub rows_exists {
my ($dbh, $sql) = @_;
my $sth = $dbh->prepare( $ sql );
$sth->execute;
return $sth->rows > 0;
}
sub test {
close READER;
my $dbh = DBI->connect("dbi:Pg:dbname=postgres host=localhost" .
" application_name=CANCEL_TEST",
"pavel","",
{RaiseError=>1, PrintError=>0});
if (!eval {
execute_with_reflect_term ($dbh, "SELECT pg_sleep(1000)");
}) {
if ($dbh->state eq '57014') {
print WRITER "*** Query cancelled ***";
} else {
print WRITER "unexpected error: >>$DBI::state<< >>$DBI::err<< >>$DBI::errstr<<\n$@"
}
}
close WRITER;
exit;
}
$dbh_alfa = DBI->connect("dbi:Pg:dbname=postgres host=localhost application_name=test_parent",
"pavel","",
{RaiseError=>1, PrintError=>0});
if (rows_exists($dbh_alfa,
"SELECT * FROM pg_stat_activity WHERE application_name='CANCEL_TEST'")) {
die "clean PostgreSQL connections first";
}
# close this connect before new fork,
# because killing child kills it too. It is available from child.
$dbh_alfa->disconnect;
pipe(READER, WRITER);
WRITER->autoflush(1);
my $pid = fork;
if (!defined $pid) {
die "Cannot fork: $!";
}
elsif ($pid == 0) {
# client process
test;
}
else {
# parent process
sleep 1;
close WRITER;
$dbh_alfa = DBI->connect("dbi:Pg:dbname=postgres host=localhost application_name=test_parent",
"pavel","",
{RaiseError=>1, PrintError=>0});
if (! rows_exists($dbh_alfa,
"SELECT * FROM pg_stat_activity WHERE application_name='CANCEL_TEST'")) {
die "cannot start test";
}
print "subprocess started corectly, sending SIGTERM\n";
kill(15, $pid);
waitpid $pid, 0;
if (rows_exists($dbh_alfa,
"SELECT * FROM pg_stat_activity WHERE application_name='CANCEL_TEST'")) {
die "subprocess didn't cancel own long query";
}
print "subprocess terminated long query corectly\n";
chomp ($line = <READER>);
if ($line eq "*** Query cancelled ***") {
print "subprocess returned expected result\n";
}
else {
die "unexpected result from subprocess: $line";
}
close READER;
print "test is complete.\n"
}