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   168 use strict;
  50         55  
  50         1179  
4 50     50   162 use warnings;
  50         794  
  50         1271  
5 50     50   13604 use Test::MockDBI::Constants;
  50         78  
  50         8892  
6 50     50   219 use Test::MockDBI::Db;
  50         49  
  50         247  
7 50     50   153 use Test::MockDBI::Base;
  50         54  
  50         956  
8              
9 50     50   146 use base qw(Test::MockDBI::Base);
  50         46  
  50         68710  
10              
11             my $mockdbi = undef;
12              
13 51     51   363 sub import{ $mockdbi = $_[1]; }
14              
15              
16             sub _dbi_bind_param{
17 28     28   2115 my ($self, $p_num, $bind_value, $attr) = @_;
18            
19             #Clearing the dbi err/errstr
20 28         75 $mockdbi->_clear_dbi_err_errstr($self);
21            
22 28         71 my ($status, $retval) = $mockdbi->_has_fake_retval($self->{Statement});
23 28 100       52 if($status){
24 5         15 $mockdbi->_set_fake_dbi_err_errstr($self);
25            
26 5 100       22 if(ref($retval) eq 'CODE'){
27 1         6 return $retval->($self);
28             }
29            
30 4         15 return $retval;
31             }
32 23 100       70 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       72 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     99 if($p_num < 1 || $p_num > $self->{NUM_OF_PARAMS}){
40 2         6 $mockdbi->_set_dbi_err_errstr($self, err => 16, errstr => 'Illegal parameter number');
41 2         6 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     117 if($attr && $attr =~ m/^\d+$/){
    100          
49 1         3 $self->{ParamTypes}->{$p_num} = { TYPE => $attr};
50             }elsif($attr){
51             #Assume its a hash
52             #Throw a warning as DBI does
53 1 50       4 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         2 $self->{ParamTypes}->{$p_num} = $attr;
58             }
59            
60             }else{
61 14         42 $self->{ParamTypes}->{$p_num} = { TYPE => SQL_VARCHAR };
62             }
63            
64 16         68 $self->{ParamValues}->{$p_num} = $bind_value;
65            
66 16         173 return 1;
67             }
68              
69             sub _dbi_bind_param_inout{
70 12     12   52 my($self, $p_num, $bind_value, $max_length, $attr) = @_;
71            
72 12         28 $mockdbi->_clear_dbi_err_errstr($self);
73            
74 12         29 my ($status, $retval) = $mockdbi->_has_fake_retval($self->{Statement});
75 12 100       22 if($status){
76 3         8 $mockdbi->_set_fake_dbi_err_errstr($self);
77            
78 3 100       12 if( ref($retval) eq 'CODE'){
79 1         4 return $retval->($self);
80             }
81            
82 2         4 return $retval;
83             }
84 9 50       23 return if($mockdbi->_is_bad_bind_param($self->{Statement}, $bind_value));
85            
86 9 100 66     62 if(!$self || !$p_num || !$bind_value || $max_length ){
      66        
87             #DBI just dies if it has to few parameters
88 1         8 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       30 if($p_num !~ m/^\d+$/){
94 1         5 $mockdbi->_set_dbi_err_errstr($self, err => 16, errstr => 'Illegal parameter number');
95 1         3 return;
96             }
97 7 100 66     28 if($p_num < 1 || $p_num > $self->{NUM_OF_PARAMS}){
98 1         26 $mockdbi->_set_dbi_err_errstr($self, err => 16, errstr => 'Illegal parameter number');
99 1         4 return;
100             }
101            
102             #Verify that the bind_param attribute is a valid one
103 6 50 33     17 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         16 $self->{ParamTypes}->{$p_num} = { TYPE => SQL_VARCHAR };
117             }
118            
119 6 100       14 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         6 $self->{ParamValues}->{$p_num} = $bind_value;
126            
127 5         4 push( @{ $self->{_fake}->{InoutParams} }, $p_num );
  5         7  
128            
129 5         11 return 1;
130             }
131              
132             sub _dbi_execute{
133 57     57   846 my ($self, @bind_values) = @_;
134            
135 57         130 $mockdbi->_clear_dbi_err_errstr($self);
136            
137 57         136 my ($status, $retval) = $mockdbi->_has_fake_retval($self->{Statement});
138 57 100       164 if($status){
139 5         13 $mockdbi->_set_fake_dbi_err_errstr($self);
140            
141 5 100       15 if(ref($retval) eq 'CODE'){
142 1         3 return $retval->($self);
143             }
144 4         16 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       210 $self->{Active} = 1 if $self->{Statement} =~ m/^select/i;
163 52         70 $self->{Executed} = 1;
164             #Update the parent activekids flag
165 52         127 Test::MockDBI::Db::_update_active_kids($self->{Database});
166            
167 52 100 66     244 if(ref($self->{_fake}->{InoutParams}) eq 'ARRAY' && scalar( @{ $self->{_fake}->{InoutParams} } ) > 0 ){
  52         213  
168 2         1 foreach my $p_num ( @{ $self->{_fake}->{InoutParams} } ){
  2         3  
169 3         8 my ($status, $retval) = $mockdbi->_has_inout_value($self->{Statement}, $p_num);
170 3 50       5 ${ $self->{ParamValues}->{$p_num} } = $retval if $status;
  3         5  
171             }
172            
173             }
174              
175             #Not enough parameters bound
176 52 100       68 if( $self->{NUM_OF_PARAMS} != scalar(keys %{ $self->{ParamValues} })){
  52         173  
177 3         22 return '0E0';
178             }
179            
180             #Number of affected rows is not known
181 49         94 return -1;
182             }
183              
184             sub _dbi_fetchrow_arrayref{
185 59     59   756 my ($self) = @_;
186            
187 59         122 $mockdbi->_clear_dbi_err_errstr($self);
188            
189             #return if we are not executed
190 59 100       150 return if( !$self->{Executed} );
191            
192 44         94 my ($status, $retval) = $mockdbi->_has_fake_retval($self->{Statement});
193 44 100       100 if($status){
194 31         138 $mockdbi->_set_fake_dbi_err_errstr($self);
195            
196 31 100       89 if(ref($retval) eq 'CODE'){
197 6         19 my @caller = caller(1);
198 6 100 66     65 if($caller[3] && $caller[3] =~ m/fetchrow_array$/){
199 3         9 return $retval;
200             }
201 3         9 return $retval->($self);
202             }
203             }
204            
205             #The resultset should be an array of hashes
206 38 100       88 if(ref($retval) ne 'ARRAY'){
207             #Should implement support for RaiseError and PrintError
208 17         41 return;
209             }
210            
211 21 100       21 if(scalar( @{$retval} ) > 0){
  21         47  
212 18         17 my $row = shift @{ $retval };
  18         19  
213 18 50       56 if(ref($row) ne 'ARRAY'){
214             #Should implement support for RaiseError and PrintError
215 0         0 return;
216             }
217 18         38 return $row;
218             }
219             #fetchrow_arrayref returns undef if no more rows are available, or an error has occured
220 3         4 return;
221             }
222              
223             sub _dbi_fetch{
224 4     4   20 return $_[0]->fetchrow_arrayref();
225             }
226              
227             sub _dbi_fetchrow_array{
228 20     20   535 my ($self) = @_;
229 20         42 my $row = $self->fetchrow_arrayref();
230 20 100       82 return if !$row;
231 7 100       19 return @{$row} if ref($row) eq 'ARRAY';
  4         15  
232 3 50       19 return $row->($self) if ref($row) eq 'CODE';
233 0         0 return $row;
234             }
235              
236             sub _dbi_fetchrow_hashref{
237 24     24   3288 my ($self) = @_;
238            
239 24         50 $mockdbi->_clear_dbi_err_errstr($self);
240            
241             #return if we are not executed
242 24 50       68 return if( !$self->{Executed} );
243            
244 24         45 my ($status, $retval) = $mockdbi->_has_fake_retval($self->{Statement});
245 24 100       46 if($status){
246 23         44 $mockdbi->_set_fake_dbi_err_errstr($self);
247            
248 23 100       51 if(ref($retval) eq 'CODE'){
249 8         18 return $retval->($self);
250             }
251             }
252            
253             #The resultset should be an array of hashes
254 16 100       27 if(ref($retval) ne 'ARRAY'){
255             #Should implement support for RaiseError and PrintError
256 3         6 return;
257             }
258            
259 13 100       8 if(scalar( @{$retval} ) > 0){
  13         18  
260 10         9 my $row = shift @{ $retval };
  10         10  
261 10 50       15 if(ref($row) ne 'HASH'){
262             #Should implement support for RaiseError and PrintError
263 0         0 return;
264             }
265 10         14 return $row;
266             }
267              
268             #fetchrow_hashref returns undef if no more rows are available, or an error has occured
269 3         4 return;
270             }
271              
272             sub _dbi_fetchall_arrayref{
273 11     11   587 my ($self) = @_;
274            
275 11         28 $mockdbi->_clear_dbi_err_errstr($self);
276            
277             #return if we are not executed
278 11 100       44 return if( !$self->{Executed} );
279            
280 7         20 my ($status, $retval) = $mockdbi->_has_fake_retval($self->{Statement});
281 7 100       21 if($status){
282 5         71 $mockdbi->_set_fake_dbi_err_errstr($self);
283            
284 5 100       19 if(ref($retval) eq 'CODE'){
285 1         4 return $retval->($self);
286             }
287             }
288              
289             #The resultset should be an array of hashes
290 6 100       14 if(ref($retval) ne 'ARRAY'){
291             #Should implement support for RaiseError and PrintError
292 4         7 return;
293             }
294            
295 2         4 return $retval;
296             }
297              
298              
299             sub _dbi_finish{
300 50     50   14604 my ($self) = @_;
301            
302 50         153 $mockdbi->_clear_dbi_err_errstr($self);
303            
304 50         152 my ($status, $retval) = $mockdbi->_has_fake_retval($self->{Statement});
305 50 100       129 if($status){
306 5         13 $mockdbi->_set_fake_dbi_err_errstr($self);
307            
308 5 100       15 if(ref($retval) eq 'CODE'){
309 1         4 return $retval->($self);
310             }
311 4         17 return $retval;
312             }
313            
314 45         63 $self->{Active} = undef;
315             #Update the parent activekids flag
316 45         108 Test::MockDBI::Db::_update_active_kids($self->{Database});
317            
318 45         504 return 1;
319             }
320              
321             sub _dbi_rows{
322 12     12   791 my ($self) = @_;
323            
324 12         37 $mockdbi->_clear_dbi_err_errstr($self);
325            
326 12         54 my ($status, $retval) = $mockdbi->_has_fake_retval($self->{Statement});
327 12 100       36 if($status){
328 10         29 $mockdbi->_set_fake_dbi_err_errstr($self);
329            
330 10 100       26 if(ref($retval) eq 'CODE'){
331 2         6 return $retval->($self);
332             }
333 8         36 return $retval;
334             }
335            
336 2         7 return -1;
337             }
338             1;