Filename | /usr/share/perl5/DBIx/Class/InflateColumn.pm |
Statements | Executed 1109 statements in 4.45ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
122 | 1 | 1 | 3.59ms | 44.4ms | inflate_column | DBIx::Class::InflateColumn::
1 | 1 | 1 | 17µs | 28µs | BEGIN@3 | DBIx::Class::InflateColumn::
1 | 1 | 1 | 11µs | 39µs | BEGIN@7 | DBIx::Class::InflateColumn::
1 | 1 | 1 | 11µs | 14.9ms | BEGIN@6 | DBIx::Class::InflateColumn::
1 | 1 | 1 | 10µs | 18µs | BEGIN@4 | DBIx::Class::InflateColumn::
1 | 1 | 1 | 8µs | 100µs | BEGIN@8 | DBIx::Class::InflateColumn::
0 | 0 | 0 | 0s | 0s | _deflated_column | DBIx::Class::InflateColumn::
0 | 0 | 0 | 0s | 0s | _inflated_column | DBIx::Class::InflateColumn::
0 | 0 | 0 | 0s | 0s | get_inflated_column | DBIx::Class::InflateColumn::
0 | 0 | 0 | 0s | 0s | set_inflated_column | DBIx::Class::InflateColumn::
0 | 0 | 0 | 0s | 0s | store_inflated_column | DBIx::Class::InflateColumn::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package DBIx::Class::InflateColumn; | ||||
2 | |||||
3 | 2 | 43µs | 2 | 40µs | # spent 28µs (17+11) within DBIx::Class::InflateColumn::BEGIN@3 which was called:
# once (17µs+11µs) by Class::C3::Componentised::ensure_class_loaded at line 3 # spent 28µs making 1 call to DBIx::Class::InflateColumn::BEGIN@3
# spent 11µs making 1 call to strict::import |
4 | 2 | 39µs | 2 | 26µs | # spent 18µs (10+8) within DBIx::Class::InflateColumn::BEGIN@4 which was called:
# once (10µs+8µs) by Class::C3::Componentised::ensure_class_loaded at line 4 # spent 18µs making 1 call to DBIx::Class::InflateColumn::BEGIN@4
# spent 8µs making 1 call to warnings::import |
5 | |||||
6 | 2 | 187µs | 2 | 14.9ms | # spent 14.9ms (11µs+14.9) within DBIx::Class::InflateColumn::BEGIN@6 which was called:
# once (11µs+14.9ms) by Class::C3::Componentised::ensure_class_loaded at line 6 # spent 14.9ms making 1 call to DBIx::Class::InflateColumn::BEGIN@6
# spent 14.9ms making 1 call to base::import, recursion: max depth 1, sum of overlapping time 14.9ms |
7 | 2 | 59µs | 2 | 67µs | # spent 39µs (11+28) within DBIx::Class::InflateColumn::BEGIN@7 which was called:
# once (11µs+28µs) by Class::C3::Componentised::ensure_class_loaded at line 7 # spent 39µs making 1 call to DBIx::Class::InflateColumn::BEGIN@7
# spent 28µs making 1 call to Exporter::import |
8 | 2 | 773µs | 2 | 192µs | # spent 100µs (8+92) within DBIx::Class::InflateColumn::BEGIN@8 which was called:
# once (8µs+92µs) by Class::C3::Componentised::ensure_class_loaded at line 8 # spent 100µs making 1 call to DBIx::Class::InflateColumn::BEGIN@8
# spent 92µs making 1 call to namespace::clean::import |
9 | |||||
10 | =head1 NAME | ||||
11 | |||||
12 | DBIx::Class::InflateColumn - Automatically create references from column data | ||||
13 | |||||
14 | =head1 SYNOPSIS | ||||
15 | |||||
16 | # In your table classes | ||||
17 | __PACKAGE__->inflate_column('column_name', { | ||||
18 | inflate => sub { | ||||
19 | my ($raw_value_from_db, $result_object) = @_; | ||||
20 | ... | ||||
21 | }, | ||||
22 | deflate => sub { | ||||
23 | my ($inflated_value_from_user, $result_object) = @_; | ||||
24 | ... | ||||
25 | }, | ||||
26 | }); | ||||
27 | |||||
28 | =head1 DESCRIPTION | ||||
29 | |||||
30 | This component translates column data into references, i.e. "inflating" | ||||
31 | the column data. It also "deflates" references into an appropriate format | ||||
32 | for the database. | ||||
33 | |||||
34 | It can be used, for example, to automatically convert to and from | ||||
35 | L<DateTime> objects for your date and time fields. There's a | ||||
36 | convenience component to actually do that though, try | ||||
37 | L<DBIx::Class::InflateColumn::DateTime>. | ||||
38 | |||||
39 | It will handle all types of references except scalar references. It | ||||
40 | will not handle scalar values, these are ignored and thus passed | ||||
41 | through to L<SQL::Abstract>. This is to allow setting raw values to | ||||
42 | "just work". Scalar references are passed through to the database to | ||||
43 | deal with, to allow such settings as C< \'year + 1'> and C< \'DEFAULT' > | ||||
44 | to work. | ||||
45 | |||||
46 | If you want to filter plain scalar values and replace them with | ||||
47 | something else, see L<DBIx::Class::FilterColumn>. | ||||
48 | |||||
49 | =head1 METHODS | ||||
50 | |||||
51 | =head2 inflate_column | ||||
52 | |||||
53 | Instruct L<DBIx::Class> to inflate the given column. | ||||
54 | |||||
55 | In addition to the column name, you must provide C<inflate> and | ||||
56 | C<deflate> methods. The C<inflate> method is called when you access | ||||
57 | the field, while the C<deflate> method is called when the field needs | ||||
58 | to used by the database. | ||||
59 | |||||
60 | For example, if you have a table C<events> with a timestamp field | ||||
61 | named C<insert_time>, you could inflate the column in the | ||||
62 | corresponding table class using something like: | ||||
63 | |||||
64 | __PACKAGE__->inflate_column('insert_time', { | ||||
65 | inflate => sub { | ||||
66 | my ($insert_time_raw_value, $event_result_object) = @_; | ||||
67 | DateTime->from_epoch( epoch => $insert_time_raw_value ); | ||||
68 | }, | ||||
69 | deflate => sub { | ||||
70 | my ($insert_time_dt_object, $event_result_object) = @_; | ||||
71 | $insert_time_dt_object->epoch; | ||||
72 | }, | ||||
73 | }); | ||||
74 | |||||
75 | The coderefs you set for inflate and deflate are called with two parameters, | ||||
76 | the first is the value of the column to be inflated/deflated, the second is | ||||
77 | the result object itself. | ||||
78 | |||||
79 | In this example, calls to an event's C<insert_time> accessor return a | ||||
80 | L<DateTime> object. This L<DateTime> object is later "deflated" back | ||||
81 | to the integer epoch representation when used in the database layer. | ||||
82 | For a much more thorough handling of the above example, please see | ||||
83 | L<DBIx::Class::DateTime::Epoch> | ||||
84 | |||||
85 | =cut | ||||
86 | |||||
87 | # spent 44.4ms (3.59+40.8) within DBIx::Class::InflateColumn::inflate_column which was called 122 times, avg 364µs/call:
# 122 times (3.59ms+40.8ms) by DBIx::Class::Relationship::Accessor::add_relationship_accessor at line 95 of DBIx/Class/Relationship/Accessor.pm, avg 364µs/call | ||||
88 | 122 | 60µs | my ($self, $col, $attrs) = @_; | ||
89 | |||||
90 | 122 | 1.23ms | 122 | 2.29ms | my $colinfo = $self->column_info($col); # spent 2.29ms making 122 calls to DBIx::Class::ResultSourceProxy::column_info, avg 19µs/call |
91 | |||||
92 | 122 | 76µs | $self->throw_exception("InflateColumn can not be used on a column with a declared FilterColumn filter") | ||
93 | if defined $colinfo->{_filter_info} and $self->isa('DBIx::Class::FilterColumn'); | ||||
94 | |||||
95 | 122 | 176µs | 122 | 1.28ms | $self->throw_exception("No such column $col to inflate") # spent 1.28ms making 122 calls to DBIx::Class::ResultSourceProxy::has_column, avg 10µs/call |
96 | unless $self->has_column($col); | ||||
97 | 122 | 704µs | $self->throw_exception("inflate_column needs attr hashref") | ||
98 | unless ref $attrs eq 'HASH'; | ||||
99 | 122 | 115µs | $colinfo->{_inflate_info} = $attrs; | ||
100 | 122 | 53µs | my $acc = $colinfo->{accessor}; | ||
101 | 122 | 617µs | 122 | 37.2ms | $self->mk_group_accessors('inflated_column' => [ (defined $acc ? $acc : $col), $col]); # spent 37.2ms making 122 calls to Class::Accessor::Grouped::mk_group_accessors, avg 305µs/call |
102 | 122 | 320µs | return 1; | ||
103 | } | ||||
104 | |||||
105 | sub _inflated_column { | ||||
106 | my ($self, $col, $value) = @_; | ||||
107 | |||||
108 | return $value if ( | ||||
109 | ! defined $value # NULL is NULL is NULL | ||||
110 | or | ||||
111 | is_literal_value($value) #that would be a not-yet-reloaded literal update | ||||
112 | ); | ||||
113 | |||||
114 | my $info = $self->result_source->column_info($col) | ||||
115 | or $self->throw_exception("No column info for $col"); | ||||
116 | |||||
117 | return $value unless exists $info->{_inflate_info}; | ||||
118 | |||||
119 | return ( | ||||
120 | $info->{_inflate_info}{inflate} | ||||
121 | || | ||||
122 | $self->throw_exception("No inflator found for '$col'") | ||||
123 | )->($value, $self); | ||||
124 | } | ||||
125 | |||||
126 | sub _deflated_column { | ||||
127 | my ($self, $col, $value) = @_; | ||||
128 | |||||
129 | ## Deflate any refs except for literals, pass through plain values | ||||
130 | return $value if ( | ||||
131 | ! length ref $value | ||||
132 | or | ||||
133 | is_literal_value($value) | ||||
134 | ); | ||||
135 | |||||
136 | my $info = $self->result_source->column_info($col) or | ||||
137 | $self->throw_exception("No column info for $col"); | ||||
138 | |||||
139 | return $value unless exists $info->{_inflate_info}; | ||||
140 | |||||
141 | return ( | ||||
142 | $info->{_inflate_info}{deflate} | ||||
143 | || | ||||
144 | $self->throw_exception("No deflator found for '$col'") | ||||
145 | )->($value, $self); | ||||
146 | } | ||||
147 | |||||
148 | =head2 get_inflated_column | ||||
149 | |||||
150 | my $val = $obj->get_inflated_column($col); | ||||
151 | |||||
152 | Fetch a column value in its inflated state. This is directly | ||||
153 | analogous to L<DBIx::Class::Row/get_column> in that it only fetches a | ||||
154 | column already retrieved from the database, and then inflates it. | ||||
155 | Throws an exception if the column requested is not an inflated column. | ||||
156 | |||||
157 | =cut | ||||
158 | |||||
159 | sub get_inflated_column { | ||||
160 | my ($self, $col) = @_; | ||||
161 | |||||
162 | $self->throw_exception("$col is not an inflated column") | ||||
163 | unless exists $self->result_source->column_info($col)->{_inflate_info}; | ||||
164 | |||||
165 | # we take care of keeping things in sync | ||||
166 | return $self->{_inflated_column}{$col} | ||||
167 | if exists $self->{_inflated_column}{$col}; | ||||
168 | |||||
169 | my $val = $self->get_column($col); | ||||
170 | |||||
171 | return $self->{_inflated_column}{$col} = $self->_inflated_column($col, $val); | ||||
172 | } | ||||
173 | |||||
174 | =head2 set_inflated_column | ||||
175 | |||||
176 | my $copy = $obj->set_inflated_column($col => $val); | ||||
177 | |||||
178 | Sets a column value from an inflated value. This is directly | ||||
179 | analogous to L<DBIx::Class::Row/set_column>. | ||||
180 | |||||
181 | =cut | ||||
182 | |||||
183 | sub set_inflated_column { | ||||
184 | my ($self, $col, $value) = @_; | ||||
185 | |||||
186 | # pass through deflated stuff | ||||
187 | if (! length ref $value or is_literal_value($value)) { | ||||
188 | $self->set_column($col, $value); | ||||
189 | delete $self->{_inflated_column}{$col}; | ||||
190 | } | ||||
191 | # need to call set_column with the deflate cycle so that | ||||
192 | # relationship caches are nuked if any | ||||
193 | # also does the compare-for-dirtyness and change tracking dance | ||||
194 | else { | ||||
195 | $self->set_column($col, $self->_deflated_column($col, $value)); | ||||
196 | $self->{_inflated_column}{$col} = $value; | ||||
197 | } | ||||
198 | |||||
199 | return $value; | ||||
200 | } | ||||
201 | |||||
202 | =head2 store_inflated_column | ||||
203 | |||||
204 | my $copy = $obj->store_inflated_column($col => $val); | ||||
205 | |||||
206 | Sets a column value from an inflated value without marking the column | ||||
207 | as dirty. This is directly analogous to L<DBIx::Class::Row/store_column>. | ||||
208 | |||||
209 | =cut | ||||
210 | |||||
211 | sub store_inflated_column { | ||||
212 | my ($self, $col, $value) = @_; | ||||
213 | |||||
214 | if (! length ref $value or is_literal_value($value)) { | ||||
215 | delete $self->{_inflated_column}{$col}; | ||||
216 | $self->store_column($col => $value); | ||||
217 | } | ||||
218 | else { | ||||
219 | delete $self->{_column_data}{$col}; | ||||
220 | $self->{_inflated_column}{$col} = $value; | ||||
221 | } | ||||
222 | |||||
223 | return $value; | ||||
224 | } | ||||
225 | |||||
226 | =head1 SEE ALSO | ||||
227 | |||||
228 | =over 4 | ||||
229 | |||||
230 | =item L<DBIx::Class::Core> - This component is loaded as part of the | ||||
231 | C<core> L<DBIx::Class> components; generally there is no need to | ||||
232 | load it directly | ||||
233 | |||||
234 | =back | ||||
235 | |||||
236 | =head1 FURTHER QUESTIONS? | ||||
237 | |||||
238 | Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>. | ||||
239 | |||||
240 | =head1 COPYRIGHT AND LICENSE | ||||
241 | |||||
242 | This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE> | ||||
243 | by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can | ||||
244 | redistribute it and/or modify it under the same terms as the | ||||
245 | L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>. | ||||
246 | |||||
247 | =cut | ||||
248 | |||||
249 | 1 | 2µs | 1 | 47µs | 1; # spent 47µs making 1 call to B::Hooks::EndOfScope::XS::__ANON__ |