File Coverage

blib/lib/DBIx/dbMan/DBI.pm
Criterion Covered Total %
statement 21 236 8.9
branch 0 132 0.0
condition 0 15 0.0
subroutine 7 43 16.2
pod 0 34 0.0
total 28 460 6.0


line stmt bran cond sub pod time code
1             package DBIx::dbMan::DBI;
2              
3 3     3   465 use strict;
  3         12  
  3         85  
4 3     3   397 use locale;
  3         518  
  3         18  
5 3     3   160 use vars qw/$AUTOLOAD/;
  3         7  
  3         135  
6              
7 3     3   403 use POSIX;
  3         6648  
  3         22  
8 3     3   6770 use DBIx::dbMan::Config;
  3         7  
  3         77  
9 3     3   1182 use DBIx::dbMan::MemPool;
  3         9  
  3         88  
10 3     3   4103 use DBI;
  3         52787  
  3         10679  
11              
12             our $VERSION = '0.15';
13              
14             1;
15              
16             sub new {
17 0     0 0   my $class = shift;
18 0           my $obj = bless { @_ }, $class;
19              
20 0           $obj->clear_all_connections;
21 0           $obj->load_groups();
22 0           $obj->load_connections;
23              
24 0           return $obj;
25             }
26              
27             sub connectiondir {
28 0     0 0   my $obj = shift;
29              
30 0 0         return $ENV{ DBMAN_CONNECTIONDIR } if $ENV{ DBMAN_CONNECTIONDIR };
31              
32 0 0         return $obj->{ -config }->connection_dir if $obj->{ -config }->connection_dir;
33              
34 0 0         mkdir $ENV{ HOME } . '/.dbman/connections' unless -d $ENV{ HOME } . '/.dbman/connections';
35              
36 0           return $ENV{ HOME } . '/.dbman/connections';
37             }
38              
39             sub groupdir {
40 0     0 0   my $obj = shift;
41              
42 0 0         return $ENV{ DBMAN_GROUPDIR } if $ENV{ DBMAN_GROUPDIR };
43              
44 0 0         mkdir $ENV{ HOME } . '/.dbman/groups' unless -d $ENV{ HOME } . '/.dbman/groups';
45              
46 0           return $ENV{ HOME } . '/.dbman/groups';
47             }
48              
49             sub clear_all_connections {
50 0     0 0   my $obj = shift;
51 0           $obj->{ connections } = {};
52             }
53              
54             sub load_group {
55 0     0 0   my ( $obj, $name ) = @_;
56              
57 0           my $gdir = $obj->groupdir();
58 0 0         return -1 unless -d $gdir;
59 0           $gdir =~ s/\/$//;
60 0 0         return -2 unless -f "$gdir/$name";
61              
62 0           return new DBIx::dbMan::Config -file => "$gdir/$name";
63             }
64              
65             sub load_groups {
66 0     0 0   my $obj = shift;
67              
68 0           my $sdir = $obj->groupdir;
69 0           my %groups = ();
70              
71 0 0         if ( -d $sdir ) {
72 0           opendir S, $sdir;
73 0           for my $group ( grep ! /^\.\.?/, readdir S ) {
74 0           $groups{ $group } = $obj->load_group( $group );
75             }
76 0           closedir S;
77             }
78              
79 0           $obj->{ _groups } = \%groups;
80             }
81              
82             sub get_group {
83 0     0 0   my ( $obj, $group ) = @_;
84              
85 0           return $obj->{ _groups }->{ $group };
86             }
87              
88             sub load_connections {
89 0     0 0   my $obj = shift;
90              
91 0           my $cdir = $obj->connectiondir;
92 0 0         return -1 unless -d $cdir;
93              
94 0           opendir D, $cdir;
95 0           $obj->load_connection( $_ ) for grep ! /^\.\.?/, readdir D;
96 0           closedir D;
97              
98 0           my $current = '';
99 0 0         $current = $obj->{ -config }->current_connection if $obj->{ -config }->current_connection;
100             $obj->{ -interface }->add_to_actionlist(
101             {
102 0           action => 'CONNECTION',
103             operation => 'use', what => $current
104             }
105             );
106             }
107              
108             sub load_connection {
109 0     0 0   my ( $obj, $name ) = @_;
110              
111 0           my $cdir = $obj->connectiondir;
112 0 0         return -1 unless -d $cdir;
113 0           $cdir =~ s/\/$//;
114 0 0         return -2 unless -f "$cdir/$name";
115              
116 0           my $lcfg = new DBIx::dbMan::Config -file => "$cdir/$name";
117              
118 0           my %processed_groups = ();
119 0 0         if ( $lcfg->group() ) {
120 0           my $something_processed = 1;
121 0           while ( $something_processed ) {
122 0           $something_processed = 0;
123 0           for ( $lcfg->group() ) {
124 0 0         next if $processed_groups{ $_ };
125 0           ++$something_processed;
126 0 0         print STDERR "Error: Can't use group '$_' for connection '$name'\n" unless $lcfg->merge( $obj->get_group( $_ ) );
127 0           ++$processed_groups{ $_ };
128             }
129             }
130             }
131              
132 0           my %connection;
133 0           $connection{ $_ } = $lcfg->$_ for $lcfg->all_tags;
134 0           $obj->{ connections }->{ $name } = \%connection;
135              
136             $obj->{ -interface }->add_to_actionlist(
137             {
138 0 0         action => 'CONNECTION',
139             operation => 'open', what => $name
140             }
141             ) if lc $lcfg->auto_login eq 'yes';
142             }
143              
144             sub open {
145 0     0 0   my ( $obj, $name ) = @_;
146              
147 0 0         return -3 unless exists $obj->{ connections }->{ $name };
148 0 0         return -4 if $obj->{ connections }->{ $name }->{ -logged };
149 0 0         return -1 unless grep { $_ eq $obj->{ connections }->{ $name }->{ driver } } $obj->driverlist;
  0            
150              
151 0           my %vars = qw/PrintError 0 RaiseError 0 AutoCommit 1 LongTruncOk 1/;
152              
153             # in case Oracle we need from 11R2 provide information about supported signals
154 0 0         if ( $obj->{ connections }->{ $name }->{ driver } eq 'Oracle' ) {
155 0           $vars{ ora_connect_with_default_signals } = [ 'INT' ];
156             }
157              
158 0 0         if ( $obj->{ connections }->{ $name }->{ config } ) {
159 0           for ( split /;\s*/, $obj->{ connections }->{ $name }->{ config } ) {
160 0 0         if ( /^\s*(\S+?)\s*=\s*(\S+)\s*$/ ) {
161 0           my ( $var, $val ) = ( $1, $2 );
162 0 0         next if $var eq 'AutoCommit'; # everything unless transactions
163 0 0 0       $val = eval $val if $val =~ /^\[(.*)\]$/ || $val =~ /^\{(.*)\}$/;
164 0           $vars{ $var } = $val;
165             }
166             }
167             }
168              
169             my $dbi = DBI->connect(
170             'dbi:' . $obj->{ connections }->{ $name }->{ driver } . ':' . $obj->{ connections }->{ $name }->{ dsn },
171             $obj->{ connections }->{ $name }->{ login },
172             $obj->{ connections }->{ $name }->{ password },
173 0           \%vars
174             );
175              
176 0 0         return -2 unless defined $dbi;
177              
178 0           $obj->{ connections }->{ $name }->{ -dbi } = $dbi;
179 0           $obj->{ connections }->{ $name }->{ -mempool } = new DBIx::dbMan::MemPool;
180 0           $obj->{ connections }->{ $name }->{ -logged } = 1;
181 0           $obj->{ -interface }->add_to_actionlist( { action => 'AUTO_SQL', connection => $name } );
182              
183 0           return 0;
184             }
185              
186             sub driverlist {
187 0     0 0   my $obj = shift;
188 0           return DBI->available_drivers;
189             }
190              
191             sub close {
192 0     0 0   my ( $obj, $name ) = @_;
193              
194 0 0         return -1 unless exists $obj->{ connections }->{ $name };
195 0 0         return -2 unless $obj->{ connections }->{ $name }->{ -logged };
196              
197 0 0         $obj->set_current() if $obj->{ current } eq $name;
198 0           $obj->discard_profile_data();
199 0           delete $obj->{ connections }->{ $name }->{ -logged };
200 0           $obj->{ connections }->{ $name }->{ -dbi }->disconnect();
201 0           undef $obj->{ connections }->{ $name }->{ -dbi };
202 0           undef $obj->{ connections }->{ $name }->{ -mempool };
203              
204 0           return 0;
205             }
206              
207             sub close_all {
208 0     0 0   my $obj = shift;
209 0           for my $name ( keys %{ $obj->{ connections } } ) {
  0            
210 0 0         if ( $obj->{ connections }->{ $name }->{ -logged } ) {
211 0           $obj->close( $name );
212 0           $obj->{ -interface }->print( "Disconnected from $name.\n" );
213              
214             # we can't move this message to extension - close_all called when
215             # destroying DBI object (handle event collapsed :(, no OUTPUT event exist)
216             }
217             }
218             }
219              
220             sub DESTROY {
221 0     0     my $obj = shift;
222 0           $obj->close_all;
223             }
224              
225             sub list {
226 0     0 0   my ( $obj, $what ) = @_;
227 0           my @returned = ();
228              
229 0           for my $name ( keys %{ $obj->{ connections } } ) {
  0            
230 0           my %r = %{ $obj->{ connections }->{ $name } };
  0            
231 0 0 0       next if ( $what eq 'inactive' and $r{ -logged } ) || ( $what eq 'active' and ! $r{ -logged } );
      0        
      0        
232 0           $r{ name } = $name;
233 0           push @returned, \%r;
234             }
235              
236 0           return [ sort { $a->{ name } cmp $b->{ name } } @returned ];
  0            
237             }
238              
239             sub autosql {
240 0     0 0   my $obj = shift;
241              
242 0 0         return -1 unless $obj->{ current };
243 0 0         return -2 unless exists $obj->{ connections }->{ $obj->{ current } };
244 0           return $obj->{ connections }->{ $obj->{ current } }->{ autosql };
245             }
246              
247             sub silent_autosql {
248 0     0 0   my $obj = shift;
249              
250 0 0         return -1 unless $obj->{ current };
251 0 0         return -2 unless exists $obj->{ connections }->{ $obj->{ current } };
252 0           return $obj->{ connections }->{ $obj->{ current } }->{ silent_autosql };
253             }
254              
255             sub set_current {
256 0     0 0   my ( $obj, $name ) = @_;
257              
258 0 0         return 9999 if $obj->{ current } eq $name;
259              
260 0 0         unless ( $name ) { delete $obj->{ current }; return 1; }
  0            
  0            
261              
262 0 0         return -1 unless exists $obj->{ connections }->{ $name };
263 0 0         return -2 unless $obj->{ connections }->{ $name }->{ -logged };
264              
265 0           $obj->{ current } = $name;
266 0           return 0;
267             }
268              
269             sub current {
270 0     0 0   my $obj = shift;
271 0           return $obj->{ current };
272             }
273              
274             sub drop_connection {
275 0     0 0   my ( $obj, $name ) = @_;
276 0 0         return -1 unless exists $obj->{ connections }->{ $name };
277 0 0         $obj->close( $name ) if $obj->{ connections }->{ $name }->{ -logged };
278 0           delete $obj->{ connections }->{ $name };
279 0           return 0;
280             }
281              
282             sub create_connection {
283 0     0 0   my ( $obj, $name, $p ) = @_;
284 0           my %parms = %$p;
285              
286 0 0         return -1 if exists $obj->{ connections }->{ $name };
287              
288 0           $obj->{ connections }->{ $name } = \%parms;
289 0 0         return 100 + $obj->open( $name ) if lc $parms{ auto_login } eq 'yes';
290 0           return 0;
291             }
292              
293             sub save_connection {
294 0     0 0   my $obj = shift;
295 0           my $name = shift;
296              
297 0 0         return -1 unless exists $obj->{ connections }->{ $name };
298              
299 0           my $cdir = $obj->connectiondir;
300 0 0         mkdir $cdir unless -d $cdir;
301 0 0         return -1 unless -d $cdir;
302 0           $cdir =~ s/\/$//;
303 0 0         CORE::open F, ">$cdir/$name" or return -2;
304 0           for ( qw/driver dsn login password auto_login config/ ) {
305             print F "$_ " . $obj->{ connections }->{ $name }->{ $_ } . "\n"
306             if exists $obj->{ connections }->{ $name }->{ $_ }
307 0 0 0       and $obj->{ connections }->{ $name }->{ $_ } ne '';
308             }
309 0           CORE::close F;
310 0           chmod 0600, "$cdir/$name";
311 0           return 0;
312             }
313              
314             sub destroy_connection {
315 0     0 0   my $obj = shift;
316 0           my $name = shift;
317              
318 0           my $cdir = $obj->connectiondir;
319 0 0         return -1 unless -d $cdir;
320 0           $cdir =~ s/\/$//;
321 0 0         return 1 unless -e "$cdir/$name";
322 0           unlink "$cdir/$name";
323 0 0         return -2 if -e "$cdir/$name";
324 0           return 0;
325             }
326              
327             sub is_permanent_connection {
328 0     0 0   my $obj = shift;
329 0           my $name = shift;
330 0           my $cdir = $obj->connectiondir;
331 0 0         return 0 unless -d $cdir;
332 0           $cdir =~ s/\/$//;
333 0           return -e "$cdir/$name";
334             }
335              
336             sub trans_begin {
337 0     0 0   my $obj = shift;
338 0 0         return -1 unless $obj->{ current };
339 0           $obj->{ connections }->{ $obj->{ current } }->{ -dbi }->{ AutoCommit } = 0;
340             }
341              
342             sub longreadlen {
343 0     0 0   my $obj = shift;
344 0           my $long = shift;
345 0 0         $obj->{ connections }->{ $obj->{ current } }->{ -dbi }->{ LongReadLen } = $long if $long;
346 0           return $obj->{ connections }->{ $obj->{ current } }->{ -dbi }->{ LongReadLen };
347             }
348              
349             sub trans_end {
350 0     0 0   my $obj = shift;
351 0 0         return -1 unless $obj->{ current };
352 0           $obj->{ connections }->{ $obj->{ current } }->{ -dbi }->{ AutoCommit } = 1;
353             }
354              
355             sub in_transaction {
356 0     0 0   my $obj = shift;
357 0 0         return 0 unless $obj->{ current };
358 0           return not $obj->{ connections }->{ $obj->{ current } }->{ -dbi }->{ AutoCommit };
359             }
360              
361             sub driver {
362 0     0 0   my $obj = shift;
363 0 0         return undef unless $obj->{ current };
364 0           return $obj->{ connections }->{ $obj->{ current } }->{ driver };
365             }
366              
367             sub login {
368 0     0 0   my $obj = shift;
369 0 0         return undef unless $obj->{ current };
370 0           return $obj->{ connections }->{ $obj->{ current } }->{ login };
371             }
372              
373             sub prompt_color {
374 0     0 0   my $obj = shift;
375 0 0         return undef unless $obj->{ current };
376 0           return $obj->{ connections }->{ $obj->{ current } }->{ prompt_color };
377             }
378              
379             sub AUTOLOAD {
380 0     0     my $obj = shift;
381              
382 0           $AUTOLOAD =~ s/^DBIx::dbMan::DBI:://g;
383 0 0         return undef unless $obj->{ current };
384 0 0         return undef unless exists $obj->{ connections }->{ $obj->{ current } };
385 0 0         return undef unless $obj->{ connections }->{ $obj->{ current } }->{ -logged };
386 0 0         return undef unless defined $obj->{ connections }->{ $obj->{ current } }->{ -dbi };
387              
388 0           my $dbi = $obj->{ connections }->{ $obj->{ current } }->{ -dbi };
389              
390 0           return $dbi->$AUTOLOAD( @_ );
391             }
392              
393             sub set {
394 0     0 0   my ( $obj, $var, $val ) = @_;
395 0 0         return unless $obj->{ current };
396              
397 0           $obj->{ connections }->{ $obj->{ current } }->{ -dbi }->{ $var } = $val;
398             }
399              
400             sub get {
401 0     0 0   my ( $obj, $var ) = @_;
402 0 0         return undef unless $obj->{ current };
403 0           return $obj->{ connections }->{ $obj->{ current } }->{ -dbi }->{ $var };
404             }
405              
406             sub discard_profile_data {
407 0     0 0   my $obj = shift;
408 0 0         return unless $obj->{ current };
409              
410             # $obj->{connections}->{$obj->{current}}->{-dbi}->{Profile}->{Data} = undef;
411             }
412              
413             sub mempool {
414 0     0 0   my $obj = shift;
415 0 0         return undef unless $obj->{ current };
416 0           return $obj->{ connections }->{ $obj->{ current } }->{ -mempool };
417             }