File Coverage

blib/lib/Test/MockDBI/St.pm
Criterion Covered Total %
statement 161 174 92.5
branch 84 96 87.5
condition 17 24 70.8
subroutine 17 17 100.0
pod n/a
total 279 311 89.7


line stmt bran cond sub pod time code
1             package Test::MockDBI::St;
2              
3 50     50   275 use strict;
  50         85  
  50         1766  
4 50     50   253 use warnings;
  50         86  
  50         1634  
5 50     50   25232 use Test::MockDBI::Constants;
  50         127  
  50         20989  
6 50     50   305 use Test::MockDBI::Db;
  50         518  
  50         373  
7 50     50   319 use Test::MockDBI::Base;
  50         77  
  50         1254  
8              
9 50     50   240 use base qw(Test::MockDBI::Base);
  50         79  
  50         112185  
10              
11             my $mockdbi = undef;
12              
13 51     51   572 sub import{ $mockdbi = $_[1]; }
14              
15              
16             sub _dbi_bind_param{
17 28     28   3764 my ($self, $p_num, $bind_value, $attr) = @_;
18            
19             #Clearing the dbi err/errstr
20 28         276 $mockdbi->_clear_dbi_err_errstr($self);
21            
22 28         108 my ($status, $retval) = $mockdbi->_has_fake_retval($self->{Statement});
23 28 100       85 if($status){
24 5         23 $mockdbi->_set_fake_dbi_err_errstr($self);
25            
26 5 100       30 if(ref($retval) eq 'CODE'){
27 1         5 return $retval->($self);
28             }
29            
30 4         23 return $retval;
31             }
32 23 100       139 return if($mockdbi->_is_bad_bind_param($self->{Statement}, $bind_value));
33            
34             #Check that the $p_num is a valid number
35 18 50       120 if($p_num !~ m/^\d+$/){
36 0         0 $mockdbi->_set_dbi_err_errstr($self, err => 16, errstr => 'Illegal parameter number');
37 0         0 return;
38             }
39 18 100 100     698 if($p_num < 1 || $p_num > $self->{NUM_OF_PARAMS}){
40 2         9 $mockdbi->_set_dbi_err_errstr($self, err => 16, errstr => 'Illegal parameter number');
41 2         11 return;
42             }
43            
44             #Verify that the bind_param attribute is a valid one
45              
46            
47             #Rewrite this to resemble the DBI behaviour
48 16 100 100     99 if($attr && $attr =~ m/^\d+$/){
    100          
49 1         7 $self->{ParamTypes}->{$p_num} = { TYPE => $attr};
50             }elsif($attr){
51             #Assume its a hash
52             #Throw a warning as DBI does
53 1 50       8 if( $attr->{TYPE} !~ m/^\d+$/){
54 0         0 my @caller = caller(1);
55 0         0 warn 'Argument "' . $attr->{TYPE} .'" isn\'t numeric in subroutine entry at ' . $caller[1] . ' line ' . $caller[2] . '.' . "\n";
56             }else{
57 1         5 $self->{ParamTypes}->{$p_num} = $attr;
58             }
59            
60             }else{
61 14         79 $self->{ParamTypes}->{$p_num} = { TYPE => SQL_VARCHAR };
62             }
63            
64 16         218 $self->{ParamValues}->{$p_num} = $bind_value;
65            
66 16         168 return 1;
67             }
68              
69             sub _dbi_bind_param_inout{
70 12     12   65 my($self, $p_num, $bind_value, $max_length, $attr) = @_;
71            
72 12         40 $mockdbi->_clear_dbi_err_errstr($self);
73            
74 12         42 my ($status, $retval) = $mockdbi->_has_fake_retval($self->{Statement});
75 12 100       34 if($status){
76 3         11 $mockdbi->_set_fake_dbi_err_errstr($self);
77            
78 3 100       13 if( ref($retval) eq 'CODE'){
79 1         5 return $retval->($self);
80             }
81            
82 2         8 return $retval;
83             }
84 9 50       31 return if($mockdbi->_is_bad_bind_param($self->{Statement}, $bind_value));
85            
86 9 100 66     80 if(!$self || !$p_num || !$bind_value || $max_length ){
      66        
87             #DBI just dies if it has to few parameters
88 1         10 die('DBI bind_param_inout: invalid number of arguments: got handle + 2, expected handle + between 3 and 4
89             Usage: $h->bind_param_inout($parameter, \$var, $maxlen, [, \%attr])');
90             }
91              
92             #Check that the $p_num is a valid number
93 8 100       41 if($p_num !~ m/^\d+$/){
94 1         6 $mockdbi->_set_dbi_err_errstr($self, err => 16, errstr => 'Illegal parameter number');
95 1         6 return;
96             }
97 7 100 66     40 if($p_num < 1 || $p_num > $self->{NUM_OF_PARAMS}){
98 1         11 $mockdbi->_set_dbi_err_errstr($self, err => 16, errstr => 'Illegal parameter number');
99 1         5 return;
100             }
101            
102             #Verify that the bind_param attribute is a valid one
103 6 50 33     22 if($attr && $attr =~ m/^\d+$/){
    50          
104 0         0 $self->{ParamTypes}->{$p_num} = { TYPE => $attr};
105             }elsif($attr){
106             #Assume its a hash
107             #Throw a warning as DBI does
108 0 0       0 if( $attr->{TYPE} !~ m/^\d+$/){
109 0         0 my @caller = caller(1);
110 0         0 warn 'Argument "' . $attr->{TYPE} .'" isn\'t numeric in subroutine entry at ' . $caller[1] . ' line ' . $caller[2] . '.' . "\n";
111             }else{
112 0         0 $self->{ParamTypes}->{$p_num} = $attr;
113             }
114            
115             }else{
116 6         21 $self->{ParamTypes}->{$p_num} = { TYPE => SQL_VARCHAR };
117             }
118            
119 6 100       20 if ( ref($bind_value) ne 'SCALAR' ) {
120             #DBI just dies if $bind_value is not a SCALAR reference
121 1         10 die('bind_param_inout needs a reference to a scalar value');
122 0         0 return;
123             }
124            
125 5         16 $self->{ParamValues}->{$p_num} = $bind_value;
126            
127 5         6 push( @{ $self->{_fake}->{InoutParams} }, $p_num );
  5         17  
128            
129 5         18 return 1;
130             }
131              
132             sub _dbi_execute{
133 57     57   1958 my ($self, @bind_values) = @_;
134            
135 57         214 $mockdbi->_clear_dbi_err_errstr($self);
136            
137 57         270 my ($status, $retval) = $mockdbi->_has_fake_retval($self->{Statement});
138 57 100       196 if($status){
139 5         17 $mockdbi->_set_fake_dbi_err_errstr($self);
140            
141 5 100       20 if(ref($retval) eq 'CODE'){
142 1         4 return $retval->($self);
143             }
144 4         37 return $retval;
145             }
146            
147             #Copied from the DBI documentation:
148             # Active
149             # Type: boolean, read-only
150             # The Active attribute is true if the handle object is "active". This is rarely used in applications.
151             # The exact meaning of active is somewhat vague at the moment.
152             # For a database handle it typically means that the handle is connected to a database ($dbh->disconnect sets Active off).
153             # For a statement handle it typically means that the handle is a SELECT that may have more data to fetch.
154             # (Fetching all the data or calling $sth->finish sets Active off.)
155             #
156             # Due to the vague definition of the Active attribute i have taken the freedom to interpeter the attribute in the following way:
157             # - The Active attribute is set to true on a statementhandler when the execute method is called on an already prepared select statement
158             # - The Active attribute is set to false either if finish is called on the statementhandler or disconnect is called on the dbh
159             #
160            
161             #Updating attributes
162 52 100       272 $self->{Active} = 1 if $self->{Statement} =~ m/^select/i;
163 52         99 $self->{Executed} = 1;
164             #Update the parent activekids flag
165 52         179 Test::MockDBI::Db::_update_active_kids($self->{Database});
166            
167 52 100 66     311 if(ref($self->{_fake}->{InoutParams}) eq 'ARRAY' && scalar( @{ $self->{_fake}->{InoutParams} } ) > 0 ){
  52         308  
168 2         3 foreach my $p_num ( @{ $self->{_fake}->{InoutParams} } ){
  2         5  
169 3         12 my ($status, $retval) = $mockdbi->_has_inout_value($self->{Statement}, $p_num);
170 3 50       9 ${ $self->{ParamValues}->{$p_num} } = $retval if $status;
  3         11  
171             }
172            
173             }
174              
175             #Not enough parameters bound
176 52 100       108 if( $self->{NUM_OF_PARAMS} != scalar(keys %{ $self->{ParamValues} })){
  52         271  
177 3         22 return '0E0';
178             }
179            
180             #Number of affected rows is not known
181 49         136 return -1;
182             }
183              
184             sub _dbi_fetchrow_arrayref{
185 59     59   1133 my ($self) = @_;
186            
187 59         171 $mockdbi->_clear_dbi_err_errstr($self);
188            
189             #return if we are not executed
190 59 100       195 return if( !$self->{Executed} );
191            
192 44         143 my ($status, $retval) = $mockdbi->_has_fake_retval($self->{Statement});
193 44 100       163 if($status){
194 31         120 $mockdbi->_set_fake_dbi_err_errstr($self);
195            
196 31 100       292 if(ref($retval) eq 'CODE'){
197 6         22 my @caller = caller(1);
198 6 100 66     83 if($caller[3] && $caller[3] =~ m/fetchrow_array$/){
199 3         11 return $retval;
200             }
201 3         12 return $retval->($self);
202             }
203             }
204            
205             #The resultset should be an array of hashes
206 38 100       105 if(ref($retval) ne 'ARRAY'){
207             #Should implement support for RaiseError and PrintError
208 17         57 return;
209             }
210            
211 21 100       24 if(scalar( @{$retval} ) > 0){
  21         63  
212 18         22 my $row = shift @{ $retval };
  18         48  
213 18 50       52 if(ref($row) ne 'ARRAY'){
214             #Should implement support for RaiseError and PrintError
215 0         0 return;
216             }
217 18         62 return $row;
218             }
219             #fetchrow_arrayref returns undef if no more rows are available, or an error has occured
220 3         7 return;
221             }
222              
223             sub _dbi_fetch{
224 4     4   24 return $_[0]->fetchrow_arrayref();
225             }
226              
227             sub _dbi_fetchrow_array{
228 20     20   1005 my ($self) = @_;
229 20         67 my $row = $self->fetchrow_arrayref();
230 20 100       127 return if !$row;
231 7 100       28 return @{$row} if ref($row) eq 'ARRAY';
  4         29  
232 3 50       18 return $row->($self) if ref($row) eq 'CODE';
233 0         0 return $row;
234             }
235              
236             sub _dbi_fetchrow_hashref{
237 24     24   6700 my ($self) = @_;
238            
239 24         70 $mockdbi->_clear_dbi_err_errstr($self);
240            
241             #return if we are not executed
242 24 50       63 return if( !$self->{Executed} );
243            
244 24         93 my ($status, $retval) = $mockdbi->_has_fake_retval($self->{Statement});
245 24 100       63 if($status){
246 23         81 $mockdbi->_set_fake_dbi_err_errstr($self);
247            
248 23 100       79 if(ref($retval) eq 'CODE'){
249 8         23 return $retval->($self);
250             }
251             }
252            
253             #The resultset should be an array of hashes
254 16 100       37 if(ref($retval) ne 'ARRAY'){
255             #Should implement support for RaiseError and PrintError
256 3         7 return;
257             }
258            
259 13 100       15 if(scalar( @{$retval} ) > 0){
  13         31  
260 10         9 my $row = shift @{ $retval };
  10         18  
261 10 50       26 if(ref($row) ne 'HASH'){
262             #Should implement support for RaiseError and PrintError
263 0         0 return;
264             }
265 10         22 return $row;
266             }
267              
268             #fetchrow_hashref returns undef if no more rows are available, or an error has occured
269 3         5 return;
270             }
271              
272             sub _dbi_fetchall_arrayref{
273 11     11   971 my ($self) = @_;
274            
275 11         39 $mockdbi->_clear_dbi_err_errstr($self);
276            
277             #return if we are not executed
278 11 100       66 return if( !$self->{Executed} );
279            
280 7         28 my ($status, $retval) = $mockdbi->_has_fake_retval($self->{Statement});
281 7 100       22 if($status){
282 5         126 $mockdbi->_set_fake_dbi_err_errstr($self);
283            
284 5 100       21 if(ref($retval) eq 'CODE'){
285 1         3 return $retval->($self);
286             }
287             }
288              
289             #The resultset should be an array of hashes
290 6 100       26 if(ref($retval) ne 'ARRAY'){
291             #Should implement support for RaiseError and PrintError
292 4         12 return;
293             }
294            
295 2         6 return $retval;
296             }
297              
298              
299             sub _dbi_finish{
300 50     50   24414 my ($self) = @_;
301            
302 50         195 $mockdbi->_clear_dbi_err_errstr($self);
303            
304 50         204 my ($status, $retval) = $mockdbi->_has_fake_retval($self->{Statement});
305 50 100       162 if($status){
306 5         22 $mockdbi->_set_fake_dbi_err_errstr($self);
307            
308 5 100       21 if(ref($retval) eq 'CODE'){
309 1         4 return $retval->($self);
310             }
311 4         20 return $retval;
312             }
313            
314 45         91 $self->{Active} = undef;
315             #Update the parent activekids flag
316 45         178 Test::MockDBI::Db::_update_active_kids($self->{Database});
317            
318 45         1689 return 1;
319             }
320              
321             sub _dbi_rows{
322 12     12   1532 my ($self) = @_;
323            
324 12         50 $mockdbi->_clear_dbi_err_errstr($self);
325            
326 12         56 my ($status, $retval) = $mockdbi->_has_fake_retval($self->{Statement});
327 12 100       50 if($status){
328 10         135 $mockdbi->_set_fake_dbi_err_errstr($self);
329            
330 10 100       42 if(ref($retval) eq 'CODE'){
331 2         7 return $retval->($self);
332             }
333 8         48 return $retval;
334             }
335            
336 2         17 return -1;
337             }
338             1;