Profile of DBIx/Class/InflateColumn.pm

← Index
NYTProf Performance Profile «block view•line view•sub view»
For xt/tapper-mcp-scheduler-with-db-longrun.t
Run on Tue May 22 17:18:39 2012
Reported on Tue May 22 17:23:01 2012

Filename | /2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/InflateColumn.pm
Statements | Executed 4468 statements in 16.1ms

Subroutines
Calls | P | F | Exclusive Time | Inclusive Time | Subroutine
--- | --- | --- | --- | --- | ---
441 | 2 | 2 | 9.75ms | 142ms | DBIx::Class::InflateColumn::::set_inflated_columnDBIx::Class::InflateColumn::set_inflated_column
588 | 2 | 2 | 4.86ms | 73.8ms | DBIx::Class::InflateColumn::::_deflated_columnDBIx::Class::InflateColumn::_deflated_column
38 | 5 | 5 | 1.21ms | 6.06ms | DBIx::Class::InflateColumn::::inflate_columnDBIx::Class::InflateColumn::inflate_column
1 | 1 | 1 | 16µs | 21µs | DBIx::Class::InflateColumn::::BEGIN@3DBIx::Class::InflateColumn::BEGIN@3
1 | 1 | 1 | 9µs | 26µs | DBIx::Class::InflateColumn::::BEGIN@4DBIx::Class::InflateColumn::BEGIN@4
1 | 1 | 1 | 8µs | 5.63ms | DBIx::Class::InflateColumn::::BEGIN@6DBIx::Class::InflateColumn::BEGIN@6
0 | 0 | 0 | 0s | 0s | DBIx::Class::InflateColumn::::_inflated_columnDBIx::Class::InflateColumn::_inflated_column
0 | 0 | 0 | 0s | 0s | DBIx::Class::InflateColumn::::get_inflated_columnDBIx::Class::InflateColumn::get_inflated_column
0 | 0 | 0 | 0s | 0s | DBIx::Class::InflateColumn::::store_inflated_columnDBIx::Class::InflateColumn::store_inflated_column

Call graph for these subroutines as a Graphviz dot language file.

Line | State ments | Time on line | Calls | Time in subs | Code
--- | --- | --- | --- | --- | ---
1 |  |  |  |  | package DBIx::Class::InflateColumn;
2 |  |  |  |  |
3 | 3 | 21µs | 2 | 25µs | # spent 21µs (16+4) within DBIx::Class::InflateColumn::BEGIN@3 which was called: # once (16µs+4µs) by Class::C3::Componentised::ensure_class_loaded at line 3 use strict; # spent 21µs making 1 call to DBIx::Class::InflateColumn::BEGIN@3 # spent 4µs making 1 call to strict::import
4 | 3 | 23µs | 2 | 42µs | # spent 26µs (9+16) within DBIx::Class::InflateColumn::BEGIN@4 which was called: # once (9µs+16µs) by Class::C3::Componentised::ensure_class_loaded at line 4 use warnings; # spent 26µs making 1 call to DBIx::Class::InflateColumn::BEGIN@4 # spent 16µs making 1 call to warnings::import
5 |  |  |  |  |
6 | 3 | 423µs | 2 | 11.2ms | # spent 5.63ms (8µs+5.62) within DBIx::Class::InflateColumn::BEGIN@6 which was called: # once (8µs+5.62ms) by Class::C3::Componentised::ensure_class_loaded at line 6 use base qw/DBIx::Class::Row/; # spent 5.63ms making 1 call to DBIx::Class::InflateColumn::BEGIN@6 # spent 5.62ms making 1 call to base::import
7 |  |  |  |  |
8 |  |  |  |  | =head1 NAME
9 |  |  |  |  |
10 |  |  |  |  | DBIx::Class::InflateColumn - Automatically create references from column data
11 |  |  |  |  |
12 |  |  |  |  | =head1 SYNOPSIS
13 |  |  |  |  |
14 |  |  |  |  | # In your table classes
15 |  |  |  |  | __PACKAGE__->inflate_column('column_name', {
16 |  |  |  |  | inflate => sub { ... },
17 |  |  |  |  | deflate => sub { ... },
18 |  |  |  |  | });
19 |  |  |  |  |
20 |  |  |  |  | =head1 DESCRIPTION
21 |  |  |  |  |
22 |  |  |  |  | This component translates column data into references, i.e. "inflating"
23 |  |  |  |  | the column data. It also "deflates" references into an appropriate format
24 |  |  |  |  | for the database.
25 |  |  |  |  |
26 |  |  |  |  | It can be used, for example, to automatically convert to and from
27 |  |  |  |  | L<DateTime> objects for your date and time fields. There's a
28 |  |  |  |  | convenience component to actually do that though, try
29 |  |  |  |  | L<DBIx::Class::InflateColumn::DateTime>.
30 |  |  |  |  |
31 |  |  |  |  | It will handle all types of references except scalar references. It
32 |  |  |  |  | will not handle scalar values, these are ignored and thus passed
33 |  |  |  |  | through to L<SQL::Abstract>. This is to allow setting raw values to
34 |  |  |  |  | "just work". Scalar references are passed through to the database to
35 |  |  |  |  | deal with, to allow such settings as C< \'year + 1'> and C< \'DEFAULT' >
36 |  |  |  |  | to work.
37 |  |  |  |  |
38 |  |  |  |  | If you want to filter plain scalar values and replace them with
39 |  |  |  |  | something else, see L<DBIx::Class::FilterColumn>.
40 |  |  |  |  |
41 |  |  |  |  | =head1 METHODS
42 |  |  |  |  |
43 |  |  |  |  | =head2 inflate_column
44 |  |  |  |  |
45 |  |  |  |  | Instruct L<DBIx::Class> to inflate the given column.
46 |  |  |  |  |
47 |  |  |  |  | In addition to the column name, you must provide C<inflate> and
48 |  |  |  |  | C<deflate> methods. The C<inflate> method is called when you access
49 |  |  |  |  | the field, while the C<deflate> method is called when the field needs
50 |  |  |  |  | to used by the database.
51 |  |  |  |  |
52 |  |  |  |  | For example, if you have a table C<events> with a timestamp field
53 |  |  |  |  | named C<insert_time>, you could inflate the column in the
54 |  |  |  |  | corresponding table class using something like:
55 |  |  |  |  |
56 |  |  |  |  | __PACKAGE__->inflate_column('insert_time', {
57 |  |  |  |  | inflate => sub { DateTime::Format::Pg->parse_datetime(shift); },
58 |  |  |  |  | deflate => sub { DateTime::Format::Pg->format_datetime(shift); },
59 |  |  |  |  | });
60 |  |  |  |  |
61 |  |  |  |  | (Replace L<DateTime::Format::Pg> with the appropriate module for your
62 |  |  |  |  | database, or consider L<DateTime::Format::DBI>.)
63 |  |  |  |  |
64 |  |  |  |  | The coderefs you set for inflate and deflate are called with two parameters,
65 |  |  |  |  | the first is the value of the column to be inflated/deflated, the second is the
66 |  |  |  |  | row object itself. Thus you can call C<< ->result_source->schema->storage->dbh >> in your inflate/defalte subs, to feed to L<DateTime::Format::DBI>.
67 |  |  |  |  |
68 |  |  |  |  | In this example, calls to an event's C<insert_time> accessor return a
69 |  |  |  |  | L<DateTime> object. This L<DateTime> object is later "deflated" when
70 |  |  |  |  | used in the database layer.
71 |  |  |  |  |
72 |  |  |  |  | =cut
73 |  |  |  |  |
74 |  |  |  |  | # spent 6.06ms (1.21+4.85) within DBIx::Class::InflateColumn::inflate_column which was called 38 times, avg 159µs/call: # 34 times (1.10ms+4.19ms) by DBIx::Class::InflateColumn::DateTime::register_column at line 189 of DBIx/Class/InflateColumn/DateTime.pm, avg 156µs/call # once (74µs+205µs) by DBIx::Class::InflateColumn::Object::Enum::register_column at line 114 of DBIx/Class/InflateColumn/Object/Enum.pm # once (11µs+178µs) by Class::C3::Componentised::ensure_class_loaded at line 28 of Tapper/Schema/TestrunDB/Result/Message.pm # once (11µs+175µs) by Class::C3::Componentised::ensure_class_loaded at line 27 of Tapper/Schema/TestrunDB/Result/State.pm # once (11µs+103µs) by Class::C3::Componentised::ensure_class_loaded at line 30 of Tapper/Schema/ReportsDB/Result/NotificationEvent.pm sub inflate_column {
75 | 342 | 1.38ms |  |  | my ($self, $col, $attrs) = @_;
76 |  |  |  |  |
77 |  |  | 38 | 850µs | my $colinfo = $self->column_info($col); # spent 850µs making 38 calls to DBIx::Class::ResultSourceProxy::column_info, avg 22µs/call
78 |  |  |  |  |
79 |  |  | 38 | 225µs | $self->throw_exception("InflateColumn does not work with FilterColumn") # spent 225µs making 38 calls to UNIVERSAL::isa, avg 6µs/call
80 |  |  |  |  | if $self->isa('DBIx::Class::FilterColumn') &&
81 |  |  |  |  | defined $colinfo->{_filter_info};
82 |  |  |  |  |
83 |  |  | 38 | 686µs | $self->throw_exception("No such column $col to inflate") # spent 686µs making 38 calls to DBIx::Class::ResultSourceProxy::has_column, avg 18µs/call
84 |  |  |  |  | unless $self->has_column($col);
85 |  |  |  |  | $self->throw_exception("inflate_column needs attr hashref")
86 |  |  |  |  | unless ref $attrs eq 'HASH';
87 |  |  |  |  | $colinfo->{_inflate_info} = $attrs;
88 |  |  |  |  | my $acc = $colinfo->{accessor};
89 |  |  | 38 | 3.09ms | $self->mk_group_accessors('inflated_column' => [ (defined $acc ? $acc : $col), $col]); # spent 3.09ms making 38 calls to Class::Accessor::Grouped::mk_group_accessors, avg 81µs/call
90 |  |  |  |  | return 1;
91 |  |  |  |  | }
92 |  |  |  |  |
93 |  |  |  |  | sub _inflated_column {
94 |  |  |  |  | my ($self, $col, $value) = @_;
95 |  |  |  |  | return $value unless defined $value; # NULL is NULL is NULL
96 |  |  |  |  | my $info = $self->column_info($col)
97 |  |  |  |  | or $self->throw_exception("No column info for $col");
98 |  |  |  |  | return $value unless exists $info->{_inflate_info};
99 |  |  |  |  | my $inflate = $info->{_inflate_info}{inflate};
100 |  |  |  |  | $self->throw_exception("No inflator for $col") unless defined $inflate;
101 |  |  |  |  | return $inflate->($value, $self);
102 |  |  |  |  | }
103 |  |  |  |  |
104 |  |  |  |  | # spent 73.8ms (4.86+68.9) within DBIx::Class::InflateColumn::_deflated_column which was called 588 times, avg 125µs/call: # 441 times (2.75ms+0s) by DBIx::Class::InflateColumn::set_inflated_column at line 152, avg 6µs/call # 147 times (2.11ms+68.9ms) by DBIx::Class::Row::get_columns at line 674 of DBIx/Class/Row.pm, avg 483µs/call sub _deflated_column {
105 | 1911 | 5.87ms |  |  | my ($self, $col, $value) = @_;
106 |  |  |  |  | # return $value unless ref $value && blessed($value); # If it's not an object, don't touch it
107 |  |  |  |  | ## Leave scalar refs (ala SQL::Abstract literal SQL), untouched, deflate all other refs
108 |  |  |  |  | return $value unless (ref $value && ref($value) ne 'SCALAR');
109 |  |  | 147 | 6.43ms | my $info = $self->column_info($col) or # spent 6.43ms making 147 calls to DBIx::Class::ResultSourceProxy::column_info, avg 44µs/call
110 |  |  |  |  | $self->throw_exception("No column info for $col");
111 |  |  |  |  | return $value unless exists $info->{_inflate_info};
112 |  |  |  |  | my $deflate = $info->{_inflate_info}{deflate};
113 |  |  |  |  | $self->throw_exception("No deflator for $col") unless defined $deflate;
114 |  |  | 147 | 62.5ms | return $deflate->($value, $self); # spent 62.5ms making 147 calls to DBIx::Class::InflateColumn::DateTime::__ANON__[DBIx/Class/InflateColumn/DateTime.pm:187], avg 425µs/call
115 |  |  |  |  | }
116 |  |  |  |  |
117 |  |  |  |  | =head2 get_inflated_column
118 |  |  |  |  |
119 |  |  |  |  | my $val = $obj->get_inflated_column($col);
120 |  |  |  |  |
121 |  |  |  |  | Fetch a column value in its inflated state. This is directly
122 |  |  |  |  | analogous to L<DBIx::Class::Row/get_column> in that it only fetches a
123 |  |  |  |  | column already retrieved from the database, and then inflates it.
124 |  |  |  |  | Throws an exception if the column requested is not an inflated column.
125 |  |  |  |  |
126 |  |  |  |  | =cut
127 |  |  |  |  |
128 |  |  |  |  | sub get_inflated_column {
129 |  |  |  |  | my ($self, $col) = @_;
130 |  |  |  |  | $self->throw_exception("$col is not an inflated column")
131 |  |  |  |  | unless exists $self->column_info($col)->{_inflate_info};
132 |  |  |  |  | return $self->{_inflated_column}{$col}
133 |  |  |  |  | if exists $self->{_inflated_column}{$col};
134 |  |  |  |  |
135 |  |  |  |  | my $val = $self->get_column($col);
136 |  |  |  |  | return $val if ref $val eq 'SCALAR'; #that would be a not-yet-reloaded sclarref update
137 |  |  |  |  |
138 |  |  |  |  | return $self->{_inflated_column}{$col} = $self->_inflated_column($col, $val);
139 |  |  |  |  | }
140 |  |  |  |  |
141 |  |  |  |  | =head2 set_inflated_column
142 |  |  |  |  |
143 |  |  |  |  | my $copy = $obj->set_inflated_column($col => $val);
144 |  |  |  |  |
145 |  |  |  |  | Sets a column value from an inflated value. This is directly
146 |  |  |  |  | analogous to L<DBIx::Class::Row/set_column>.
147 |  |  |  |  |
148 |  |  |  |  | =cut
149 |  |  |  |  |
150 |  |  |  |  | # spent 142ms (9.75+133) within DBIx::Class::InflateColumn::set_inflated_column which was called 441 times, avg 323µs/call: # 294 times (6.39ms+95.8ms) by Tapper::Schema::TestrunDB::Result::TestrunScheduling::status at line 2 of (eval 307)[Class/Accessor/Grouped.pm:807], avg 348µs/call # 147 times (3.36ms+36.7ms) by Tapper::Schema::TestrunDB::Result::Testrun::starttime_testrun at line 2 of (eval 382)[Class/Accessor/Grouped.pm:807], avg 273µs/call sub set_inflated_column {
151 | 1764 | 7.64ms |  |  | my ($self, $col, $inflated) = @_;
152 |  |  | 882 | 133ms | $self->set_column($col, $self->_deflated_column($col, $inflated)); # spent 130ms making 441 calls to DBIx::Class::Row::set_column, avg 294µs/call # spent 2.75ms making 441 calls to DBIx::Class::InflateColumn::_deflated_column, avg 6µs/call
153 |  |  |  |  | # if (blessed $inflated) {
154 | 441 | 749µs |  |  | if (ref $inflated && ref($inflated) ne 'SCALAR') {
155 |  |  |  |  | $self->{_inflated_column}{$col} = $inflated;
156 |  |  |  |  | } else {
157 |  |  |  |  | delete $self->{_inflated_column}{$col};
158 |  |  |  |  | }
159 |  |  |  |  | return $inflated;
160 |  |  |  |  | }
161 |  |  |  |  |
162 |  |  |  |  | =head2 store_inflated_column
163 |  |  |  |  |
164 |  |  |  |  | my $copy = $obj->store_inflated_column($col => $val);
165 |  |  |  |  |
166 |  |  |  |  | Sets a column value from an inflated value without marking the column
167 |  |  |  |  | as dirty. This is directly analogous to L<DBIx::Class::Row/store_column>.
168 |  |  |  |  |
169 |  |  |  |  | =cut
170 |  |  |  |  |
171 |  |  |  |  | sub store_inflated_column {
172 |  |  |  |  | my ($self, $col, $inflated) = @_;
173 |  |  |  |  | # unless (blessed $inflated) {
174 |  |  |  |  | unless (ref $inflated && ref($inflated) ne 'SCALAR') {
175 |  |  |  |  | delete $self->{_inflated_column}{$col};
176 |  |  |  |  | $self->store_column($col => $inflated);
177 |  |  |  |  | return $inflated;
178 |  |  |  |  | }
179 |  |  |  |  | delete $self->{_column_data}{$col};
180 |  |  |  |  | return $self->{_inflated_column}{$col} = $inflated;
181 |  |  |  |  | }
182 |  |  |  |  |
183 |  |  |  |  | =head1 SEE ALSO
184 |  |  |  |  |
185 |  |  |  |  | =over 4
186 |  |  |  |  |
187 |  |  |  |  | =item L<DBIx::Class::Core> - This component is loaded as part of the
188 |  |  |  |  | C<core> L<DBIx::Class> components; generally there is no need to
189 |  |  |  |  | load it directly
190 |  |  |  |  |
191 |  |  |  |  | =back
192 |  |  |  |  |
193 |  |  |  |  | =head1 AUTHOR
194 |  |  |  |  |
195 |  |  |  |  | Matt S. Trout <mst@shadowcatsystems.co.uk>
196 |  |  |  |  |
197 |  |  |  |  | =head1 CONTRIBUTORS
198 |  |  |  |  |
199 |  |  |  |  | Daniel Westermann-Clark <danieltwc@cpan.org> (documentation)
200 |  |  |  |  |
201 |  |  |  |  | Jess Robinson <cpan@desert-island.demon.co.uk>
202 |  |  |  |  |
203 |  |  |  |  | =head1 LICENSE
204 |  |  |  |  |
205 |  |  |  |  | You may distribute this code under the same terms as Perl itself.
206 |  |  |  |  |
207 |  |  |  |  | =cut
208 |  |  |  |  |
209 | 1 | 3µs |  |  | 1;