| 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 |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 441 | 2 | 2 | 9.75ms | 142ms | DBIx::Class::InflateColumn::set_inflated_column |
| 588 | 2 | 2 | 4.86ms | 73.8ms | DBIx::Class::InflateColumn::_deflated_column |
| 38 | 5 | 5 | 1.21ms | 6.06ms | DBIx::Class::InflateColumn::inflate_column |
| 1 | 1 | 1 | 16µs | 21µs | DBIx::Class::InflateColumn::BEGIN@3 |
| 1 | 1 | 1 | 9µs | 26µs | DBIx::Class::InflateColumn::BEGIN@4 |
| 1 | 1 | 1 | 8µs | 5.63ms | DBIx::Class::InflateColumn::BEGIN@6 |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::InflateColumn::_inflated_column |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::InflateColumn::get_inflated_column |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::InflateColumn::store_inflated_column |
| 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 # 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 # 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 # 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 | ||||
| 75 | 38 | 51µs | my ($self, $col, $attrs) = @_; | ||
| 76 | |||||
| 77 | 38 | 268µs | 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 | 553µs | 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 | 245µs | 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 | 38 | 28µs | $self->throw_exception("inflate_column needs attr hashref") | ||
| 86 | unless ref $attrs eq 'HASH'; | ||||
| 87 | 38 | 32µs | $colinfo->{_inflate_info} = $attrs; | ||
| 88 | 38 | 20µs | my $acc = $colinfo->{accessor}; | ||
| 89 | 38 | 87µs | 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 | 38 | 98µs | 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 | ||||
| 105 | 588 | 1.04ms | 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 | 588 | 3.18ms | return $value unless (ref $value && ref($value) ne 'SCALAR'); | ||
| 109 | 147 | 443µs | 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 | 147 | 114µs | return $value unless exists $info->{_inflate_info}; | ||
| 112 | 147 | 192µs | my $deflate = $info->{_inflate_info}{deflate}; | ||
| 113 | 147 | 46µs | $self->throw_exception("No deflator for $col") unless defined $deflate; | ||
| 114 | 147 | 853µs | 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 | ||||
| 151 | 441 | 921µs | my ($self, $col, $inflated) = @_; | ||
| 152 | 441 | 4.05ms | 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 | 477µs | if (ref $inflated && ref($inflated) ne 'SCALAR') { | ||
| 155 | $self->{_inflated_column}{$col} = $inflated; | ||||
| 156 | } else { | ||||
| 157 | 441 | 749µs | delete $self->{_inflated_column}{$col}; | ||
| 158 | } | ||||
| 159 | 441 | 2.19ms | 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; |