File Coverage

blib/lib/DBD/Mock/StatementTrack.pm
Criterion Covered Total %
statement 130 142 91.5
branch 50 58 86.2
condition 22 24 91.6
subroutine 28 30 93.3
pod 0 26 0.0
total 230 280 82.1


line stmt bran cond sub pod time code
1             package DBD::Mock::StatementTrack;
2              
3 40     40   309 use strict;
  40         113  
  40         1311  
4 40     40   223 use warnings;
  40         86  
  40         1312  
5              
6 40     40   715 use List::Util qw( reduce );
  40         95  
  40         75866  
7              
8             sub new {
9 148     148 0 7338 my ( $class, %params ) = @_;
10              
11             # these params have default values
12             # but can be overridden
13 148   100     683 $params{return_data} ||= [];
14 148 100 100     632 $params{fields} ||= $DBD::Mock::DefaultFieldsToUndef ? undef : [];
15 148   100     715 $params{bound_params} ||= [];
16 148   50     724 $params{bound_param_attrs} ||= [];
17 148   100     384 $params{statement} ||= "";
18 148   100     690 $params{failure} ||= undef;
19 148   100     618 $params{callback} ||= undef;
20 148   100     659 $params{driver_attributes} ||= {};
21 148   100     677 $params{execute_attributes} ||= {};
22              
23             # these params should never be overridden
24             # and should always start out in a default
25             # state to assure the sanity of this class
26 148         345 $params{is_executed} = 'no';
27 148         296 $params{is_finished} = 'no';
28 148         284 $params{current_record_num} = 0;
29              
30             # NOTE:
31             # changed from \%params here because that
32             # would bind the hash sent in so that it
33             # would reflect alterations in the object
34             # this violates encapsulation
35 148         1219 my $self = bless {%params}, $class;
36 148         705 return $self;
37             }
38              
39             sub has_failure {
40 150     150 0 308 my ($self) = @_;
41 150 100       635 $self->{failure} ? 1 : 0;
42             }
43              
44             sub get_failure {
45 3     3 0 5 my ($self) = @_;
46 3         4 @{ $self->{failure} };
  3         61  
47             }
48              
49             sub num_fields {
50 4     4 0 684 my ($self) = @_;
51 4 100       18 return $self->{fields} ? scalar @{ $self->{fields} } : $self->{fields};
  3         15  
52             }
53              
54             sub num_rows {
55 48     48 0 95 my ($self) = @_;
56 48         72 return scalar @{ $self->{return_data} };
  48         345  
57             }
58              
59             sub num_params {
60 143     143 0 324 my ($self) = @_;
61 143         214 return scalar @{ $self->{bound_params} };
  143         890  
62             }
63              
64             sub bind_col {
65 13     13 0 27 my ( $self, $param_num, $ref ) = @_;
66 13         39 $self->{bind_cols}->[ $param_num - 1 ] = $ref;
67             }
68              
69             sub bound_param {
70 17     17 0 39 my ( $self, $param_num, $value, $attr ) = @_;
71              
72             # Basic support for named parameters
73 17 100       74 if ( $param_num !~ /^\d+/ ) {
74 2         5 $param_num = $self->num_params + 1;
75             }
76              
77 17         65 $self->{bound_params}->[ $param_num - 1 ] = $value;
78 17 100       62 $self->{bound_param_attrs}->[ $param_num - 1 ] = ref $attr eq "HASH" ? { %$attr } : $attr;
79              
80 17         42 return $self->bound_params;
81             }
82              
83             sub bound_param_trailing {
84 1     1 0 4 my ( $self, @values ) = @_;
85 1         2 push @{ $self->{bound_params} }, @values;
  1         5  
86             }
87              
88             sub bind_cols {
89 123     123 0 186 my $self = shift;
90 123 100       176 return @{ $self->{bind_cols} || [] };
  123         643  
91             }
92              
93             sub bind_params {
94 47     47 0 129 my ( $self, @values ) = @_;
95 47         91 @{ $self->{bound_params} } = @values;
  47         118  
96 47         114 @{ $self->{bound_param_attrs} } = map { undef } @values;
  47         159  
  65         150  
97             }
98              
99             # Rely on the DBI's notion of Active: a statement is active if it's
100             # currently in a SELECT and has more records to fetch
101              
102             sub is_active {
103 10     10 0 21 my ($self) = @_;
104 10 100       23 return 0 unless $self->statement =~ /^\s*select/ism;
105 7 100       21 return 0 unless $self->is_executed eq 'yes';
106 6 100       22 return 0 if $self->is_depleted;
107 3         13 return 1;
108             }
109              
110             sub is_finished {
111 50     50 0 110 my ( $self, $value ) = @_;
112 50 100 100     240 if ( defined $value && $value eq 'yes' ) {
    100          
113 39         85 $self->{is_finished} = 'yes';
114 39         106 $self->current_record_num(0);
115 39         92 $self->{return_data} = [];
116             }
117             elsif ( defined $value ) {
118 1         2 $self->{is_finished} = 'no';
119             }
120 50         214 return $self->{is_finished};
121             }
122              
123             ####################
124             # RETURN VALUES
125              
126             sub mark_executed {
127 139     139 0 784 my ($self) = @_;
128              
129              
130 139         361 push @{$self->{execution_history} }, {
131 139         352 params => [ @{ $self->{bound_params} } ],
132 139         214 attrs => [ @{ $self->{bound_param_attrs} } ],
  139         573  
133             };
134              
135 139         483 $self->is_executed('yes');
136 139         394 $self->current_record_num(0);
137              
138 139         219 $self->{driver_attributes} = { %{ $self->{driver_attributes} }, %{ $self->{execute_attributes} } };
  139         360  
  139         346  
139              
140 139 100       672 if (ref $self->{callback} eq "CODE") {
141 13         19 my %recordSet = $self->{callback}->(@{ $self->{bound_params} });
  13         38  
142              
143 13 100       173 if (ref $recordSet{fields} eq "ARRAY") {
144 10         22 $self->{fields} = $recordSet{fields};
145             }
146              
147 13 50       30 if (ref $recordSet{rows} eq "ARRAY") {
148 13 100   10   45 die "DBD::Mock error - a resultset's callback should return rows as an arrayref of arrayrefs" if reduce { ref $b ne "ARRAY" ? 1 : $a } 0, @{ $recordSet{rows} };
  10 100       47  
  13         87  
149 12         52 $self->{return_data} = $recordSet{rows};
150             }
151              
152 12 100       42 if (defined $recordSet{last_insert_id}) {
153 2         4 $self->{last_insert_id} = $recordSet{last_insert_id};
154             }
155              
156 12 100       40 if (defined $recordSet{execute_attributes}) {
157 1         2 $self->{driver_attributes} = { %{ $self->{driver_attributes} }, %{ $recordSet{execute_attributes} } };
  1         3  
  1         5  
158             }
159             }
160             }
161              
162             sub next_record {
163 171     171 0 798 my ($self) = @_;
164 171 100       341 return if $self->is_depleted;
165 142         303 my $rec_num = $self->current_record_num;
166 142         241 my $rec = $self->return_data->[$rec_num];
167 142         356 $self->current_record_num( $rec_num + 1 );
168 142         399 return $rec;
169             }
170              
171             sub is_depleted {
172 190     190 0 1303 my ($self) = @_;
173 190         369 return ( $self->current_record_num >= scalar @{ $self->return_data } );
  190         366  
174             }
175              
176             # DEBUGGING AID
177              
178             sub to_string {
179 0     0 0 0 my ($self) = @_;
180             return join "\n" => (
181             $self->{statement},
182 0         0 "Values: [" . join( '] [', @{ $self->{bound_params} } ) . "]",
183             "Records: on $self->{current_record_num} of "
184 0         0 . scalar( @{ $self->return_data } ) . "\n",
  0         0  
185             "Executed? $self->{is_executed}; Finished? $self->{is_finished}"
186             );
187             }
188              
189             # PROPERTIES
190              
191             # boolean
192              
193             sub is_executed {
194 153     153 0 330 my ( $self, $yes_no ) = @_;
195 153 100       444 $self->{is_executed} = $yes_no if defined $yes_no;
196 153 100       463 return ( $self->{is_executed} eq 'yes' ) ? 'yes' : 'no';
197             }
198              
199             # single-element fields
200              
201             sub statement {
202 29     29 0 3785 my ( $self, $value ) = @_;
203 29 100       86 $self->{statement} = $value if defined $value;
204 29         145 return $self->{statement};
205             }
206              
207             sub current_record_num {
208 669     669 0 1070 my ( $self, $value ) = @_;
209 669 100       1341 $self->{current_record_num} = $value if defined $value;
210 669         1112 return $self->{current_record_num};
211             }
212              
213             sub callback {
214 0     0 0 0 my ( $self, $callback ) = @_;
215 0 0       0 $self->{callback} = $callback if defined $callback;
216 0         0 return $self->{callback};
217             }
218              
219             # multi-element fields
220              
221             sub return_data {
222 335     335 0 516 my ( $self, @values ) = @_;
223 335 50       624 push @{ $self->{return_data} }, @values if scalar @values;
  0         0  
224 335         968 return $self->{return_data};
225             }
226              
227             sub fields {
228 163     163 0 340 my ( $self, @values ) = @_;
229              
230 163   50     410 $self->{fields} ||= [];
231              
232 163 50       393 push @{ $self->{fields} }, @values if scalar @values;
  0         0  
233              
234 163         469 return $self->{fields};
235             }
236              
237             sub bound_params {
238 83     83 0 4247 my ( $self, @values ) = @_;
239 83 50       222 push @{ $self->{bound_params} }, @values if scalar @values;
  0         0  
240 83         675 return $self->{bound_params};
241             }
242              
243             sub bound_param_attrs {
244 6     6 0 4913 my ( $self, @values ) = @_;
245 6 50       18 push @{ $self->{bound_param_attrs} }, @values if scalar @values;
  0         0  
246 6         22 return $self->{bound_param_attrs};
247             }
248              
249             sub execution_history {
250 1     1 0 4 my ( $self, @values ) = @_;
251 1 50       4 push @{ $self->{execution_history} }, @values if scalar @values;
  0         0  
252 1         5 return $self->{execution_history};
253             }
254              
255             1;