1
# Copyright (c) 2009,2010 Oracle and/or its affiliates. All rights reserved.
2
# Use is subject to license terms.
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; version 2 of the License.
8
# This program is distributed in the hope that it will be useful, but
9
# WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
# General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
18
package GenTest::Executor::Postgres;
20
@ISA = qw(GenTest::Executor);
26
use GenTest::Constants;
28
use GenTest::Executor;
29
use GenTest::Translator;
30
use GenTest::Translator::MysqlDML2ANSI;
31
use GenTest::Translator::Mysqldump2ANSI;
32
use GenTest::Translator::MysqlDML2pgsql;
33
use GenTest::Translator::Mysqldump2pgsql;
40
my $dbh = DBI->connect($self->dsn(), undef, undef,
47
if (not defined $dbh) {
48
say("connect() to dsn ".$self->dsn()." failed: ".$DBI::errstr);
49
return STATUS_ENVIRONMENT_FAILURE;
54
$self->defaultSchema($self->currentSchema());
55
say "Default schema: ".$self->defaultSchema();
62
my %acceptedErrors = (
63
"42P01" => 1,# DROP TABLE on non-existing table is accepted since
64
# tests rely on non-standard MySQL DROP IF EXISTS;
65
"42P06" => 1 # Schema already exists
69
my ($self, $query, $silent) = @_;
71
my $dbh = $self->dbh();
73
return GenTest::Result->new(
75
status => STATUS_UNKNOWN_ERROR )
78
# Filter out any /*executor */ comments that do not pertain to this particular Executor/DBI
79
my $executor_id = $self->id();
80
$query =~ s{/\*executor$executor_id (.*?) \*/}{$1}sg;
81
$query =~ s{/\*executor.*?\*/}{}sgo;
83
$query = $self->preprocess($query);
85
## This may be generalized into a translator which is a pipe
87
my @pipe = (GenTest::Translator::Mysqldump2pgsql->new(),
88
GenTest::Translator::MysqlDML2pgsql->new());
90
foreach my $p (@pipe) {
91
$query = $p->translate($query);
92
return GenTest::Result->new(
94
status => STATUS_WONT_HANDLE )
100
my $db = $self->getName()." ".$self->version();
102
my $start_time = Time::HiRes::time();
104
my $sth = $dbh->prepare($query);
106
if (defined $dbh->err()) {
107
my $errstr = $db.":".$dbh->state().":".$dbh->errstr();
108
say("Query: $query failed: $errstr.") if !$silent;
109
$self->[EXECUTOR_ERROR_COUNTS]->{$errstr}++ if rqg_debug() && !$silent;
110
return GenTest::Result->new(
112
status => $self->findStatus($dbh->state()),
114
errstr => $dbh->errstr(),
115
sqlstate => $dbh->state(),
116
start_time => $start_time,
117
end_time => Time::HiRes::time()
122
my $affected_rows = $sth->execute();
125
my $end_time = Time::HiRes::time();
127
my $err = $sth->err();
131
if (not defined $acceptedErrors{$dbh->state()}) {
133
my $errstr = $db.":".$dbh->state().":".$dbh->errstr();
134
say("Query: $query failed: $errstr.") if !$silent;
135
$self->[EXECUTOR_ERROR_COUNTS]->{$errstr}++ if rqg_debug() && !$silent;
136
return GenTest::Result->new(
138
status => $self->findStatus($dbh->state()),
140
errstr => $dbh->errstr(),
141
sqlstate => $dbh->state(),
142
start_time => $start_time,
143
end_time => $end_time
146
## E.g. DROP on non-existing table
147
return GenTest::Result->new(
151
start_time => $start_time,
152
end_time => Time::HiRes::time()
156
} elsif ((not defined $sth->{NUM_OF_FIELDS}) || ($sth->{NUM_OF_FIELDS} == 0)) {
157
## DDL/UPDATE/INSERT/DROP/DELETE
158
$result = GenTest::Result->new(
161
affected_rows => $affected_rows,
162
start_time => $start_time,
163
end_time => $end_time
165
$self->[EXECUTOR_ERROR_COUNTS]->{'(no error)'}++ if rqg_debug() && !$silent;
169
# We do not use fetchall_arrayref() due to a memory leak
170
# We also copy the row explicitly into a fresh array
171
# otherwise the entire @data array ends up referencing row #1 only
173
while (my $row = $sth->fetchrow_arrayref()) {
178
$result = GenTest::Result->new(
181
affected_rows => $affected_rows,
183
start_time => $start_time,
184
end_time => $end_time
187
$self->[EXECUTOR_ERROR_COUNTS]->{'(no error)'}++ if rqg_debug() && !$silent;
196
my ($self, $state) = @_;
198
if ($state eq "22000") {
199
return STATUS_SERVER_CRASHED;
200
} elsif (($state eq '42000') || ($state eq '42601')) {
201
return STATUS_SYNTAX_ERROR;
203
return $self->SUPER::findStatus(@_);
209
my $dbh = $self->dbh();
210
return $dbh->get_info(18);
214
my ($self,$schema) = @_;
216
return undef if not defined $self->dbh();
218
if (defined $schema) {
219
$self->execute("SET search_path TO $schema");
222
return $self->dbh()->selectrow_array("SELECT current_schema()");
225
sub getSchemaMetaData {
226
## Return the result from a query with the following columns:
227
## 1. Schema (aka database) name
229
## 3. TABLE for tables VIEW for views and MISC for other stuff
231
## 5. PRIMARY for primary key, INDEXED for indexed column and "ORDINARY" for all other columns
234
"SELECT table_schema, ".
236
"CASE WHEN table_type = 'BASE TABLE' THEN 'table' ".
237
"WHEN table_type = 'VIEW' THEN 'view' ".
238
"WHEN table_type = 'SYSTEM VIEW' then 'view' ".
241
"'ordinary'". ## Need to figure out how to find indexes and primary keys
242
"FROM information_schema.tables INNER JOIN ".
243
"information_schema.columns USING(table_schema, table_name) ".
244
"WHERE table_name <> 'dummy'";
246
return $self->dbh()->selectall_arrayref($query);
249
#### This query gives columns with keys (PK and unique constraint, but not indices)
251
# "select column_name from information_schema.columns ".
252
# "where table_schema = 'public' and ".
253
# "table_name = '$table' and ".
254
# "table_schema = '$dbname' and ".
255
# "column_name not in ".
256
# "(select k.column_name from ".
257
# "information_schema.key_column_usage as k ".
258
# "inner join information_schema.columns ".
259
# "using(table_name, table_schema, column_name) ".
260
# "where table_name='$table' and table_schema='$dbname')";
262
sub getCollationMetaData {
263
## Return the result from a query with the following columns:
268
"SELECT collation_name,character_set_name FROM information_schema.collations";
275
$self->dbh->disconnect;
276
$self->setDbh(undef);