~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to lib/GenTest/Executor/Postgres.pm

merge from internal tree

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
package GenTest::Executor::Postgres;
2
2
 
3
 
use GenTest;
4
 
use GenTest::Executor;
5
 
require Exporter;
6
 
 
7
3
@ISA = qw(GenTest::Executor);
8
4
 
9
5
use strict;
10
6
use DBI;
11
7
 
 
8
use GenTest;
 
9
use GenTest::Constants;
 
10
use GenTest::Result;
 
11
use GenTest::Executor;
 
12
use GenTest::Translator;
 
13
use GenTest::Translator::MysqlDML2ANSI;
 
14
use GenTest::Translator::Mysqldump2ANSI;
 
15
use GenTest::Translator::MysqlDML2pgsql;
 
16
use GenTest::Translator::Mysqldump2pgsql;
 
17
use Time::HiRes;
 
18
 
12
19
sub init {
13
 
        my $executor = shift;
14
 
        my $dbh =  DBI->connect($executor->dsn());
15
 
        $executor->setDbh($dbh);        
 
20
        my $self = shift;
 
21
 
 
22
        my $dbh =  DBI->connect($self->dsn(), undef, undef,
 
23
                            {
 
24
                                PrintError => 0,
 
25
                                RaiseError => 0,
 
26
                                AutoCommit => 1}
 
27
        );
 
28
 
 
29
    if (not defined $dbh) {
 
30
        say("connect() to dsn ".$self->dsn()." failed: ".$DBI::errstr);
 
31
        return STATUS_ENVIRONMENT_FAILURE;
 
32
    }
 
33
    
 
34
        $self->setDbh($dbh);    
 
35
 
 
36
    return STATUS_OK;
16
37
}
17
38
 
 
39
my %acceptedErrors = (
 
40
    "42P01" => 1 # DROP TABLE on non-existing table is accepted since
 
41
                 # tests rely on non-standard MySQL DROP IF EXISTS;
 
42
    );
 
43
 
18
44
sub execute {
19
 
        my ($executor, $query) = @_;
20
 
        my $dbh = $executor->dbh();
21
 
        my $sth = $dbh->prepare($query);
22
 
        $sth->execute();
23
 
        return $sth->fetchall_arrayref();
24
 
}
 
45
    my ($self, $query, $silent) = @_;
 
46
 
 
47
    my $dbh = $self->dbh();
 
48
 
 
49
    return GenTest::Result->new( 
 
50
        query => $query, 
 
51
        status => STATUS_UNKNOWN_ERROR ) 
 
52
        if not defined $dbh;
 
53
    
 
54
    $query = $self->preprocess($query);
 
55
    
 
56
    ## This may be generalized into a translator which is a pipe
 
57
 
 
58
    my @pipe = (GenTest::Translator::Mysqldump2pgsql->new(),
 
59
                GenTest::Translator::MysqlDML2pgsql->new());
 
60
 
 
61
    foreach my $p (@pipe) {
 
62
        $query = $p->translate($query);
 
63
        return GenTest::Result->new( 
 
64
            query => $query, 
 
65
            status => STATUS_WONT_HANDLE ) 
 
66
            if not $query;
 
67
    }
 
68
 
 
69
    # Autocommit ?
 
70
 
 
71
    my $db = $self->getName()." ".$self->version();
 
72
 
 
73
    my $start_time = Time::HiRes::time();
 
74
 
 
75
    my $sth = $dbh->prepare($query);
 
76
 
 
77
    if (defined $dbh->err()) {
 
78
        my $errstr = $db.":".$dbh->state().":".$dbh->errstr();
 
79
        say($errstr . "($query)") if !$silent;
 
80
        $self->[EXECUTOR_ERROR_COUNTS]->{$errstr}++ if rqg_debug() && !$silent;
 
81
        return GenTest::Result->new(
 
82
            query       => $query,
 
83
            status      => $self->findStatus($dbh->state()),
 
84
            err         => $dbh->err(),
 
85
            errstr      => $dbh->errstr(),
 
86
            sqlstate    => $dbh->state(),
 
87
            start_time  => $start_time,
 
88
            end_time    => Time::HiRes::time()
 
89
            );
 
90
    }
 
91
 
 
92
 
 
93
    my $affected_rows = $sth->execute();
 
94
 
 
95
    
 
96
    my $end_time = Time::HiRes::time();
 
97
    
 
98
    my $err = $sth->err();
 
99
    my $result;
 
100
    
 
101
    if (defined $err) {         
 
102
        if (not defined $acceptedErrors{$dbh->state()}) {
 
103
            ## Error on EXECUTE
 
104
            my $errstr = $db.":".$dbh->state().":".$dbh->errstr();
 
105
            say($errstr . "($query)") if !$silent;
 
106
            $self->[EXECUTOR_ERROR_COUNTS]->{$errstr}++ if rqg_debug() && !$silent;
 
107
            return GenTest::Result->new(
 
108
                query       => $query,
 
109
                status      => $self->findStatus($dbh->state()),
 
110
                err         => $dbh->err(),
 
111
                errstr      => $dbh->errstr(),
 
112
                sqlstate    => $dbh->state(),
 
113
                start_time  => $start_time,
 
114
                end_time    => $end_time
 
115
                );
 
116
        } else {
 
117
            ## E.g. DROP on non-existing table
 
118
            return GenTest::Result->new(
 
119
                query       => $query,
 
120
                status      => STATUS_OK,
 
121
                affected_rows => 0,
 
122
                start_time  => $start_time,
 
123
                end_time    => Time::HiRes::time()
 
124
                );
 
125
        }
 
126
 
 
127
    } elsif ((not defined $sth->{NUM_OF_FIELDS}) || ($sth->{NUM_OF_FIELDS} == 0)) {
 
128
        ## DDL/UPDATE/INSERT/DROP/DELETE
 
129
        $result = GenTest::Result->new(
 
130
            query       => $query,
 
131
            status      => STATUS_OK,
 
132
            affected_rows   => $affected_rows,
 
133
            start_time  => $start_time,
 
134
            end_time    => $end_time
 
135
            );
 
136
        $self->[EXECUTOR_ERROR_COUNTS]->{'(no error)'}++ if rqg_debug() && !$silent;
 
137
    } else {
 
138
        ## Query
 
139
        
 
140
        # We do not use fetchall_arrayref() due to a memory leak
 
141
        # We also copy the row explicitly into a fresh array
 
142
        # otherwise the entire @data array ends up referencing row #1 only
 
143
        my @data;
 
144
        while (my $row = $sth->fetchrow_arrayref()) {
 
145
            my @row = @$row;
 
146
            push @data, \@row;
 
147
        }   
 
148
        
 
149
        $result = GenTest::Result->new(
 
150
            query       => $query,
 
151
            status      => STATUS_OK,
 
152
            affected_rows   => $affected_rows,
 
153
            data        => \@data,
 
154
            start_time  => $start_time,
 
155
            end_time    => $end_time
 
156
            );
 
157
        
 
158
        $self->[EXECUTOR_ERROR_COUNTS]->{'(no error)'}++ if rqg_debug() && !$silent;
 
159
    }
 
160
 
 
161
    $sth->finish();
 
162
 
 
163
    return $result;
 
164
}
 
165
 
 
166
sub version {
 
167
        my $self = shift;
 
168
        my $dbh = $self->dbh();
 
169
    return $dbh->get_info(18);
 
170
}
 
171
 
 
172
1;