File Coverage

blib/lib/Test/MockDBI.pm
Criterion Covered Total %
statement 254 308 82.4
branch 100 142 70.4
condition 29 48 60.4
subroutine 29 35 82.8
pod 6 12 50.0
total 418 545 76.7


line stmt bran cond sub pod time code
1             package Test::MockDBI;
2              
3 50     50   1305134 use 5.008; # minimum Perl is V5.8.0
  50         179  
  50         2108  
4 50     50   281 use strict;
  50         98  
  50         2755  
5 50     50   291 use warnings;
  50         98  
  50         1930  
6 50     50   281 use Carp;
  50         91  
  50         3598  
7 50     50   40363 use Clone;
  50         294228  
  50         3391  
8 50     50   47978 use Test::MockObject::Extends;
  50         556222  
  50         3591  
9 50     50   6404 use Scalar::Util;
  50         126  
  50         20077  
10              
11             our $VERSION = '0.70';
12              
13             my $instance = undef;
14              
15             =head1 NAME
16            
17             Test::MockDBI - Mocked DBI interface for testing purposes
18              
19             =head1 SYNOPSIS
20              
21             use Test::MockDBI;
22            
23             my $mi = Test::MockDBI::get_instance();
24            
25             Sets a fake return value for the rows statementhandler
26             $mi->set_retval( method => rows, retval => sub{ return scalar( @somearray ); });
27            
28             $mi->set_retval( method => 'bind_param', retval => undef);
29             Same as:
30             $mi->bad_method('bind_param');
31            
32             You can also specify return values for specific sqls
33             $mi->set_retval( method => rows, retval => sub{ return scalar( @somearray ); }, sql => 'select id from names');
34            
35             $mi->set_retval( method => 'bind_param', retval => undef, sql => 'select id from names where id < ?');
36             Same as:
37             $mi->bad_method('bind_param', 'select id from names where id < ?');
38            
39            
40            
41             =cut
42              
43              
44             sub import{
45            
46 50     50   37062 require Test::MockDBI::Db;
47 50         38937 require Test::MockDBI::St;
48            
49            
50 50         506 $instance = bless {
51             methods => {
52             },
53             _regexes => {}
54             }, __PACKAGE__;
55            
56 50         401 Test::MockDBI::Db->import($instance);
57 50         222 Test::MockDBI::St->import($instance);
58            
59 50         646 my $mock = Test::MockObject::Extends->new();
60            
61 50         1376 $mock->fake_module("DBI",
62             connect => \&_dbi_connect,
63             _concat_hash_sorted => \&_dbi__concat_hash_sorted,
64             _get_sorted_hash_keys => \&_dbi__get_sorted_hash_keys,
65             looks_like_number => \&_dbi__looks_like_number
66             );
67            
68 50         5083 my %dbi_methods = (
69             "DBI::db" => ['clone', 'data_sources', 'do', 'last_inserted_id', 'selectrow_array', 'selectrow_hashref', 'selectall_arrayref',
70             'selectall_hashref', 'selectcol_arrayref', 'prepare', 'prepare_cached', 'commit', 'rollback', 'begin_work', 'disconnect',
71             'ping', 'get_info', 'table_info', 'column_info', 'primary_key_info', 'primary_key', 'foreign_key_info', 'statistics_info',
72             'tables', 'type_info_all', 'type_info', 'quote', 'quote_identifier', 'take_imp_data', 'err', 'errstr'],
73             "DBI::st" => ['bind_param', 'bind_param_inout', 'bind_param_array', 'execute', 'execute_array', 'execute_array_fetch',
74             'fetchrow_arrayref', 'fetchrow_array', 'fetchrow_hashref', 'fetchall_arrayref', 'fetchall_hashref', 'finish',
75             'rows', 'bind_col', 'bind_columns', 'dump_results', 'err', 'errstr', 'fetch']
76             );
77            
78 50         207 my %packages = ( "Test::MockDBI::Db" => "DBI::db", "Test::MockDBI::St" => "DBI::st" );
79            
80 50         178 foreach my $mock_package ( keys %packages ){
81 100         15751 my %available_methods = ();
82            
83             #Takes the package as a parameter
84             my $map_subs = sub{
85 50     50   308 no strict 'refs';
  50         708  
  50         194179  
86 200     200   358 my $p = shift;
87 200         265 return map{ s/^_dbi_//; $_ => $p . '::_dbi_' . $_ } grep { m/^_dbi_/ } grep { defined &{"$p\::$_"} } keys %{"$p\::"};
  1100         2905  
  1100         7633  
  3500         6528  
  4650         4694  
  4650         23141  
  200         1525  
88 100         546 };
89              
90 100         315 %available_methods = $map_subs->($mock_package);
91             #Also find methods inherited by the package
92 100         6556 my @isalist = eval( '@' . $mock_package . '::ISA');
93 100 50       536 die('Could not eval @' . $mock_package .'::ISA') if $@;
94 100         240 foreach my $isa_package ( @isalist ){
95             #Pray for no duplicates
96 100         276 my %isamethods = $map_subs->($isa_package);
97 100         662 @available_methods{keys %isamethods} = values %isamethods;
98             }
99              
100 100         219 my %args = ();
101 100         160 foreach my $method ( @{ $dbi_methods{ $packages{$mock_package} } } ){
  100         317  
102 2500 100       8034 if(grep { m/^$method$/} keys %available_methods){
  26900         95749  
103 1100         55556 $args{$method} = eval( '\&' . $available_methods{$method});
104 1100 50       6111 die("Error during fake module setup. " . $@) if($@);
105             }else{
106             #Need to check if the method is inherited from a parent package
107 1400     0   89667 $args{$method} = eval('sub{ die \'Test::MockDBI-ERROR : Unsupported method ' . $method . '\'; } ');
  0         0  
  0         0  
  0         0  
  1         44  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
108             }
109             }
110 100         4330 $mock->fake_module( $packages{ $mock_package }, %args );
111             }
112 50         11946 $mock->fake_new( "DBI" );
113 50         68412 return 1;
114             }
115             ##################################
116             #
117             # OO - Test MockDBI API
118             #
119             ###################################
120              
121             =head1 PUBLIC INTERFACE
122              
123             Methods available on the Test::MockDBI instance.
124              
125             =over 4
126              
127             =item reset()
128              
129             Method for reseting all mock returnvalues \ bad_params etc
130            
131             =cut
132              
133             sub reset{
134 8     8 1 3080 my ($self) = @_;
135 8         64 $self->{methods} = {};
136             }
137              
138             =item bad_method()
139              
140             This method is basically a alias for calling set_retval with the return value undef.
141            
142             Args:
143             $method_name - The name of the method which should return undef
144             $matching_sql (Optional) - The sql matching condition
145            
146             Returns:
147             On success: 1
148             On failure: undef
149            
150             The method also supports calling the method with the following arguments:
151             $method_name, $dbi_testing_type, $matching_sql
152             This will issue a warning as it is deprecated.
153              
154             =cut
155              
156             sub bad_method{
157 29     29 1 18027 my $self = shift;
158 29         58 my %args = ();
159            
160 29 100 66     234 if(scalar(@_) == 3 && $_[0] =~ m/^[a-z_]+$/ && $_[1] =~ m/^\d+$/){
      66        
161 14         85 warn "You have called bad_method in an deprecated way. Please consult the documentation\n";
162 14         704 $args{method} = shift;
163            
164             #Throw away $dbi_testing_type
165 14         17 shift;
166 14         19 my $matchingsql = shift;
167 14 50 33     40 if($matchingsql && $matchingsql ne ''){
168 0         0 my $regex = qr/$matchingsql/;
169 0         0 $args{sql} = $regex;
170             }
171             }else{
172 15         42 %args = @_;
173             }
174            
175 29         51 $args{retval} = undef;
176              
177 29         96 return $self->set_retval( %args );
178             }
179              
180             =item bad_param()
181            
182             Args:
183             $p_value - The value that will cause bind_param to return undef
184             $sql (Optional) - The sql matching condition
185            
186             Returns:
187             On success: 1
188             On failure: undef
189            
190             The method also supports calling the method with the following arguments:
191             $dbi_testing_type, $p_num, $p_value
192             This will issue a warning as it is deprecated.
193              
194             =cut
195              
196             sub bad_param{
197 6     6 1 3118 my $self = shift;
198 6         16 my %args;
199            
200             #We assume its a legacy call if its length is 3 and arg 1 && 2 is numeric
201 6 100 66     113 if(scalar(@_) == 3 && $_[0] =~ m/^\d+$/ && $_[1] =~ m/^\d+$/){
      66        
202 5         46 warn "You have called bad_param in an deprecated way. Please consult the documentation\n";
203             #Throw away $dbi_testing_type as we dont use it anymoer
204 5         303 shift;
205             #Throw away $p_num as we dont use it anymore
206 5         9 shift;
207 5         17 $args{p_value} = shift;
208             }else{
209 1         6 %args = @_;
210             }
211            
212 6 100       21 if($args{sql}){
213 1         3 push( @{ $self->{methods}->{bind_param}->{sqls}->{$args{sql}}->{bad_params}}, $args{p_value});
  1         7  
214 1 50       49 $self->{_regexes}->{$args{sql}} = (ref($args{sql}) eq 'Regexp') ? $args{sql} : qr/\Q$args{sql}\E/;
215             }else{
216 5         11 push( @{ $self->{methods}->{bind_param}->{global_bad_params} }, $args{p_value});
  5         42  
217             }
218            
219 6         47 return 1;
220             }
221              
222             =item set_retval()
223              
224             Method for setting a return value for the specific method.
225            
226             Args:(Keys in a hash)
227             method - The method that should return the provided value
228             retval - The data which should be returned
229             sql (Optional) - Matching sql. The return value will only be
230             returned for the provided method if the sql matches
231             a regex compiled by using this string
232              
233             Returnvalues:
234             On success: 1
235             On failure: undef
236            
237             Example usage:
238            
239             #fetchrow_hashref will shift one hashref from the list each time its called if the sql matches the sql provided, this will happend
240             #until the return list is empty.
241             $inst->set_retval( method => 'fetchrow_hashref',
242             retval => [ { letter => 'a' }, { letter => 'b' }, { letter => 'c' } ],
243             sql => 'select * from letters' )
244            
245             #execute will default return undef
246             $inst->set_retval( method => 'execute', retval => undef)
247            
248             #Execute will return 10 for sql 'select * from cars'
249             $inst->set_retval( method => 'execute', retval => undef);
250             $inst->set_retval( method => 'execute', retval => 10, sql => 'select * from cars');
251            
252             =cut
253              
254             sub set_retval{
255 146     146 1 58251 my ($self, %args) = @_;
256            
257 146         287 my $method = $args{method};
258 146 100       567 my $sql = $args{sql} if $args{sql};
259            
260 146 100       390 unless($method){
261 1         9 warn "No method provided\n";
262 1         62 return;
263             }
264            
265 145 100       369 if(ref($method)){
266 1         7 warn "Parameter method must be a scalar string\n";
267 1         58 return;
268             }
269              
270 144 100 100     826 if($sql && (ref($sql) && ref($sql) ne 'Regexp')){
      66        
271 1         7 warn "Parameter SQL must be a scalar string or a precompiled regex\n";
272 1         60 return;
273             }
274            
275 143 100       719 unless( exists $args{retval} ){
276 1         6 warn "No retval provided\n";
277 1         53 return;
278             }
279            
280 142 100       880 $self->{methods}->{$method} = {} if !$self->{methods}->{$method};
281            
282 142 100       350 if($sql){
283 57         985 $self->{methods}->{$method}->{sqls}->{$sql}->{retval} = Clone::clone($args{retval});
284 57 50       215 $self->{methods}->{$method}->{sqls}->{$sql}->{errstr} = $args{errstr} if $args{errstr};
285 57 50       187 $self->{methods}->{$method}->{sqls}->{$sql}->{err} = $args{err} if $args{err};
286 57 100       360 $self->{_regexes}->{$sql} = (ref($sql) eq 'Regexp') ? $sql : qr/\Q$sql\E/;
287             }else{
288 85         840 $self->{methods}->{$method}->{default}->{retval} = Clone::clone($args{retval});
289 85 100       341 $self->{methods}->{$method}->{default}->{errstr} = $args{errstr} if $args{errstr};
290 85 100       225 $self->{methods}->{$method}->{default}->{err} = $args{err} if $args{err};
291             }
292 142         533 return 1;
293             }
294              
295             =item set_inout_value()
296              
297             Special method for handling inout params.
298             In this method you can provided the value that the inout param should have
299             after execute is called.
300            
301             Args:
302             $sql - The sql that this rule should apply for
303             $p_num - The parameter number of the inout parameter
304             $value - The value that the inout parameter should have after execute
305            
306             Returns:
307             On success: 1
308             On failure: undef
309            
310             Example:
311            
312            
313              
314             =cut
315              
316             sub set_inout_value{
317 5     5 1 2108 my ($self, $sql, $p_num, $value) = @_;
318            
319 5 100 66     37 if(!$sql || ref($sql)){
320 1         9 warn "Parameter SQL must be a scalar string\n";
321 1         76 return;
322             }
323 4 100       22 if($p_num !~ m/^\d+$/){
324 1         8 warn "Parameter p_num must be numeric\n";
325 1         59 return;
326             }
327            
328 3         14 $self->{inoutvalues}->{$sql}->{$p_num} = $value;
329 3         9 return 1;
330             }
331              
332             =back
333              
334             =head1 PRIVATE INTERFACE
335              
336             Methods used by the package internally. Should not be called from an external package.
337              
338             =over 4
339              
340             =item _clear_dbi_err_errstr()
341              
342             Helper method used by the fake DBI::st and DBI::db to clear out
343             the $obj->{err} and $obj->{errstr} on each method call.
344            
345             Should not be called from an external script\package.
346              
347             =cut
348              
349             sub _clear_dbi_err_errstr{
350 394     394   649 my ($self, $obj) = @_;
351            
352 394         855 $obj->{errstr} = undef;
353 394         602 $obj->{err} = undef;
354 394         469 $DBI::errstr = undef;
355 394         442 $DBI::err = undef;
356 394         774 return 1;
357             }
358              
359             =item _set_dbi_err_errstr()
360              
361             Helper method used by the fake DBI::st and DBI::db to set the
362             $obj->{err}, $obj->{errstr}, $DBI::err and $DBI::errstr.
363             This method also handles RaiseError and PrintError attributes.
364            
365             Args:
366             $obj - Instance of DBI::st or DBI::db
367             %args - A hash with the following keys:
368             err - The numeric error code to be set
369             errstr - The user friendly DBI error message.
370            
371             Returns:
372             On success : 1
373             On failure : undef
374              
375             =cut
376              
377             sub _set_dbi_err_errstr{
378 66     66   259 my ($self, $obj, %args) = @_;
379 66 100       324 if($args{err}){
380 21         34 $DBI::err = $args{err};
381 21         43 $obj->{err} = $args{err};
382             }
383            
384 66 100       176 if($args{errstr}){
385 21         31 $DBI::errstr = $args{errstr};
386 21         40 $obj->{errstr} = $args{errstr};
387             }
388            
389 66 50 33     532 print $obj->{errstr} . "\n" if $obj->{PrintError} && $obj->{errstr};
390 66 0       389 die( (($obj->{errstr}) ? $obj->{errstr} : '') ) if $obj->{RaiseError};
    50          
391 66         147 return 1;
392             }
393              
394             =item _set_fake_dbi_err_errstr
395              
396             =cut
397              
398             sub _set_fake_dbi_err_errstr{
399 130     130   479 my ($self, $obj) = @_;
400 130         496 my $sql = $obj->{Statement};
401              
402             #This should be refactored out in a helper method
403 130         718 my @caller = caller(1);
404 130         1504 my $method = $caller[3];
405            
406 130         633 $method =~ s/Test::MockDBI::(St|Db)::_dbi_//;
407              
408             #No special return value is set for this method
409 130 50       442 return if !exists($self->{methods}->{$method});
410            
411            
412             #Search to see if the sql has a specific
413 130 50       316 if($sql){
414 130         244 foreach my $key (keys %{$self->{methods}->{$method}->{sqls}}){
  130         484  
415             #This introduces the bug that the first hit will be the one used.
416             #This is done to be complient with the regex functionality in the earlier versions
417             #of Test::MockDBI
418 47 100       255 if( $sql =~ $self->{_regexes}->{$key}){
419 45         603 $self->_set_dbi_err_errstr($obj,
420             err => $self->{methods}->{$method}->{sqls}->{$key}->{err},
421             errstr => $self->{methods}->{$method}->{sqls}->{$key}->{errstr}
422             );
423 45         197 return 1;
424             }
425             }
426             }
427             #If $sql is not or we have no matching sql we return the default if it is set
428 85 100 66     424 if(exists $self->{methods}->{$method}->{default}->{err} && exists $self->{methods}->{$method}->{default}->{errstr}){
429 17         82 $self->_set_dbi_err_errstr($obj,
430             err => $self->{methods}->{$method}->{default}->{err},
431             errstr => $self->{methods}->{$method}->{default}->{errstr});
432 17         67 return 1;
433             }
434              
435 68         233 return ;
436             }
437              
438             =item _has_inout_value()
439              
440             Helper method used by the DBI::db and DBI::st packages.
441             The method searches to see if there is specified a value for a
442             inout variable.
443            
444             If called in SCALAR context it return 1/undef based on if the
445             parameter bound as $p_num has a predefined return value set.
446            
447             If called in LIST context the method returns and array with
448             1/undef in position 0 which indicates the same as when the method
449             is called in SCALAR context. The second element of the list is the
450             value that should be applied to the inout parameter.
451              
452             =cut
453              
454             sub _has_inout_value{
455 3     3   6 my ($self, $sql, $p_num) = @_;
456            
457 3         3 foreach my $key (keys %{ $self->{inoutvalues} }){
  3         8  
458 3 50       94 if( $sql =~ m/\Q$key\E/ms){
459 3 50       12 if($self->{inoutvalues}->{$key}->{$p_num}){
460 3 50       17 return (wantarray) ? (1, $self->{inoutvalues}->{$key}->{$p_num}) : 1;
461             }
462             }
463             }
464 0         0 return;
465             }
466              
467             =item _has_fake_retval()
468            
469             Method for identifing if a method has a predefined return value set.
470             If the SQL parameter is provided
471             this will have precedence over the default value.
472            
473             If the method is called in SCALAR context it will return 1\undef based on
474             if the method has a predefined return value set.
475            
476             If the method is called in LIST context it will return a list with 1/undef at
477             index 0 which indicates the same as when called in SCALAR context. index 1 will
478             contain a reference to the actual return value that should be returned by the method.
479             This value may be undef.
480            
481             =cut
482              
483             sub _has_fake_retval{
484 431     431   735 my ($self, $sql) = @_;
485 431         2167 my @caller = caller(1);
486 431         6435 my $method = $caller[3];
487            
488 431         2423 $method =~ s/Test::MockDBI(::(St|Db))?::_dbi_//;
489            
490             #No special return value is set for this method
491 431 100       2831 return if !exists($self->{methods}->{$method});
492            
493            
494             #Search to see if the sql has a specific
495 176 100       476 if($sql){
496 149         207 foreach my $key (keys %{$self->{methods}->{$method}->{sqls}}){
  149         681  
497             #This introduces the bug that the first hit will be the one used.
498             #This is done to be complient with the regex functionality in the earlier versions
499             #of Test::MockDBI
500             # if( ( ($key =~ m/^\(\?\^:/ && $sql =~ $instance->{legacy_regex}->{$key}) || $sql =~ m/\Q$key\E/ms ) &&
501             # exists $self->{methods}->{$method}->{sqls}->{$key}->{retval}){
502            
503             # to handle old and new versions of PERL
504 73 100       321 my $modifiers = ($key =~ /\Q(?^/) ? "^" : "-xism";
505            
506 73 100 100     767 if( $sql =~ $self->{_regexes}->{$key} &&
507             exists $self->{methods}->{$method}->{sqls}->{$key}->{retval}){
508            
509 45 50       304 if(wantarray()){
510 45         390 return (1, $self->{methods}->{$method}->{sqls}->{$key}->{retval});
511             }else{
512 0         0 return 1;
513             }
514             }
515             }
516             }
517             #If $sql is not or we have no matching sql we return the default if it is set
518 131 100       527 if(exists $self->{methods}->{$method}->{default}->{retval}){
519 88 50       562 return (wantarray()) ? (1, $self->{methods}->{$method}->{default}->{retval}) : undef;
520             }
521            
522 43         185 return;
523             }
524              
525             =item _is_bad_bind_param()
526            
527             Method for identifing if a bind parameters value is predefined as unwanted.
528             The configuration for the provided SQL will have precedence over the default configured behaviour.
529            
530             When called it will return 1\undef based on
531             if the provided value should make the bind_param method fail.
532            
533             =cut
534              
535             sub _is_bad_bind_param{
536 32     32   58 my ($self, $sql, $param) = @_;
537 32         177 my @caller = caller(1);
538 32         269 my $method = $caller[3];
539            
540 32         139 $method =~ s/Test::MockDBI::(St|Db)::_dbi_//;
541            
542 32         49 foreach my $key (keys %{ $self->{methods}->{$method}->{sqls} }){
  32         132  
543             #This introduces the bug that the first hit will be the one used.
544             #This is done to be complient with the regex functionality in the earlier versions
545             #of Test::MockDBI
546            
547 4 50       17 if( $sql =~ $self->{_regexes}->{$key} ){
548             #If no bad params is set for this sql do nothing and continue the loop.
549 4 50 33     41 if($self->{methods}->{$method}->{sqls}->{$key}->{bad_params} &&
550             ref($self->{methods}->{$method}->{sqls}->{$key}->{bad_params}) eq 'ARRAY'){
551            
552 4         4 foreach my $bad_param ( @{ $self->{methods}->{$method}->{sqls}->{$key}->{bad_params} }){
  4         11  
553 4 50 33     24 if(Scalar::Util::looks_like_number($param) && Scalar::Util::looks_like_number($bad_param)){
554 4 100       30 return 1 if $param == $bad_param;
555             }
556 2 50       11 return 1 if $param eq $bad_param;
557             }
558             }
559             }
560             }
561            
562 30 100 66     200 if(exists $self->{methods}->{$method}->{global_bad_params} && ref($self->{methods}->{$method}->{global_bad_params}) eq 'ARRAY'){
563 10         17 foreach my $bad_param ( @{ $self->{methods}->{$method}->{global_bad_params} }){
  10         29  
564 10 100 100     75 if(Scalar::Util::looks_like_number($param) && Scalar::Util::looks_like_number($bad_param)){
565 1 50       4 return 1 if $param == $bad_param;
566             }
567 10 100       58 return 1 if $param eq $bad_param;
568             }
569             }
570 27         134 return;
571             }
572              
573             =back
574              
575             =head1 CLASS INTERFACE
576              
577             =over 4
578              
579             =item get_instance()
580              
581             Method for retrieving the current Test::MockDBI instance
582            
583             =cut
584              
585             sub get_instance{
586 40     40 1 27545 return $instance;
587             }
588              
589             =back
590              
591             =cut
592              
593             ####################################
594             #
595             # Mocked DBI API
596             # (Method used to mock the DBI package's methods)
597             #
598             ####################################
599              
600             =pod _dbi__concat_hash_sorted
601              
602             This is basically a copy\paste from the DBI package itself.
603             The method is used inside the prepare_cached method
604              
605             =cut
606              
607             sub _dbi__concat_hash_sorted {
608 6     6   15 my ( $hash_ref, $kv_separator, $pair_separator, $use_neat, $num_sort ) = @_;
609             # $num_sort: 0=lexical, 1=numeric, undef=try to guess
610              
611 6 50       24 return undef unless defined $hash_ref;
612 6 50       25 die "hash is not a hash reference" unless ref $hash_ref eq 'HASH';
613 6         13 my $keys = DBI::_get_sorted_hash_keys($hash_ref, $num_sort);
614 6         12 my $string = '';
615 6         11 for my $key (@$keys) {
616 3 50       11 $string .= $pair_separator if length $string > 0;
617 3         6 my $value = $hash_ref->{$key};
618 3 50       8 if ($use_neat) {
619 0         0 $value = DBI::neat($value, 0);
620             }
621             else {
622 3 50       13 $value = (defined $value) ? "'$value'" : 'undef';
623             }
624 3         11 $string .= $key . $kv_separator . $value;
625             }
626 6         50 return $string;
627             }
628              
629             =pod _dbi__get_sorted_hash_keys
630              
631             This is basically a copy\paste from the DBI package itself.
632             The method is used inside the prepare_cached method
633              
634             =cut
635              
636             sub _dbi__get_sorted_hash_keys {
637 6     6   9 my ($hash_ref, $num_sort) = @_;
638 6 50       12 if (not defined $num_sort) {
639 0         0 my $sort_guess = 1;
640             $sort_guess = (not DBI::looks_like_number($_)) ? 0 : $sort_guess
641 0 0       0 for keys %$hash_ref;
642 0         0 $num_sort = $sort_guess;
643             }
644            
645 6         18 my @keys = keys %$hash_ref;
646 50     50   605 no warnings 'numeric';
  50         175  
  50         67445  
647 0 0       0 my @sorted = ($num_sort)
648 6 50       21 ? sort { $a <=> $b or $a cmp $b } @keys
649             : sort @keys;
650 6         15 return \@sorted;
651             }
652              
653             =pod _dbi_looks_like_number
654              
655             This is basically a copy\paste from the DBI package itself.
656             The method is used inside the prepare_cached method
657              
658             =cut
659              
660             sub _dbi_looks_like_number {
661 0     0   0 my @new = ();
662 0         0 for my $thing(@_) {
663 0 0 0     0 if (!defined $thing or $thing eq '') {
664 0         0 push @new, undef;
665             }
666             else {
667 0 0       0 push @new, ($thing =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/) ? 1 : 0;
668             }
669             }
670 0 0       0 return (@_ >1) ? @new : $new[0];
671             }
672              
673             =pod _dbi_connect
674              
675             Mocked DBI->connect method.
676            
677             The method takes the same arguments as the usual DBI->connect method.
678             It returns a $dbh which has ref DBI::db
679            
680             =cut
681              
682             sub _dbi_connect{
683 56     56   18205 my ($self, $dsn, $user, $pass, $attr) = @_;
684            
685 56         145 my $statement = 'CONNECT TO $dsn AS $user WITH $pass';
686            
687 56         301 my ($status, $retval) = $instance->_has_fake_retval($statement);
688 56 100       261 if($status){
689 3 100       13 if(ref($retval) eq 'CODE'){
690 1         3 return $retval->();
691             }
692 2         9 return $retval;
693             }
694            
695 53         1761 my $object = bless({
696             AutoCommit => 1,
697             Driver => undef,
698             Name => undef,
699             Statement => $statement,
700             RowCacheSize => undef,
701             Username => undef,
702            
703             #Common
704             Warn => undef,
705             Active => undef,
706             Executed => undef,
707             Kids => 0,
708             ActiveKids => undef,
709             CachedKids => undef,
710             Type => 'db',
711             ChildHandles => [],
712             CompatMode => undef,
713             InactiveDestroy => undef,
714             AutoInactiveDestroy => undef,
715             PrintWarn => undef,
716             PrintError => undef,
717             RaiseError => undef,
718             HandleError => undef,
719             HandleSetErr => undef,
720             ErrCount => undef,
721             ShowErrorStatement => undef,
722             TraceLevel => undef,
723             FetchHashKeyName => undef,
724             ChopBlanks => undef,
725             LongReadLen => undef,
726             LongTruncOk => undef,
727             TaintIn => undef,
728             TaintOut => undef,
729             Taint => undef,
730             Profile => undef,
731             ReadOnly => undef,
732             Callbacks => undef,
733             }, "DBI::db");
734            
735 53         141 foreach my $key (keys %{ $attr }){
  53         246  
736 9 50       63 $object->{$key} = $attr->{$key} if(exists($object->{$key}));
737             }
738            
739 53         249 return $object;
740            
741             }
742              
743             ##########################################################
744             #
745             # DEPRECATED OLD INTERFACE
746             #
747             ###########################################################
748             sub set_retval_array{
749 10     10 0 1537 warn 'set_retval_array is deprecated. Please use $instance->set_retval instead' . "\n";
750 10         642 my ($self, $dbi_testing_type, $matching_sql, @retval) = @_;
751            
752 10         216 my $regex = qr/$matching_sql/;
753            
754 10 100       53 if(ref($retval[0]) eq 'CODE'){
755 2         24 return $instance->set_retval( method => 'fetchrow_arrayref', sql => $regex, retval => $retval[0]);
756             }else{
757 8         79 return $instance->set_retval( method => 'fetchrow_arrayref', sql => $regex, retval => [ \@retval ]);
758             }
759             }
760             sub set_retval_scalar{
761 17     17 0 5822 warn 'set_retval_scalar is deprecated. Please use $instance->set_retval instead' . "\n";
762 17         1037 my ($self, $dbi_testing_type, $matching_sql, $retval) = @_;
763            
764 17         66 my @methods = qw(fetchall_arrayref fetchrow_arrayref fetchall_hashref fetchrow_hashref);
765              
766 17         505 my $regex = qr/$matching_sql/;
767              
768             #try to find out if the $retval is an arrayref only, or an arrayref of arrayref
769             # or arrayref of hashrefs
770 17 100       101 if(ref($retval) eq 'ARRAY'){
    100          
771 10         42 my $item = $retval->[0];
772            
773 10 100       72 if(ref($item) eq 'ARRAY'){
    50          
    50          
774             #We most likely have an arrayref of arrayrefs
775             #it should be applied to fetchall_arrayref and fetchrow_arrayref
776 2         16 $instance->set_retval( method => 'fetchall_arrayref', sql => $regex, retval => $retval);
777 2         7 $instance->set_retval( method => 'fetchrow_arrayref', sql => $regex, retval => $retval);
778             }elsif(ref($item) eq 'HASH'){
779             #We most likely have an arrayref of hashrefs
780             #it should be applied to fetchall_hashrefref and fetchrow_hashref
781 0         0 $instance->set_retval( method => 'fetchall_hashref', sql => $regex, retval => $retval);
782 0         0 $instance->set_retval( method => 'fetchrow_hashref', sql => $regex, retval => $retval);
783             }elsif(!ref($item)){
784             #We only have 1 arrayref with values. This was used in the old Test::MockDBI tests
785             #It was passed because you only called for instance fetchrow_arrayref once
786             #We will wrap it in an array and hope for the best
787 8         561 $instance->set_retval( method => 'fetchrow_arrayref', sql => $regex, retval => [$retval]);
788             }else{
789             #We dont know, set the same retval for EVERYONE!
790 0         0 foreach my $method ( @methods ){
791 0         0 $instance->set_retval( method => $method, sql => $regex, retval => $retval);
792             }
793             }
794            
795             }elsif(ref($retval) eq 'HASH'){
796 1         7 $instance->set_retval( method => 'fetchrow_hashref', sql => $regex, retval => [$retval]);
797             }else{
798             #We dont know, set the same retval for EVERYONE!
799 6         18 foreach my $method ( @methods ){
800 24         73 $instance->set_retval( method => $method, sql => $regex, retval => $retval);
801             }
802             }
803 17         123 return 1;
804             }
805             sub set_rows{
806 4     4 0 333 warn 'set_rows is deprecated. Please use $instance->set_retval instead' . "\n";
807 4         304 my ($self, $dbi_testing_type, $matching_sql, $rows) = @_;
808            
809 4         115 my $regex = qr/$matching_sql/;
810            
811 4         29 return $instance->set_retval( method => 'rows', sql => $regex, retval => $rows );
812             }
813              
814             sub set_errstr{
815 0     0 0   warn "set_errstr is deprecated. Please use $instance->set_retval instead \n";
816 0           return;
817             }
818             sub _is_bad_param{
819 0     0     warn "_is_bad_param is deprecated and no longer functional. It allways returns 1\n";
820 0           return 1;
821             }
822             sub set_dbi_test_type{
823 0     0 0   warn "set_dbi_test_type is deprecated. Does nothing!\n";
824 0           return 1;
825             }
826             sub get_dbi_test_type{
827 0     0 0   warn "get_dbi_test_type is deprecated. Does nothing!\n";
828 0           return 1;
829             }
830              
831             =head1 AUTHOR
832              
833             Mark Leighton Fisher,
834             Emark-fisher@fisherscreek.comE
835              
836             Minor modifications (version 0.62 onwards) by
837             Andreas Faafeng
838             Eaff@cpan.orgE
839              
840             =head1 COPYRIGHT
841              
842             Copyright 2004, Fisher's Creek Consulting, LLC. Copyright
843             2004, DeepData, Inc.
844              
845             =head1 LICENSE
846              
847             This code is released under the same licenses as Perl
848             itself.
849              
850             =cut
851              
852             1;