File Coverage

blib/lib/DBIx/QuickORM/RowManager.pm
Criterion Covered Total %
statement 118 134 88.0
branch 33 52 63.4
condition 21 33 63.6
subroutine 21 27 77.7
pod 0 17 0.0
total 193 263 73.3


line stmt bran cond sub pod time code
1             package DBIx::QuickORM::RowManager;
2 23     23   19389 use strict;
  23         112  
  23         1369  
3 23     23   172 use warnings;
  23         52  
  23         1895  
4              
5             our $VERSION = '0.000019';
6              
7 23     23   157 use Carp qw/confess croak/;
  23         79  
  23         1697  
8 23     23   157 use Scalar::Util qw/weaken/;
  23         52  
  23         1245  
9 23     23   137 use DBIx::QuickORM::Util qw/load_class/;
  23         56  
  23         319  
10              
11 23     23   957 use DBIx::QuickORM::Affinity();
  23         53  
  23         778  
12              
13 23         167 use DBIx::QuickORM::Connection::RowData qw{
14             STORED
15             PENDING
16             DESYNC
17             TRANSACTION
18             ROW_DATA
19 23     23   36067 };
  23         96  
20              
21 23         175 use DBIx::QuickORM::Util::HashBase qw{
22             transactions
23             connection
24 23     23   1270 };
  23         58  
25              
26             sub init {
27 23     23 0 62 my $self = shift;
28              
29 23 50       223 my $con = $self->{+CONNECTION} or croak "Connection was not provided";
30 23   33     120 $self->{+TRANSACTIONS} //= $con->transactions;
31              
32 23         85 weaken($self->{+CONNECTION});
33             }
34              
35 0     0 0 0 sub does_cache { 0 }
36              
37       0 0   sub cache { }
38       0 0   sub uncache { }
39              
40             sub cache_lookup {
41 0     0 0 0 my $self = shift;
42 0         0 return $self->do_lookup($self->parse_params({@_}));
43             }
44              
45             sub do_cache_lookup {
46 0     0 0 0 my $self = shift;
47 0         0 my ($source, $fetched, $old_pk, $new_pk, $row) = @_;
48 0         0 return undef;
49             }
50              
51             sub invalidate {
52 0     0 0 0 my $self = shift;
53 0         0 my ($source, $fetched, $old_pk, $new_pk, $row, $params) = $self->parse_params({@_});
54              
55 0         0 my $reason = $params->{reason};
56 0 0       0 unless ($reason) {
57 0         0 my @caller = caller;
58 0         0 $reason = "$caller[1] line $caller[2]";
59             }
60              
61             # Remove from passed in row if we got one
62 0 0       0 $row->{+ROW_DATA}->invalidate(reason => $reason) if $row;
63              
64             # Now check cache for row, might be same, might not
65 0         0 $row = $self->uncache($source, $row, $old_pk, $new_pk);
66 0 0       0 $row->{+ROW_DATA}->invalidate(reason => $reason) if $row;
67              
68 0         0 return;
69             }
70              
71             sub _state {
72 176     176   369 my $self = shift;
73 176         978 my %params = @_;
74              
75 176 100 33     350 $params{+TRANSACTION} //= $self->{+TRANSACTIONS}->[-1] if @{$self->{+TRANSACTIONS}};
  176         824  
76              
77 176         607 return \%params;
78             }
79              
80             sub _vivify {
81 111     111   239 my $self = shift;
82 111         335 my ($source, $state) = @_;
83 111         284 my $connection = $self->{+CONNECTION};
84 111 50 66     2071 my $row_class = load_class($source->row_class // $connection->schema->row_class // 'DBIx::QuickORM::Row') or die $@;
      50        
85 111         1595 my $row_data = DBIx::QuickORM::Connection::RowData->new(stack => [$state], connection => $connection, source => $source);
86 111         955 return $row_class->new(ROW_DATA() => $row_data);
87             }
88              
89             sub vivify {
90 2     2 0 6 my $self = shift;
91 2         24 my ($source, $fetched, $old_pk, $new_pk, $row) = $self->parse_params({@_}, fetched => 1);
92 2   33     24 $row //= $self->_vivify($source, $self->_state(pending => $fetched));
93              
94 2         25 return $row;
95             }
96              
97             sub insert {
98 79     79 0 206 my $self = shift;
99 79         1094 my ($source, $fetched, $old_pk, $new_pk, $row) = $self->parse_params({@_});
100              
101 79         669 $row = $self->do_insert($source, $fetched, $old_pk, $new_pk, $row);
102 79         528 $self->cache($source, $row, $old_pk, $new_pk);
103              
104 79         1204 return $row;
105             }
106              
107             sub do_insert {
108 79     79 0 211 my $self = shift;
109 79         261 my ($source, $fetched, $old_pk, $new_pk, $row) = @_;
110              
111 79         530 my $state = $self->_state(stored => $fetched, pending => undef);
112              
113 79 100       543 $row->{+ROW_DATA}->change_state($state) if $row;
114              
115 79   66     697 $row //= $self->_vivify($source, $state);
116              
117 79         262 return $row;
118             }
119              
120             sub update {
121 12     12 0 30 my $self = shift;
122 12         157 my ($source, $fetched, $old_pk, $new_pk, $row) = $self->parse_params({@_});
123              
124 12         103 $row = $self->do_update($source, $fetched, $old_pk, $new_pk, $row);
125 12         74 $self->cache($source, $row, $old_pk, $new_pk);
126              
127 12         76 return $row;
128             }
129              
130             sub do_update {
131 12     12 0 31 my $self = shift;
132 12         38 my ($source, $fetched, $old_pk, $new_pk, $row) = @_;
133              
134 12         79 my $state = $self->_state(stored => $fetched, pending => undef, desync => undef);
135              
136 12 100       44 if ($row) {
137 11         69 $row->{+ROW_DATA}->change_state($state);
138             }
139             else {
140 1         8 $row = $self->_vivify($source, $state)
141             }
142              
143 12         45 return $row;
144             }
145              
146             sub delete {
147 8     8 0 23 my $self = shift;
148 8         67 my ($source, $fetched, $old_pk, $new_pk, $row) = $self->parse_params({@_}, fetched => 1);
149              
150 8 50       39 return unless $row;
151 8         44 $row = $self->do_delete($source, $fetched, $old_pk, $new_pk, $row);
152 8         41 $self->uncache($source, $row, $old_pk, $new_pk);
153              
154 8         47928 return $row;
155             }
156              
157             sub do_delete {
158 8     8 0 20 my $self = shift;
159 8         26 my ($source, $fetched, $old_pk, $new_pk, $row) = @_;
160              
161 8         40 $row->{+ROW_DATA}->change_state($self->_state(stored => undef));
162              
163 8         28 return $row;
164             }
165              
166             sub select {
167 75     75 0 158 my $self = shift;
168 75         628 my ($source, $fetched, $old_pk, $new_pk, $row) = $self->parse_params({@_});
169              
170 75         506 $row = $self->do_select($source, $fetched, $old_pk, $new_pk, $row);
171 75         371 $self->cache($source, $row, $old_pk, $new_pk);
172              
173 75         596 return $row;
174             }
175              
176             sub do_select {
177 75     75 0 145 my $self = shift;
178 75         229 my ($source, $fetched, $old_pk, $new_pk, $row) = @_;
179              
180 75         384 my $state = $self->_state(stored => $fetched);
181              
182             # No existing row, make a new one
183 75 100       359 return $self->_vivify($source, $state)
184             unless $row;
185              
186 41         294 $row->{+ROW_DATA}->change_state($state);
187              
188 41         141 return $row;
189             }
190              
191             sub parse_params {
192 176     176 0 452 my $self = shift;
193 176         614 my ($params, %skip) = @_;
194              
195 176 50       919 my $source = $params->{source} or confess "'source' is a required parameter";
196 176 50       1211 confess "'$source' is not a valid query source" unless $source->DOES('DBIx::QuickORM::Role::Source');
197              
198 176         5225 my $new_pk = $params->{new_primary_key};
199              
200 176         473 my $fetched = $params->{fetched};
201 176 100 66     5345 if ($fetched || !$skip{fetched}) {
202 174         369 my @pk_vals;
203 174 50       539 confess "'fetched' is a required parameter" unless $fetched;
204 174 50       708 confess "'$fetched' is not a valid fetched data set" unless ref($fetched) eq 'HASH';
205              
206 174 100       1033 if (my $pk_fields = $source->primary_key) {
207 165         350 my @bad;
208 165         483 for my $field (@$pk_fields) {
209 165 100       710 if (exists $fetched->{$field}) {
210 164         664 push @pk_vals => $fetched->{$field};
211             }
212             else {
213 1         5 push @bad => $field;
214             }
215             }
216              
217 165 100       525 if (@bad) {
218             confess "The following primary key fields are missing from the fetched data: " . join(', ' => sort @bad)
219 1 50       5 unless $skip{fetched};
220             }
221             else {
222 164   100     1702 $new_pk //= \@pk_vals;
223             }
224             }
225             }
226              
227 176         503 my $old_pk = $params->{old_primary_key};
228              
229 176         349 my $row;
230 176 50       649 unless ($skip{row}) {
231 176 100       682 if ($row = $params->{row}) {
232 6 50       65 confess "'$row' is not a valid row" unless $row->isa('DBIx::QuickORM::Row');
233 6 50       78 confess "Row has incorrect source" unless $row->source == $source;
234 6 50       49 confess "Row has incorrect connection" unless $row->connection == $self->{+CONNECTION};
235 6 100 50     77 $old_pk //= [$row->primary_key_value_list] if $row->in_storage;
236             }
237              
238 176         1199 my $cached = $self->do_cache_lookup($source, $fetched, $old_pk, $new_pk, $row);
239              
240 176 50 100     1117 confess "Cached row does not match operating row" if $cached && $row && $cached != $row;
      66        
241 176   100     874 $row //= $cached;
242             }
243              
244 176         937 return ($source, $fetched, $old_pk, $new_pk, $row, $params);
245             }
246              
247             1;