File Coverage

blib/lib/DBD/Log.pm
Criterion Covered Total %
statement 51 91 56.0
branch 6 26 23.0
condition 2 9 22.2
subroutine 12 17 70.5
pod 0 7 0.0
total 71 150 47.3


line stmt bran cond sub pod time code
1             package DBD::Log;
2              
3             # hartog/20041208 - 0.10 - created
4             # hartog/20050114 - 0.20 - made ready for release
5             # hartog/20050504 - 0.21 - tests added, packaged.
6             # hartog/20050524 - 0.22 - warnings prevented, loglines altered.
7              
8             BEGIN {
9 3     3   198900 $DBD::Log::VERSION = "0.22";
10             }
11              
12 3     3   32 use strict;
  3         6  
  3         121  
13 3     3   15 no strict 'refs';
  3         7  
  3         98  
14              
15 3     3   17 use Carp qw(croak);
  3         5  
  3         205  
16              
17 3     3   1915 use DBD::Log::Sth;
  3         8  
  3         137  
18             my %sthCache = ();
19              
20             use Class::AccessorMaker {
21 3         19 logThis => [],
22             logFH => "",
23              
24             dbiLogging => 0,
25              
26             dbi => "",
27 3     3   17 }, "new_init";
  3         6  
28              
29             sub init {
30 3     3 0 38165 my $self = shift;
31              
32 3         15 $self->logThis([ qw(insert update delete select create drop) ])
33 3 50       10 if !@{$self->logThis};
34              
35 3 50       99 if ( !$self->logFH ) {
36 0         0 croak("DBD::Log: Need an IO::File object to log into");
37             }
38             }
39              
40             sub logStatement {
41 0     0 0 0 my ( $self, $statement, @rest ) = @_;
42              
43             # all references are not to be logged.
44 0         0 @rest = grep { !ref($_) } @rest;
  0         0  
45              
46             # should we even log this?
47 0         0 my ($command) = lc($statement) =~ /^(\w+)/;
48 0 0 0     0 if ( $self->logThis->[0] ne "all"
  0         0  
49 0         0 && !grep { $_ eq $command } @{$self->logThis}
50             ) {
51 0         0 return undef;
52             }
53              
54 0 0       0 if ( my ( $fullSQL, @sqlRest ) = $self->composeStatement($statement, @rest) ) {
55 0         0 $self->printLog($fullSQL, @sqlRest);
56              
57             } else {
58             # we couldn't compile the statement.
59 0         0 $self->printLog('s', $statement, @rest);
60             }
61             }
62              
63             sub logAction {
64 4     4 0 10 my ( $function, $self, $statement, @rest ) = @_;
65              
66             # do we log DBI actions?
67 4 50       50 return undef if !$self->dbiLogging;
68              
69             # do we log this statement?
70 4         49 my ($command) = lc($statement) =~ /^(\w+)/;
71 4 50 33     15 if ( $self->logThis->[0] ne "all"
  24         75  
72 4         44 && !grep { $_ eq $command } @{$self->logThis}
73             ) {
74 0         0 return undef;
75             }
76              
77 4         21 $self->printLog("[$function]", $statement, @rest);
78             }
79              
80             sub composeStatement {
81 0     0 0 0 my ( $self, $statement, @rest ) = @_;
82              
83             # can we complete the statement with the values?
84 0 0       0 if ( my @parts = split(/\?/, $statement) ) {
    0          
85             # ? replacement.
86              
87 0         0 for ( 0..$#parts ) {
88             # add quotes if not fully numeric.
89 0 0       0 $rest[$_] = "'$rest[$_]'" if $rest[$_] =~ /\D+/;
90              
91             # insert the value into the statement.
92 0         0 $parts[$_] .= $rest[$_];
93             }
94              
95             # make completed SQL
96 0         0 $statement = join("", @parts);
97              
98             # if there is more to @rest then to @parts make sure to print it.
99 0         0 @rest = splice(@rest, $#parts+1, $#rest);
100              
101 0         0 return ( $statement, @rest );
102              
103             } elsif ( $statement =~ /\:\w+/ ) {
104             # oracle style replacement
105              
106             }
107              
108 0         0 return undef;
109             }
110              
111             sub printLog {
112 6     6 0 12 my ( $self, @components ) = @_;
113              
114             # print fast and add newlines.
115 6         24 local $\ = "\n";
116 6         38 local $| = 1;
117              
118 6         8 my $fh;
119 6 50       17 unless ( $fh = $self->logFH ) {
120 0         0 warn "No FH to log to! Using STDERR";
121 0         0 open($fh, ">&STDERR")
122             }
123              
124 10         19 print $fh join("\t", time, map {
125             # replace new-lines
126 6         59 s/[\r\n]+//g;
127             # replace tabs.
128 10         12 s/\t/ /g;
129              
130 10         103 $_
131             } @components);
132             }
133              
134             sub prepare {
135 4     4 0 111 my ( $self, $statement, @rest ) = @_;
136              
137             # prepare is somewhat special - we want to setup a fake $sth.
138              
139 4 50 33     29 my $action =
140             [caller(1)]->[3] && [caller(1)]->[3] =~ /prepare_cached/ ? "prepare_cached" : "prepare";
141              
142 4         17 logAction($action, @_);
143              
144 4         16 my $sth = DBD::Log::Sth->new( dbi => $self->dbi,
145             logFH => $self->logFH,
146             logThis => $self->logThis,
147             dbiLogging => $self->dbiLogging,
148             statement => $statement,
149             rest => [ @rest ],
150             );
151              
152 4         686 return $sth;
153             }
154              
155              
156             sub prepare_cached {
157 0     0 0 0 my ( $self, $statement, @rest ) = @_;
158 0         0 my $KEY = $statement . $rest[0];
159              
160             # let's try to do this caching stuff our selves.
161              
162             # prevent warnings.
163 0 0       0 exists $sthCache{$self} || ( $sthCache{$self} = {} );
164              
165             # return cached STH
166 0 0       0 exists $sthCache{$self}->{$KEY} && return $sthCache{$self}->{$KEY};
167              
168 0         0 my $sth = $self->prepare($statement, @rest);
169 0         0 $sthCache{$self}->{$KEY} = $sth;
170              
171 0         0 return $sth;
172             }
173              
174             # define the actions that need to be logged.
175             foreach my $sub ( qw( do selectall_arrayref selectcol_arrayref
176             selectrow_array selectrow_arrayref
177             selectrow_hashref )
178             ) {
179              
180             *{"DBD::Log::$sub"} = sub {
181 0     0   0 my ( $self, $statement, @rest ) = @_;
182              
183 0         0 logAction($sub, @_);
184 0         0 $self->logStatement($statement, @rest);
185              
186 0         0 return $self->dbi->$sub($statement, @rest);
187             }
188              
189             }
190              
191             sub DESTROY {
192 3     3   3167 my $self = shift;
193              
194             # make all cached sth's done.
195 3         8 foreach ( keys %{$sthCache{$self}} ) {
  3         24  
196 0         0 $sthCache{$self}->{$_}->destroy;
197 0         0 $sthCache{$self}->{$_}->DESTROY;
198             }
199              
200             # clear the cache.
201 3         11 %sthCache = ();
202              
203 3         18 $self->dbi->disconnect;
204 3         57 $self->dbi({});
205              
206 3         417 $self = undef;
207             }
208              
209             sub AUTOLOAD {
210              
211             # any of the DBI routines we missed, or want not logged, are
212             # autoloaded.
213              
214 3     3   7156 no strict;
  3         7  
  3         349  
215              
216 0     0     my ($routine) = $AUTOLOAD =~ /\:\:(\w+)$/;
217 0           my ( $self, @rest ) = @_;
218              
219 0           return $self->dbi->$routine(@rest);
220             }
221              
222             1;
223              
224             __END__