File Coverage

blib/lib/DBIx/PDlib.pm
Criterion Covered Total %
statement 15 176 8.5
branch 0 118 0.0
condition 0 53 0.0
subroutine 5 19 26.3
pod 11 12 91.6
total 31 378 8.2


line stmt bran cond sub pod time code
1             package DBIx::PDlib;
2              
3 1     1   3862 use 5.00503;
  1         3  
  1         41  
4 1     1   5 use strict;
  1         1  
  1         34  
5 1     1   2422 use DBI;
  1         20992  
  1         83  
6 1     1   12 use Carp;
  1         2  
  1         78  
7              
8             require Exporter;
9 1     1   5 use vars qw($VERSION);
  1         2  
  1         2688  
10              
11             $VERSION = sprintf "%d.%03d", q$Revision: 1.9 $ =~ /(\d+)/g;
12             # $Date: 2004/03/15 13:46:14 $
13             # $Author: sjackson $
14              
15             #############################################
16             # perl module to make sql operations easier #
17             #############################################
18              
19             sub connect
20             {
21             # options are exactly the same as DBI's
22 0     0 1   my ($this) = shift;
23 0   0       my $class = ref($this) || $this;
24              
25             # the connect code was borrowed heavily from DBIx::Abstract
26 0           my($dbh,$data_source,$user,$pass);
27 0           my $self = {};
28 0           my ($config,$options) = @_;
29              
30 0 0         if (!defined($config))
    0          
    0          
    0          
31             {
32 0           croak "DBIx::PDlib->connect A connection configuration must be provided.";
33             } elsif (ref($config) eq 'HASH') {
34 0 0         if ($$config{'dbh'})
35             { # they provided the dbh connect string
36 0           $dbh = $$config{'dbh'};
37             } else {
38 0   0       $user = $$config{'user'} || $$config{'username'};
39 0   0       $pass = $$config{'password'} || $$config{'pass'};
40 0 0 0       if (!defined($$config{'user'}) && $$config{'password'}) {
41 0           $$config{'password'} = undef;
42             }
43 0 0         if (exists($$config{'dsn'})) {
44 0           $data_source = $$config{'dsn'};
45             } else {
46 0   0       $$config{'driver'} ||= 'mysql'; # cause it's what I use
47 0   0       $$config{'dbname'} ||= $$config{'db'} || '';
      0        
48 0   0       $$config{'host'} ||= '';
49 0   0       $$config{'port'} ||= '';
50 0           $data_source = ___drivers($$config{'driver'},$config);
51             }
52             }
53             } elsif (UNIVERSAL::isa($config,'DBI::db')) {
54 0           $dbh = $config;
55             } elsif (ref($config)) {
56 0           croak "DBIx::PDlib->connect Config must be a hashref or a DBI object, not ".ref($config)."ref\n";
57             } else {
58 0           croak "DBIx::PDlib->connect Config must be a hashref or a DBI object, not a scalar.\n";
59             }
60              
61 0 0         if ($data_source)
    0          
62             {
63 0           $dbh = DBI->connect($data_source,$user,$pass);
64             } elsif (! $dbh) {
65 0           croak "Could not understand data source.\n";
66             }
67              
68 0 0         if (! $dbh) { return 0; }
  0            
69              
70 0           bless( $self, $class );
71              
72 0 0 0       if (ref($config) eq 'HASH' and !$$config{'dbh'})
73             {
74 0           $self->{'_dbh_args'} = {
75             driver => $$config{'driver'},
76             dbname => $$config{'dbname'},
77             host => $$config{'host'},
78             port => $$config{'port'},
79             user => $user,
80             password => $pass,
81             data_source => $data_source,
82             };
83             } else {
84 0           $self->{'_dbh_args'} = { dbh => 1 };
85             }
86 0           $self->{'_dbh'} = $dbh;
87              
88 0           return $self;
89             }
90              
91             sub ___drivers
92             {
93 0     0     my ($driver,$config) = @_;
94 0           my %drivers = (
95             # Feel free to add new drivers... note that some DBD data_sources
96             # do not translate well (eg Oracle).
97             mysql => "dbi:mysql:$$config{dbname}:$$config{host}:$$config{port}",
98             msql => "dbi:msql:$$config{dbname}:$$config{host}:$$config{port}",
99             Pg => "dbi:Pg:$$config{dbname}:$$config{host}:$$config{port}",
100             # According to DBI, drivers should use the below if they have no
101             # other preference. It is ODBC style.
102             DEFAULT => "dbi:$driver:"
103             );
104              
105             # Make Oracle look a little bit like other DBs.
106             # Right now we only have one hack, but I can imagine there being
107             # more...
108 0 0         if ($driver eq 'Oracle') {
109 0   0       $$config{'sid'} ||= delete($$config{'dbname'});
110 0 0         $ENV{ORACLE_HOME} = $$config{'home'} unless (-d $ENV{ORACLE_HOME});
111             }
112              
113 0           my @keys;
114 0           foreach (keys(%$config)) {
115 0 0         next if /^user$/;
116 0 0         next if /^password$/;
117 0 0         next if /^driver$/;
118 0           push(@keys,"$_=$$config{$_}");
119             }
120 0           $drivers{'DEFAULT'} .= join(';',@keys);
121 0 0         if ($drivers{$driver}) {
122 0           return $drivers{$driver};
123             } else {
124 0           return $drivers{'DEFAULT'};
125             }
126             }
127              
128             sub raw_query
129             {
130             #######################################################
131             #######################################################
132             ##
133             ## This will allow you to send any raw SQL to the $dbh
134             ## handle. Mainly useful for CREATE and DROP type statements
135             ##
136              
137 0 0   0 1   ref(my $self = shift) or croak "instance variable needed";
138              
139 0           my $query = shift;
140              
141             # make sure connection is still up
142 0           $self->_check_active_connection();
143              
144 0           my $return_value = $self->{_dbh}->do($query);
145 0 0         return defined(wantarray()) ? ($return_value) : "";
146             }
147              
148             sub iterated_select
149             {
150             #######################################################
151             #######################################################
152             ##
153             ## This will allow you to select a lot of stuff at once
154             ## usage should be self explanitory i hope =]
155             ##
156              
157 0 0   0 1   ref(my $self = shift) or croak "instance variable needed";
158              
159 0           my($select, $from, $where, $other) = @_;
160              
161             # make sure connection is still up
162 0           $self->_check_active_connection();
163              
164 0           my $query = "SELECT $select ";
165 0 0         $query .= " FROM $from " if $from;
166 0 0         $query .= " WHERE $where " if $where;
167 0 0         $query .= " $other" if $other;
168              
169 0           my $handle = $self->{_dbh}->prepare($query);
170              
171             # If we can execute a statement then do it and send back the handle
172              
173 0 0         return $handle if ($handle->execute);
174            
175             # else we can finish things up and close the dbh
176 0           my ($pkg,$file,$line) = caller;
177 0           carp "Unable to execute handle at line $line in file $file package $pkg\n";
178 0           $handle->finish;
179 0           return;
180             }
181              
182              
183             sub select_hashref
184             {
185             ####################################################
186             ####################################################
187             ##
188             ## Useful SQL Select wrapper to cut down on code
189             ## in our friendly main scripts
190              
191 0 0   0 0   ref(my $self = shift) or croak "instance variable needed";
192              
193 0           my($select, $from, $where, $other) = @_;
194              
195             # make sure connection is still up
196 0           $self->_check_active_connection();
197              
198 0           my $query = "SELECT $select ";
199 0 0         $query .= "FROM $from " if $from;
200 0 0         $query .= "WHERE $where " if $where;
201 0 0         $query .= "$other" if $other;
202            
203 0           my $handle = $self->{_dbh}->prepare($query);
204              
205 0 0         unless ($handle->execute)
206             {
207 0           my ($pkg,$file,$line) = caller;
208 0           carp "Unable to execute handle at line $line in file $file package $pkg\n";
209 0           return;
210             }
211 0           my $hashref = $handle->fetchrow_hashref;
212 0           $handle->finish;
213              
214 0           return $hashref;
215             }
216              
217             sub select
218             {
219            
220             ####################################################
221             ####################################################
222             ##
223             ## Useful SQL Select wrapper to cut down on code
224             ## in our friendly main scripts
225              
226 0 0   0 1   ref(my $self = shift) or croak "instance variable needed";
227              
228 0           my($select, $from, $where, $other) = @_;
229              
230             # make sure connection is still up
231 0           $self->_check_active_connection();
232              
233 0           my $query = "SELECT $select ";
234 0 0         $query .= "FROM $from " if $from;
235 0 0         $query .= "WHERE $where " if $where;
236 0 0         $query .= "$other" if $other;
237            
238 0           my $handle = $self->{_dbh}->prepare($query);
239              
240 0 0         unless ($handle->execute)
241             {
242 0           my ($pkg,$file,$line) = caller;
243 0           carp "Unable to execute handle at line $line in file $file package $pkg\n";
244 0           return;
245             }
246 0           my @array = $handle->fetchrow_array;
247 0           $handle->finish;
248              
249             # return entire array if they're asking for an array,
250             # otherwise return the first element
251 0 0         return wantarray ? @array : $array[0];
252             }
253              
254             sub select_all
255             {
256            
257             ####################################################
258             ####################################################
259             ##
260             ## Useful SQL Select wrapper to cut down on code
261             ## in our friendly main scripts
262             ##
263             ## returns an array referance of all rows returns, containing
264             ## an array referance of columns returned for each row
265            
266 0 0   0 1   ref(my $self = shift) or croak "instance variable needed";
267              
268 0           my($select, $from, $where, $other) = @_;
269              
270             # make sure connection is still up
271 0           $self->_check_active_connection();
272              
273 0           my $query = "SELECT $select ";
274 0 0         $query .= "FROM $from " if $from;
275 0 0         $query .= "WHERE $where " if $where;
276 0 0         $query .= "$other" if $other;
277            
278 0           my $alldata = $self->{_dbh}->selectall_arrayref($query);
279 0 0         if ($alldata)
280             {
281 0           return $alldata
282             } else {
283 0           my ($pkg,$file,$line) = caller;
284 0           carp "Unable to execute handle at line $line in file $file package $pkg\n";
285 0           return; # if there was an error, return nothing
286             }
287             }
288              
289             sub insert
290             {
291 0     0 1   my ($pkg,$file,$line) = caller;
292             ####################################################
293             ####################################################
294             ##
295             ## Useful SQL Insert wrapper to cut down on code
296             ## in our friendly main scripts
297             ##
298             ## Usage: insert($tablename,$fields_array_ref,$values_array_ref);
299              
300 0 0         ref(my $self = shift) or croak "instance variable needed";
301              
302 0           my($table, $fields, $values) = @_;
303              
304             # make sure connection is still up
305 0           $self->_check_active_connection();
306              
307 0 0 0       return unless ($table &&
      0        
      0        
308             (ref $fields eq "ARRAY") &&
309             (ref $values eq "ARRAY") &&
310             (@$fields == @$values)
311             );
312              
313 0           my $f_list = join(', ',@$fields);
314 0           my $v_list = join(',', map { "?" } @$values );
  0            
315 0           my $handle = $self->{_dbh}->prepare("INSERT INTO $table ($f_list) VALUES ($v_list)");
316 0 0         if ($handle->execute(@$values))
317             { # will auto-quote stuff this way. pass 'undef' for NULL values
318 0           $handle->finish;
319             # return 1 (success) if they want a return value, or just return.
320 0 0         return defined(wantarray()) ? (1) : "";
321             } else {
322             # couldn't execute it.
323 0           carp "Unable to execute insert handle at line $line in file $file package $pkg\n";
324 0           return;
325             }
326             }
327              
328             sub update
329             {
330 0     0 1   my ($pkg,$file,$line) = caller;
331              
332             ####################################################
333             ####################################################
334             ##
335             ## Useful SQL Update wrapper to cut down on code
336             ## in our friendly main scripts
337             ##
338             ## Usage: update($tablename,$fields_array_ref,$values_array_ref,$where_statement);
339              
340 0 0         ref(my $self = shift) or croak "instance variable needed";
341              
342 0           my($table, $fields, $values, $where) = @_;
343              
344             # make sure connection is still up
345 0           $self->_check_active_connection();
346              
347             # they must give us everything. UPDATE's without $where are valid SQL, but
348             # I see no reason we should have them called from any script using this
349             # sql wrapper. So we make sure they give us some where statement,
350             # and they can pass "$where=1" if they really know what they're doing.
351 0 0 0       return unless ($table &&
      0        
      0        
      0        
352             (ref($fields) eq "ARRAY") &&
353             (ref($values) eq "ARRAY") &&
354             (@$fields == @$values) &&
355             $where
356             );
357 0           my $query = "UPDATE $table SET " .
358 0           join(',', map { " $_ = ?" } @$fields ) .
359             " WHERE $where";
360              
361 0           my $handle = $self->{_dbh}->prepare($query);
362 0 0         if ($handle->execute(@$values))
363             { # will auto-quote stuff this way.
364 0           $handle->finish;
365             # return 1 (success) if they want a return value, or just return.
366 0 0         return defined(wantarray()) ? (1) : "";
367             } else {
368             # couldn't execute it.
369 0           carp "Unable to execute update handle at line $line in file $file package $pkg\n";
370 0           return;
371             }
372             }
373              
374             sub delete
375             {
376             ####################################################
377             ####################################################
378             ##
379             ## Useful delete wrapper to cut down on code
380             ## in our friendly main scripts
381              
382 0 0   0 1   ref(my $self = shift) or croak "instance variable needed";
383              
384 0           my($table,$where) = @_;
385              
386             # make sure connection is still up
387 0           $self->_check_active_connection();
388              
389 0 0 0       if ($table && $where)
390             {
391 0           my $return_value = $self->{_dbh}->do("DELETE FROM $table WHERE $where");
392             # return $return_value if they want a return value, or just return.
393 0 0         return defined(wantarray()) ? ($return_value) : "";
394             } else {
395 0           return;
396             }
397             }
398              
399             sub quote
400             {
401             ## THIS SHOULDN'T BE NEEDED EXCEPT A FEW CASES (where statements)
402             ## MOST FUNCTIONS NEEDING QUOTING (inserts, updates)
403             ## WILL DO QUOTING THEMSELVES
404              
405             ####################################################
406             ####################################################
407             ##
408             ## Useful for quoting text fields, since we don't
409             ## actually connect to DBI in the main scripts anymore
410             ## it's needed
411             ##
412             ## Usage:
413             ## my @newvalues = quote(@values);
414             ## my $firstquotedvalue = $newvalues[0];
415             ## foreach (@newvalues) {
416             ## # do something
417             ## }
418              
419 0 0   0 1   ref(my $self = shift) or croak "instance variable needed";
420              
421             # make sure connection is still up
422 0           $self->_check_active_connection();
423              
424 0           my(@toreturn);
425 0           foreach my $toquote (@_)
426             {
427 0           my $temp = $self->{_dbh}->quote($toquote);
428 0           push(@toreturn,$temp);
429             }
430             # return entire array if they're asking for an array,
431             # otherwise return the first element
432 0 0         return wantarray ? @toreturn : $toreturn[0];
433             }
434              
435             sub disconnect
436             {
437 0 0   0 1   ref(my $self = shift) or croak "instance variable needed";
438 0           $self->{_dbh}->disconnect();
439             }
440              
441             sub connected
442             {
443 0 0   0 1   ref(my $self = shift) or croak "instance variable needed";
444 0           my $rc = $self->{_dbh}->ping;
445 0 0         return 1 if $rc;
446             }
447              
448             sub _check_active_connection
449             {
450 0 0   0     ref(my $self = shift) or croak "instance variable needed";
451              
452 0 0         unless ($self->connected())
453             { # we're not connected anymore, something died.
454 0 0         if ($self->{_dbh_args}{data_source})
455             { # we can't do a reconnect if they passed in an active handle
456 0           my $dbh = DBI->connect(
457             $self->{_dbh_args}{datasource},
458             $self->{_dbh_args}{user},
459             $self->{_dbh_args}{password} );
460 0           $self->{_dbh} = $dbh;
461             }
462             }
463             # we could loop until ok, or return some error code if we're still
464             # not connected, but I'm just hoping this fixes things. We've been getting:
465             #DBD::mysql::st execute failed: MySQL server has gone away at /usr/local/apache/public-dns.purifieddata.net/lib/PDlib_dns.pm line 64.
466             #Unable to execute handle at line 87 in file /usr/local/apache/public-dns.purifieddata.net/lib/utils_dns.pm package utils_dns
467             #[Tue Aug 19 22:20:07 2003] [error] Can't call method "fetchrow_array" on an undefined value at /usr/local/apache/public-dns.purifieddata.net/lib/utils_dns.pm line 88.
468             }
469              
470              
471             1;
472              
473             __END__