line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
=head1 NAME |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
DBIx::Class::Numeric - helper methods for numeric columns |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 SYNOPSIS |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
package MyApp::Schema::SomeTable; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
use base 'DBIx::Class'; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# Load the Numeric component |
12
|
|
|
|
|
|
|
# Don't forget to load it *before* Core! |
13
|
|
|
|
|
|
|
__PACKAGE__->load_components(qw/Numeric Core/); |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
# Add columns as per usual |
16
|
|
|
|
|
|
|
# Note, any numeric columns still need to appear here |
17
|
|
|
|
|
|
|
__PACKAGE__->add_columns( |
18
|
|
|
|
|
|
|
qw/primary_id some_string height width restricted bounded lower_bound upper_bound/ |
19
|
|
|
|
|
|
|
); |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
# Define 'simple' numeric cols, these will have some extra accessors & mutators |
22
|
|
|
|
|
|
|
# created |
23
|
|
|
|
|
|
|
__PACKAGE__->numeric_columns(qw/height width/); |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
# Define min and max values for a column |
26
|
|
|
|
|
|
|
__PACKAGE__->numeric_columns(restricted => {min_value => 10, max_value => 30}); |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# Define a column that's bound by the value of other columns |
29
|
|
|
|
|
|
|
__PACKAGE__->numeric_columns(bounded => {lower_bound_col => 'lower_bound', upper_bound_col => 'upper_bound'}); |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# ... meanwhile, after reading a record from the DB |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
$row->increase_height(5); # Add 5 to height |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
$row->decrease_width(9); # Subtract 9 from width |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
$row->adjust_height(-5); # Subtract 5 from height |
38
|
|
|
|
|
|
|
# (can be positive or negative, as can increase/decrease... |
39
|
|
|
|
|
|
|
# adjust is just a clearer name...) |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
$row->increment_height; # Increment height |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
$row->decrement_width; # Decrement width |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
$row->restricted(40); # restricted col will be set to '30' since that's the max |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
$row->lower_bound(5); |
48
|
|
|
|
|
|
|
$row->bounded(10); # bounded will be set to '5', since its lower bound was set to 5 |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=head1 DESCRIPTION |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
A DBIx::Class component that adds some extra accessors / mutators to any numeric columns |
53
|
|
|
|
|
|
|
you define. Additionally, columns can have max and min values defined, or be bound to the |
54
|
|
|
|
|
|
|
values of other columns in the table. |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
This is useful if you have a lot of numeric columns to work with, and you want a bit of |
57
|
|
|
|
|
|
|
syntactic sugar for adding / subtracting from the column, or you need upper/lower |
58
|
|
|
|
|
|
|
bounds. |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=head1 METHODS |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=head2 numeric_columns(@cols) |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
Call this method as you would add_columns(), and pass it a list of columns that are numeric. Note, |
65
|
|
|
|
|
|
|
you need to pass the column names to add_columns() *and* numeric_columns(). |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
Any columns in this list will have extra accessors / mutators defined (see below). |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
If the item in the list after a column name is a hashref, the hashref will define the arguments for |
70
|
|
|
|
|
|
|
that numeric column. (If the next item's not a hashref, it's assumed to be the next column - you can |
71
|
|
|
|
|
|
|
mix and match columns with and without arguments in the same call to numeric_colums(). |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
The valid keys in the argument hashref are: |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=over 4 |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
=item min_value / max_value |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
These two keys define the minimum and/or maximum value of the column. If you attempt to set the column |
80
|
|
|
|
|
|
|
to a value outside this range, it will be set to that min or max value accordingly. |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=item lower_bound_col / upper_bound_col |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
If either of these are set to the name of a column in the same table, the numeric column will be |
85
|
|
|
|
|
|
|
restricted in the same way as a min or max value, except the min/max value will be defined by the |
86
|
|
|
|
|
|
|
value of the column specified. |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
If the value of the lower or upper bound column changes, the bounded column won't be affected, until |
89
|
|
|
|
|
|
|
its value is set. Eg. if your bounded column is currently 5, and you set it's lower_bound_col to |
90
|
|
|
|
|
|
|
8 the bounded col won't change, even though it's below the minimum value. If you were to (eg) increment |
91
|
|
|
|
|
|
|
the column, it would then be set to 8. |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=back |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=over |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=item WARNING |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
Little (if any) validation is done on the list of cols passed to numeric_columns(). You could easily |
100
|
|
|
|
|
|
|
pass it non-existant column names, etc. (This may be improved in a later release). |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
In particular, no check is made to see if you are using incompatible combinations of min/max_value |
103
|
|
|
|
|
|
|
and lower/uppper_bound_col (e.g. both a min_value and a lower_bound_col). Doing this is unsupported, |
104
|
|
|
|
|
|
|
and may be prevented in the future (even thought it might 'kind of' work at the moment). You're free |
105
|
|
|
|
|
|
|
to use compatible combinations, though, eg. a min_value and an upper_bound_col. |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=back |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
=head2 increase_*, decrease_*, increment_*, decrement_*, adjust_* |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
These 5 methods are added to your schema class for each column you pass to numeric_cols(). E.g. if |
112
|
|
|
|
|
|
|
you have a numeric column called 'foo', you will automagically get methods called increment_foo(), |
113
|
|
|
|
|
|
|
decrement_foo(), etc. They are fairly self-explanatory, with the possible exception of 'adjust_*'. |
114
|
|
|
|
|
|
|
You can pass it either a positive or negative value to adjust the value of the column accordingly. |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=head1 AUTHOR |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
Sam Crawley (Mutant) - mutant dot nz at gmail dot com |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=head1 LICENSE |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
You may distribute this code under the same terms as Perl itself. |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=cut |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
package DBIx::Class::Numeric; |
127
|
|
|
|
|
|
|
|
128
|
3
|
|
|
3
|
|
1421
|
use strict; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
70
|
|
129
|
3
|
|
|
3
|
|
13
|
use warnings; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
117
|
|
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
our $VERSION = '0.004'; |
132
|
|
|
|
|
|
|
|
133
|
3
|
|
|
3
|
|
13
|
use base qw(DBIx::Class Class::Accessor::Grouped); |
|
3
|
|
|
|
|
11
|
|
|
3
|
|
|
|
|
1096
|
|
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
__PACKAGE__->mk_group_accessors('inherited', '_numeric_col_def'); |
136
|
|
|
|
|
|
|
|
137
|
3
|
|
|
3
|
|
118179
|
use Sub::Name (); |
|
3
|
|
|
|
|
9
|
|
|
3
|
|
|
|
|
492
|
|
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub numeric_columns { |
140
|
7
|
|
|
7
|
1
|
169436
|
my $self = shift; |
141
|
7
|
|
|
|
|
20
|
my @cols = @_; |
142
|
|
|
|
|
|
|
|
143
|
7
|
|
|
|
|
20
|
my $count = 0; |
144
|
7
|
|
|
|
|
11
|
my %def; |
145
|
|
|
|
|
|
|
|
146
|
7
|
|
|
|
|
17
|
foreach my $col (@cols) { |
147
|
24
|
100
|
|
|
|
63
|
next if ref $col eq 'HASH'; |
148
|
|
|
|
|
|
|
|
149
|
14
|
|
|
|
|
23
|
my $args = {}; |
150
|
14
|
100
|
|
|
|
37
|
if (ref $cols[$count+1] eq 'HASH') { |
151
|
10
|
|
|
|
|
22
|
$args = $cols[$count+1]; |
152
|
|
|
|
|
|
|
} |
153
|
14
|
|
|
|
|
29
|
$def{$col} = $args; |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
my %methods = ( |
156
|
|
|
|
|
|
|
adjust => sub { |
157
|
1
|
|
|
1
|
|
396
|
_adjust($col, @_); |
|
|
|
|
1
|
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
158
|
|
|
|
|
|
|
}, |
159
|
|
|
|
|
|
|
increase => sub { |
160
|
1
|
|
|
1
|
|
359
|
_increase($col, @_); |
|
|
|
|
1
|
|
|
|
|
|
|
|
1
|
|
|
|
161
|
|
|
|
|
|
|
}, |
162
|
|
|
|
|
|
|
decrease => sub { |
163
|
1
|
|
|
1
|
|
490
|
_decrease($col, @_); |
|
|
|
|
1
|
|
|
|
|
|
|
|
1
|
|
|
|
164
|
|
|
|
|
|
|
}, |
165
|
|
|
|
|
|
|
increment => sub { |
166
|
1
|
|
|
1
|
|
443
|
_increment($col, @_); |
|
|
|
|
1
|
|
|
|
|
|
|
|
1
|
|
|
|
167
|
|
|
|
|
|
|
}, |
168
|
|
|
|
|
|
|
decrement => sub { |
169
|
1
|
|
|
1
|
|
435
|
_decrement($col, @_); |
|
|
|
|
1
|
|
|
|
|
|
|
|
1
|
|
|
|
170
|
|
|
|
|
|
|
} |
171
|
14
|
|
|
|
|
142
|
); |
172
|
|
|
|
|
|
|
|
173
|
14
|
|
|
|
|
53
|
while (my ($method_name, $subref) = each %methods) { |
174
|
3
|
|
|
3
|
|
20
|
no strict 'refs'; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
87
|
|
175
|
3
|
|
|
3
|
|
15
|
no warnings 'redefine'; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
1222
|
|
176
|
|
|
|
|
|
|
|
177
|
70
|
|
|
|
|
155
|
my $name = join '::', $self, "${method_name}_$col"; |
178
|
70
|
|
|
|
|
445
|
*$name = Sub::Name::subname($name, $subref); |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
continue { |
182
|
24
|
|
|
|
|
46
|
$count++; |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
|
185
|
7
|
|
|
|
|
158
|
my $existing = $self->_numeric_col_def; |
186
|
7
|
100
|
|
|
|
624
|
%def = (%$existing, %def) if $existing; |
187
|
|
|
|
|
|
|
|
188
|
7
|
|
|
|
|
123
|
$self->_numeric_col_def(\%def); |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
sub _increase { |
192
|
5
|
|
|
5
|
|
11
|
my $col = shift; |
193
|
5
|
|
|
|
|
7
|
my $self = shift; |
194
|
5
|
|
|
|
|
8
|
my $increase = shift; |
195
|
|
|
|
|
|
|
|
196
|
5
|
|
50
|
|
|
13
|
$self->set_column($col, ($self->get_column($col) || 0) + ($increase || 0)); |
|
|
|
50
|
|
|
|
|
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
sub _decrease { |
200
|
2
|
|
|
2
|
|
6
|
_increase($_[0], $_[1], -$_[2]); |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
sub _increment { |
204
|
1
|
|
|
1
|
|
4
|
_increase($_[0], $_[1], 1); |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
sub _decrement { |
208
|
1
|
|
|
1
|
|
3
|
_decrease($_[0], $_[1], 1); |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
sub _adjust { |
212
|
1
|
|
|
1
|
|
4
|
_increase(@_); |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
sub set_column { |
216
|
12
|
|
|
12
|
0
|
24939
|
my $self = shift; |
217
|
12
|
|
|
|
|
34
|
my $column = shift; |
218
|
12
|
|
|
|
|
26
|
my $new_val = shift; |
219
|
|
|
|
|
|
|
|
220
|
12
|
|
|
|
|
34
|
$new_val = $self->_restrict_numeric($column, $new_val); |
221
|
|
|
|
|
|
|
|
222
|
12
|
|
|
|
|
71
|
return $self->next::method( $column, $new_val, @_ ); |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub insert { |
226
|
2
|
|
|
2
|
0
|
781540
|
my $self = shift; |
227
|
|
|
|
|
|
|
|
228
|
2
|
50
|
|
|
|
71
|
if (my $def = $self->_numeric_col_def) { |
229
|
2
|
|
|
|
|
110
|
foreach my $column (keys %$def) { |
230
|
6
|
100
|
66
|
|
|
1016
|
next unless $def->{$column} && %{ $def->{$column} }; |
|
6
|
|
|
|
|
53
|
|
231
|
|
|
|
|
|
|
|
232
|
5
|
|
|
|
|
46
|
my $val = $self->get_column($column); |
233
|
|
|
|
|
|
|
|
234
|
5
|
50
|
|
|
|
76
|
next unless defined $val; |
235
|
|
|
|
|
|
|
|
236
|
5
|
|
|
|
|
31
|
$self->set_column($column, $self->_restrict_numeric($column, $val)); |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
|
240
|
2
|
|
|
|
|
86
|
return $self->next::method( @_ ); |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
sub _restrict_numeric { |
244
|
17
|
|
|
17
|
|
42
|
my $self = shift; |
245
|
17
|
|
|
|
|
36
|
my $column = shift; |
246
|
17
|
|
|
|
|
34
|
my $new_val = shift; |
247
|
|
|
|
|
|
|
|
248
|
17
|
|
|
|
|
433
|
my $def = $self->_numeric_col_def; |
249
|
|
|
|
|
|
|
|
250
|
17
|
50
|
|
|
|
560
|
if ($def) { |
251
|
17
|
100
|
100
|
|
|
94
|
if (defined $def->{$column}{min_value} && $new_val < $def->{$column}{min_value}) { |
252
|
1
|
|
|
|
|
4
|
$new_val = $def->{$column}{min_value}; |
253
|
|
|
|
|
|
|
} |
254
|
17
|
100
|
100
|
|
|
81
|
if (defined $def->{$column}{max_value} && $new_val > $def->{$column}{max_value}) { |
255
|
3
|
|
|
|
|
11
|
$new_val = $def->{$column}{max_value}; |
256
|
|
|
|
|
|
|
} |
257
|
17
|
100
|
|
|
|
53
|
if (defined $def->{$column}{upper_bound_col}) { |
258
|
6
|
|
|
|
|
25
|
my $max_val = $self->get_column($def->{$column}{upper_bound_col}); |
259
|
6
|
100
|
|
|
|
70
|
$new_val = $max_val if $new_val > $max_val; |
260
|
|
|
|
|
|
|
} |
261
|
17
|
100
|
|
|
|
73
|
if (defined $def->{$column}{lower_bound_col}) { |
262
|
6
|
|
|
|
|
21
|
my $min_val = $self->get_column($def->{$column}{lower_bound_col}); |
263
|
6
|
100
|
|
|
|
73
|
$new_val = $min_val if $new_val < $min_val; |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
17
|
|
|
|
|
65
|
return $new_val; |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
1; |