| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Test::Environment::Plugin::PostgreSQL; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Test::Environment::Plugin::PostgreSQL - PostreSQL psql function for testing |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
use Test::Environment qw{ |
|
10
|
|
|
|
|
|
|
PostgreSQL |
|
11
|
|
|
|
|
|
|
}; |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
# set database credentials |
|
14
|
|
|
|
|
|
|
psql( |
|
15
|
|
|
|
|
|
|
'database' => $config->{'db'}->{'database'}, |
|
16
|
|
|
|
|
|
|
'hostname' => $config->{'db'}->{'hostname'}, |
|
17
|
|
|
|
|
|
|
'username' => $config->{'db'}->{'username'}, |
|
18
|
|
|
|
|
|
|
'password' => $config->{'db'}->{'password'}, |
|
19
|
|
|
|
|
|
|
# or skip hostname and database and set them via |
|
20
|
|
|
|
|
|
|
#'dbi_dsn' => 'dbi:Pg:dbname=dsn_test;host=localhost', |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
); |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# execute sql query |
|
25
|
|
|
|
|
|
|
my @output = psql( |
|
26
|
|
|
|
|
|
|
'switches' => '--expanded', |
|
27
|
|
|
|
|
|
|
'command' => 'SELECT * FROM Table', |
|
28
|
|
|
|
|
|
|
# ..., see psql function description for more |
|
29
|
|
|
|
|
|
|
) |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
This plugin will export 'psql' function that can be used to execute PostreSQL psql command |
|
35
|
|
|
|
|
|
|
with lot of options for testing. |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
Module will prepare %ENV for postgres: |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
'username' => 'PGUSER', |
|
40
|
|
|
|
|
|
|
'password' => 'PGPASSWORD', |
|
41
|
|
|
|
|
|
|
'database' => 'PGDATABASE', |
|
42
|
|
|
|
|
|
|
'hostname' => 'PGHOST', |
|
43
|
|
|
|
|
|
|
'port' => 'PGPORT', |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
Any postgres connection settings not listed or undef will be deleted from the %ENV hash. |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=cut |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
|
|
50
|
1
|
|
|
1
|
|
9
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
49
|
|
|
51
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
53
|
|
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
our $VERSION = 0.03; |
|
54
|
|
|
|
|
|
|
|
|
55
|
1
|
|
|
1
|
|
6
|
use base qw{ Exporter }; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
145
|
|
|
56
|
|
|
|
|
|
|
our @EXPORT = qw{ |
|
57
|
|
|
|
|
|
|
psql |
|
58
|
|
|
|
|
|
|
}; |
|
59
|
|
|
|
|
|
|
our $debug = 0; |
|
60
|
|
|
|
|
|
|
|
|
61
|
1
|
|
|
1
|
|
6
|
use Carp::Clan; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
7
|
|
|
62
|
1
|
|
|
1
|
|
1145
|
use String::ShellQuote; |
|
|
1
|
|
|
|
|
968
|
|
|
|
1
|
|
|
|
|
76
|
|
|
63
|
1
|
|
|
1
|
|
3822
|
use List::MoreUtils 'any'; |
|
|
1
|
|
|
|
|
2698
|
|
|
|
1
|
|
|
|
|
107
|
|
|
64
|
1
|
|
|
1
|
|
339173
|
use DBI; |
|
|
1
|
|
|
|
|
73570
|
|
|
|
1
|
|
|
|
|
868
|
|
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=head1 FUNCTIONS |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=head2 import |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
All functions are exported 2 levels up. That is to the use Test::Environment caller. |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=cut |
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
sub import { |
|
75
|
1
|
|
|
1
|
|
2
|
my $package = shift; |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# export symbols two levels up - to the Test::Environment caller |
|
78
|
1
|
|
|
|
|
496
|
__PACKAGE__->export_to_level(2, $package, @EXPORT); |
|
79
|
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=head2 psql() |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
psql command executed easily. Here is the list of options that can be used. |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
Option related to the connection to the database. |
|
87
|
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
username |
|
89
|
|
|
|
|
|
|
password |
|
90
|
|
|
|
|
|
|
database |
|
91
|
|
|
|
|
|
|
hostname |
|
92
|
|
|
|
|
|
|
port |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
By setting this PostreSQL %ENV variables will be set. So for psql command to the |
|
95
|
|
|
|
|
|
|
same databse you need to set them only once. |
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
The rest of the option related to the psql command. |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
command - scalar or array ref of sql commands |
|
100
|
|
|
|
|
|
|
switches - scalar or array of additional psql switches |
|
101
|
|
|
|
|
|
|
output_filename - the output will be written to this file (-o) |
|
102
|
|
|
|
|
|
|
execution_path - before executing psql change to that folder |
|
103
|
|
|
|
|
|
|
stderr_redirect - will redirect stderr to stdout so that also error appears in the return value |
|
104
|
|
|
|
|
|
|
debug - turn on debug mode, it can be also done globaly by setting "$ENV{'IN_DEBUG_MODE'} = 1" |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=cut |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
sub psql { |
|
109
|
5
|
|
|
5
|
1
|
30191
|
my %arg = @_; |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# deparse dbi_dsn if passed |
|
112
|
5
|
100
|
|
|
|
34
|
if (defined $arg{'dbi_dsn'}) { |
|
113
|
2
|
|
|
|
|
36
|
my($scheme, $driver, $attr_string, $attr_hash, $driver_dsn) |
|
114
|
|
|
|
|
|
|
= DBI->parse_dsn($arg{'dbi_dsn'}); |
|
115
|
|
|
|
|
|
|
|
|
116
|
2
|
50
|
33
|
|
|
87
|
croak 'not a Pg dbi dsn "'.$arg{'dbi_dsn'}.'"' |
|
117
|
|
|
|
|
|
|
if (($scheme ne 'dbi') or ($driver ne 'Pg')); |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# contruct hash out of "dbname=dsn_test;host=localhost;port=123" |
|
120
|
2
|
|
|
|
|
13
|
my %dsn_options = map { split '=', $_ } split(';',$driver_dsn); |
|
|
5
|
|
|
|
|
23
|
|
|
121
|
|
|
|
|
|
|
|
|
122
|
2
|
50
|
|
|
|
150
|
$arg{'database'} = $dsn_options{'dbname'} |
|
123
|
|
|
|
|
|
|
if exists $dsn_options{'dbname'}; |
|
124
|
2
|
50
|
|
|
|
17
|
$arg{'hostname'} = $dsn_options{'host'} |
|
125
|
|
|
|
|
|
|
if exists $dsn_options{'host'}; |
|
126
|
2
|
100
|
|
|
|
13
|
$arg{'port'} = $dsn_options{'port'} |
|
127
|
|
|
|
|
|
|
if exists $dsn_options{'port'}; |
|
128
|
|
|
|
|
|
|
} |
|
129
|
|
|
|
|
|
|
|
|
130
|
5
|
|
|
|
|
37
|
my %pg_settings_names = ( |
|
131
|
|
|
|
|
|
|
'username' => 'PGUSER', |
|
132
|
|
|
|
|
|
|
'password' => 'PGPASSWORD', |
|
133
|
|
|
|
|
|
|
'database' => 'PGDATABASE', |
|
134
|
|
|
|
|
|
|
'hostname' => 'PGHOST', |
|
135
|
|
|
|
|
|
|
'port' => 'PGPORT', |
|
136
|
|
|
|
|
|
|
); |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
# change %ENV only if at least one pg connection setting set |
|
139
|
5
|
100
|
|
8
|
|
96
|
if (any { $pg_settings_names{$_} } keys %arg) { |
|
|
8
|
|
|
|
|
34
|
|
|
140
|
|
|
|
|
|
|
# set/delete postgres ENV variables |
|
141
|
4
|
|
|
|
|
17
|
foreach my $arg_name (keys %pg_settings_names) { |
|
142
|
20
|
|
|
|
|
36
|
my $env_name = $pg_settings_names{$arg_name}; |
|
143
|
20
|
100
|
|
|
|
136
|
( defined $arg{$arg_name} |
|
144
|
|
|
|
|
|
|
? $ENV{$env_name} = $arg{$arg_name} |
|
145
|
|
|
|
|
|
|
: delete $ENV{$env_name} |
|
146
|
|
|
|
|
|
|
); |
|
147
|
|
|
|
|
|
|
} |
|
148
|
|
|
|
|
|
|
} |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
# function paramaters |
|
151
|
5
|
|
|
|
|
27
|
my $command = $arg{'command'}; |
|
152
|
5
|
|
|
|
|
12
|
my $output_filename = $arg{'output_filename'}; |
|
153
|
5
|
|
|
|
|
10
|
my $execution_path = $arg{'execution_path'}; |
|
154
|
5
|
|
|
|
|
10
|
my $stderr_redirect = $arg{'stderr_redirect'}; |
|
155
|
|
|
|
|
|
|
|
|
156
|
5
|
50
|
|
|
|
23
|
my @switches = (ref $arg{'switches'} eq 'ARRAY' ? @{$arg{'switches'}} : $arg{'switches'} ) |
|
|
0
|
100
|
|
|
|
0
|
|
|
157
|
|
|
|
|
|
|
if exists $arg{'switches'}; |
|
158
|
|
|
|
|
|
|
|
|
159
|
5
|
50
|
33
|
|
|
39
|
local $debug = 1 if ($arg{'debug'} or $ENV{'IN_DEBUG_MODE'}); |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# if there is no command return nothink to do more |
|
162
|
5
|
100
|
|
|
|
31
|
return if not defined $command; |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
# if more commands then join them together |
|
165
|
1
|
50
|
|
|
|
6
|
if (ref $command eq 'ARRAY') { |
|
166
|
0
|
|
|
|
|
0
|
$command = join '; ', @{$command}; |
|
|
0
|
|
|
|
|
0
|
|
|
167
|
|
|
|
|
|
|
} |
|
168
|
1
|
50
|
|
|
|
8
|
$command .= ';' if ($command !~ m{;\s*$}xms); |
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
|
|
171
|
1
|
50
|
|
|
|
9
|
if (defined $output_filename) { |
|
172
|
1
|
|
|
|
|
5
|
push(@switches, '-o', '"'.$output_filename.'"') |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
# redirect stderr to stdout |
|
176
|
1
|
50
|
|
|
|
5
|
open(STDERR, ">&STDOUT") if (defined $stderr_redirect); |
|
177
|
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
# chdir if needed |
|
179
|
1
|
50
|
|
|
|
5
|
if (defined $execution_path) { |
|
180
|
1
|
50
|
|
|
|
5
|
print STDERR '+ cd ', $execution_path, "\n" if $debug; |
|
181
|
1
|
|
|
|
|
1510
|
chdir($execution_path); |
|
182
|
|
|
|
|
|
|
} |
|
183
|
|
|
|
|
|
|
|
|
184
|
1
|
|
|
|
|
25
|
my @ret = execute( |
|
185
|
|
|
|
|
|
|
'psql', |
|
186
|
|
|
|
|
|
|
@switches, |
|
187
|
|
|
|
|
|
|
'-c', |
|
188
|
|
|
|
|
|
|
$command, |
|
189
|
|
|
|
|
|
|
); |
|
190
|
|
|
|
|
|
|
|
|
191
|
1
|
50
|
|
|
|
103
|
return @ret if defined wantarray; |
|
192
|
0
|
|
|
|
|
|
return join('', @ret); |
|
193
|
|
|
|
|
|
|
} |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=head2 execute |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
Executes command as system and return output. |
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
In debug mode prints command to stderr. |
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=cut |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
sub execute { |
|
205
|
|
|
|
|
|
|
my $cmd = shell_quote @_; |
|
206
|
|
|
|
|
|
|
print STDERR '+ ', $cmd, "\n" if $debug; |
|
207
|
|
|
|
|
|
|
my @ret = `$cmd`; |
|
208
|
|
|
|
|
|
|
} |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
1; |
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
Test::Environment L |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=head1 AUTHOR |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
Jozef Kutej - Ejozef@kutej.netE |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
=cut |