~ubuntu-branches/ubuntu/vivid/drizzle/vivid-proposed

« back to all changes in this revision

Viewing changes to tests/kewpie/randgen/lib/GenTest/Executor/Postgres.pm

  • Committer: Package Import Robot
  • Author(s): Tobias Frost
  • Date: 2013-08-22 20:18:31 UTC
  • mto: (20.1.1 sid)
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: package-import@ubuntu.com-20130822201831-gn3ozsh7o7wmc5tk
Tags: upstream-7.2.3
ImportĀ upstreamĀ versionĀ 7.2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (c) 2009,2010 Oracle and/or its affiliates. All rights reserved.
2
 
# Use is subject to license terms.
3
 
#
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.
7
 
#
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.
12
 
#
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
16
 
# USA
17
 
 
18
 
package GenTest::Executor::Postgres;
19
 
 
20
 
@ISA = qw(GenTest::Executor);
21
 
 
22
 
use strict;
23
 
use DBI;
24
 
 
25
 
use GenTest;
26
 
use GenTest::Constants;
27
 
use GenTest::Result;
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;
34
 
use Time::HiRes;
35
 
use Data::Dumper;
36
 
 
37
 
sub init {
38
 
        my $self = shift;
39
 
 
40
 
        my $dbh =  DBI->connect($self->dsn(), undef, undef,
41
 
                            {
42
 
                                PrintError => 0,
43
 
                                RaiseError => 0,
44
 
                                AutoCommit => 1}
45
 
        );
46
 
 
47
 
    if (not defined $dbh) {
48
 
        say("connect() to dsn ".$self->dsn()." failed: ".$DBI::errstr);
49
 
        return STATUS_ENVIRONMENT_FAILURE;
50
 
    }
51
 
    
52
 
        $self->setDbh($dbh);    
53
 
 
54
 
    $self->defaultSchema($self->currentSchema());
55
 
    say "Default schema: ".$self->defaultSchema();
56
 
 
57
 
    return STATUS_OK;
58
 
}
59
 
 
60
 
my %caches;
61
 
 
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
66
 
    );
67
 
 
68
 
sub execute {
69
 
    my ($self, $query, $silent) = @_;
70
 
 
71
 
    my $dbh = $self->dbh();
72
 
 
73
 
    return GenTest::Result->new( 
74
 
        query => $query, 
75
 
        status => STATUS_UNKNOWN_ERROR ) 
76
 
        if not defined $dbh;
77
 
 
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;
82
 
    
83
 
    $query = $self->preprocess($query);
84
 
    
85
 
    ## This may be generalized into a translator which is a pipe
86
 
 
87
 
    my @pipe = (GenTest::Translator::Mysqldump2pgsql->new(),
88
 
                GenTest::Translator::MysqlDML2pgsql->new());
89
 
 
90
 
    foreach my $p (@pipe) {
91
 
        $query = $p->translate($query);
92
 
        return GenTest::Result->new( 
93
 
            query => $query, 
94
 
            status => STATUS_WONT_HANDLE ) 
95
 
            if not $query;
96
 
    }
97
 
 
98
 
    # Autocommit ?
99
 
 
100
 
    my $db = $self->getName()." ".$self->version();
101
 
 
102
 
    my $start_time = Time::HiRes::time();
103
 
 
104
 
    my $sth = $dbh->prepare($query);
105
 
 
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(
111
 
            query       => $query,
112
 
            status      => $self->findStatus($dbh->state()),
113
 
            err         => $dbh->err(),
114
 
            errstr      => $dbh->errstr(),
115
 
            sqlstate    => $dbh->state(),
116
 
            start_time  => $start_time,
117
 
            end_time    => Time::HiRes::time()
118
 
            );
119
 
    }
120
 
 
121
 
 
122
 
    my $affected_rows = $sth->execute();
123
 
 
124
 
    
125
 
    my $end_time = Time::HiRes::time();
126
 
    
127
 
    my $err = $sth->err();
128
 
    my $result;
129
 
    
130
 
    if (defined $err) {         
131
 
        if (not defined $acceptedErrors{$dbh->state()}) {
132
 
            ## Error on EXECUTE
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(
137
 
                query       => $query,
138
 
                status      => $self->findStatus($dbh->state()),
139
 
                err         => $dbh->err(),
140
 
                errstr      => $dbh->errstr(),
141
 
                sqlstate    => $dbh->state(),
142
 
                start_time  => $start_time,
143
 
                end_time    => $end_time
144
 
                );
145
 
        } else {
146
 
            ## E.g. DROP on non-existing table
147
 
            return GenTest::Result->new(
148
 
                query       => $query,
149
 
                status      => STATUS_OK,
150
 
                affected_rows => 0,
151
 
                start_time  => $start_time,
152
 
                end_time    => Time::HiRes::time()
153
 
                );
154
 
        }
155
 
 
156
 
    } elsif ((not defined $sth->{NUM_OF_FIELDS}) || ($sth->{NUM_OF_FIELDS} == 0)) {
157
 
        ## DDL/UPDATE/INSERT/DROP/DELETE
158
 
        $result = GenTest::Result->new(
159
 
            query       => $query,
160
 
            status      => STATUS_OK,
161
 
            affected_rows   => $affected_rows,
162
 
            start_time  => $start_time,
163
 
            end_time    => $end_time
164
 
            );
165
 
        $self->[EXECUTOR_ERROR_COUNTS]->{'(no error)'}++ if rqg_debug() && !$silent;
166
 
    } else {
167
 
        ## Query
168
 
        
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
172
 
        my @data;
173
 
        while (my $row = $sth->fetchrow_arrayref()) {
174
 
            my @row = @$row;
175
 
            push @data, \@row;
176
 
        }   
177
 
        
178
 
        $result = GenTest::Result->new(
179
 
            query       => $query,
180
 
            status      => STATUS_OK,
181
 
            affected_rows   => $affected_rows,
182
 
            data        => \@data,
183
 
            start_time  => $start_time,
184
 
            end_time    => $end_time
185
 
            );
186
 
        
187
 
        $self->[EXECUTOR_ERROR_COUNTS]->{'(no error)'}++ if rqg_debug() && !$silent;
188
 
    }
189
 
 
190
 
    $sth->finish();
191
 
 
192
 
    return $result;
193
 
}
194
 
 
195
 
sub findStatus {
196
 
    my ($self, $state) = @_;
197
 
 
198
 
    if ($state eq "22000") {
199
 
        return STATUS_SERVER_CRASHED;
200
 
    } elsif (($state eq '42000') || ($state eq '42601')) {
201
 
        return STATUS_SYNTAX_ERROR;
202
 
    } else {
203
 
        return $self->SUPER::findStatus(@_);
204
 
    }
205
 
}
206
 
 
207
 
sub version {
208
 
    my $self = shift;
209
 
    my $dbh = $self->dbh();
210
 
    return $dbh->get_info(18);
211
 
}
212
 
 
213
 
sub currentSchema {
214
 
        my ($self,$schema) = @_;
215
 
 
216
 
        return undef if not defined $self->dbh();
217
 
    
218
 
    if (defined $schema) {
219
 
        $self->execute("SET search_path TO $schema");
220
 
    }
221
 
    
222
 
        return $self->dbh()->selectrow_array("SELECT current_schema()");
223
 
}
224
 
 
225
 
sub getSchemaMetaData {
226
 
    ## Return the result from a query with the following columns:
227
 
    ## 1. Schema (aka database) name
228
 
    ## 2. Table name
229
 
    ## 3. TABLE for tables VIEW for views and MISC for other stuff
230
 
    ## 4. Column name
231
 
    ## 5. PRIMARY for primary key, INDEXED for indexed column and "ORDINARY" for all other columns
232
 
    my ($self) = @_;
233
 
    my $query = 
234
 
        "SELECT table_schema, ".
235
 
               "table_name, ".
236
 
               "CASE WHEN table_type = 'BASE TABLE' THEN 'table' ".
237
 
                    "WHEN table_type = 'VIEW' THEN 'view' ".
238
 
                    "WHEN table_type = 'SYSTEM VIEW' then 'view' ".
239
 
                    "ELSE 'misc' END, ".
240
 
               "column_name, ".
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'"; 
245
 
 
246
 
    return $self->dbh()->selectall_arrayref($query);
247
 
}
248
 
 
249
 
#### This query gives columns with keys (PK and unique constraint, but not indices)
250
 
 
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')";
261
 
 
262
 
sub getCollationMetaData {
263
 
    ## Return the result from a query with the following columns:
264
 
    ## 1. Collation name
265
 
    ## 2. Character set
266
 
    my ($self) = @_;
267
 
    my $query = 
268
 
        "SELECT collation_name,character_set_name FROM information_schema.collations";
269
 
 
270
 
    return [];
271
 
}
272
 
 
273
 
sub disconnect {
274
 
    my ($self) = @_;
275
 
    $self->dbh->disconnect;
276
 
    $self->setDbh(undef);
277
 
}
278
 
 
279
 
 
280
 
 
281
 
1;