1
package GenTest::Executor::JavaDB;
5
@ISA = qw(GenTest::Executor);
10
use GenTest::Constants;
12
use GenTest::Executor;
13
use GenTest::Translator;
14
use GenTest::Translator::MysqlDML2ANSI;
15
use GenTest::Translator::Mysqldump2ANSI;
16
use GenTest::Translator::MysqlDML2javadb;
17
use GenTest::Translator::Mysqldump2javadb;
24
my %acceptedErrors = (
25
"42Y55" => 1 # DROP TABLE on non-existing table is accepted since
26
# tests rely on non-standard MySQL DROP IF EXISTS;
33
## The jdbc URL may contain both = and ;. These characters have to
34
## be encoded in order to pass unharmed through DBI. We assume
35
## here, that url=.... is the last part of the dsn, and encode
36
## everything after url=
38
my ($dsn_part1,$dsn_part2) = split(/url=/,$self->dsn());
40
$dsn_part2 =~ s/([=;])/uc sprintf("%%%02x",ord($1))/eg;
42
my $dbh = DBI->connect($dsn_part1."url=".$dsn_part2, undef, undef,
49
if (not defined $dbh) {
50
say("connect() to dsn ".$self->dsn()." failed: ".$DBI::errstr);
51
return STATUS_ENVIRONMENT_FAILURE;
60
my ($self, $query, $silent) = @_;
62
my $dbh = $self->dbh();
64
return GenTest::Result->new(
66
status => STATUS_UNKNOWN_ERROR )
69
$query = $self->preprocess($query);
71
## This may be generalized into a translator which is a pipe
73
my @pipe = (GenTest::Translator::Mysqldump2javadb->new(),
74
GenTest::Translator::MysqlDML2javadb->new());
76
foreach my $p (@pipe) {
77
$query = $p->translate($query);
78
return GenTest::Result->new(
80
status => STATUS_WONT_HANDLE )
86
## Reinit if connection is dead
87
say("JavaDB connection is dead. Reconnect");
94
my $db = $self->getName()." ".$self->version();
96
my $start_time = Time::HiRes::time();
99
my $sth = $dbh->prepare($query);
101
if (defined $dbh->err()) {
102
## Error on prepare. Check for the ones we accept (E.g. DROP
103
## TABLE on non-existing table)
104
if (not defined $acceptedErrors{$dbh->state()}) {
105
my $errstr = $db.":".$dbh->state().":".$dbh->errstr();
106
say($errstr . "($query)") if !$silent;
107
$self->[EXECUTOR_ERROR_COUNTS]->{$errstr}++ if rqg_debug() && !$silent;
108
return GenTest::Result->new(
110
status => $self->findStatus($dbh->state()),
112
errstr => $dbh->errstr(),
113
sqlstate => $dbh->state(),
114
start_time => $start_time,
115
end_time => Time::HiRes::time()
118
## E.g. DROP on non-existing table
119
return GenTest::Result->new(
123
start_time => $start_time,
124
end_time => Time::HiRes::time()
129
my $affected_rows = $sth->execute();
131
my $end_time = Time::HiRes::time();
133
my $err = $sth->err();
138
my $errstr = $db.":".$dbh->state().":".$dbh->errstr();
139
say($errstr . "($query)") if !$silent;
140
$self->[EXECUTOR_ERROR_COUNTS]->{$errstr}++ if rqg_debug() && !$silent;
141
return GenTest::Result->new(
143
status => $self->findStatus($dbh->state()),
145
errstr => $dbh->errstr(),
146
sqlstate => $dbh->state(),
147
start_time => $start_time,
148
end_time => $end_time
150
} elsif ((not defined $sth->{NUM_OF_FIELDS}) || ($sth->{NUM_OF_FIELDS} == 0)) {
151
## DDL/UPDATE/INSERT/DROP/DELETE
152
$result = GenTest::Result->new(
155
affected_rows => $affected_rows,
156
start_time => $start_time,
157
end_time => $end_time
159
$self->[EXECUTOR_ERROR_COUNTS]->{'(no error)'}++ if rqg_debug() && !$silent;
163
# We do not use fetchall_arrayref() due to a memory leak
164
# We also copy the row explicitly into a fresh array
165
# otherwise the entire @data array ends up referencing row #1 only
167
while (my $row = $sth->fetchrow_arrayref()) {
168
$self->normalize($row);
173
$result = GenTest::Result->new(
176
affected_rows => $affected_rows,
178
start_time => $start_time,
179
end_time => $end_time
182
$self->[EXECUTOR_ERROR_COUNTS]->{'(no error)'}++ if rqg_debug() && !$silent;
191
## Normalizing is in this case the process of making the rsult look
192
## like it came from MySQL
194
my ($self, $row) = @_;
198
foreach my $e (@row) {
199
## Remove .0 fractions from timestamps
200
$e =~ s/^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\.0+$/\1/;
208
say("Statistics for Executor ".$self->dsn());
210
$Data::Dumper::Sortkeys = 1;
211
say("Rows returned:");
212
print Dumper $self->[EXECUTOR_ROW_COUNTS];
213
say("Explain items:");
214
print Dumper $self->[EXECUTOR_EXPLAIN_COUNTS];
216
print Dumper $self->[EXECUTOR_ERROR_COUNTS];
217
say("Rare EXPLAIN items:");
218
print Dumper $self->[EXECUTOR_EXPLAIN_QUERIES];
220
$self->dbh()->disconnect();
225
return "Version N/A"; # Not implemented in DBD::JDBC