| Filename | /2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/ResultSource.pm |
| Statements | Executed 410874 statements in 1.31s |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 8975 | 4 | 3 | 223ms | 309ms | DBIx::Class::ResultSource::columns_info |
| 5332 | 3 | 3 | 154ms | 229ms | DBIx::Class::ResultSource::_resolve_condition |
| 5708 | 3 | 3 | 117ms | 1.28s | DBIx::Class::ResultSource::resultset |
| 17444 | 7 | 5 | 106ms | 106ms | DBIx::Class::ResultSource::columns |
| 10410 | 10 | 4 | 101ms | 301ms | DBIx::Class::ResultSource::storage |
| 4155 | 6 | 4 | 66.6ms | 333ms | DBIx::Class::ResultSource::related_source |
| 23459 | 15 | 8 | 65.8ms | 65.8ms | DBIx::Class::ResultSource::schema |
| 14007 | 10 | 6 | 58.9ms | 58.9ms | DBIx::Class::ResultSource::relationship_info |
| 5708 | 1 | 1 | 57.5ms | 344ms | DBIx::Class::ResultSource::__ANON__[:1038] |
| 10914 | 3 | 1 | 24.6ms | 24.6ms | DBIx::Class::ResultSource::CORE:subst (opcode) |
| 1528 | 3 | 2 | 23.7ms | 28.9ms | DBIx::Class::ResultSource::column_info |
| 4356 | 3 | 2 | 21.5ms | 21.5ms | DBIx::Class::ResultSource::has_column |
| 4155 | 1 | 1 | 19.1ms | 31.9ms | DBIx::Class::ResultSource::__ANON__[:1853] |
| 1690 | 1 | 1 | 16.4ms | 21.7ms | DBIx::Class::ResultSource::_pri_cols |
| 4302 | 2 | 2 | 15.3ms | 15.3ms | DBIx::Class::ResultSource::has_relationship |
| 3166 | 4 | 4 | 14.8ms | 14.8ms | DBIx::Class::ResultSource::primary_columns |
| 714 | 3 | 1 | 7.75ms | 10.8ms | DBIx::Class::ResultSource::unique_constraint_columns |
| 972 | 3 | 3 | 7.31ms | 7.31ms | DBIx::Class::ResultSource::relationships |
| 294 | 2 | 1 | 7.18ms | 25.3ms | DBIx::Class::ResultSource::_resolve_join |
| 188 | 4 | 3 | 4.14ms | 4.14ms | DBIx::Class::ResultSource::new |
| 60 | 1 | 1 | 3.69ms | 25.0ms | DBIx::Class::ResultSource::reverse_relationship_info |
| 809 | 4 | 2 | 3.56ms | 3.65ms | DBIx::Class::ResultSource::unique_constraints |
| 37 | 1 | 1 | 2.65ms | 3.16ms | DBIx::Class::ResultSource::add_columns |
| 60 | 1 | 1 | 959µs | 1.17ms | DBIx::Class::ResultSource::add_relationship |
| 116 | 2 | 1 | 808µs | 1.24ms | DBIx::Class::ResultSource::__strip_relcond |
| 37 | 1 | 1 | 731µs | 2.17ms | DBIx::Class::ResultSource::default_sqlt_deploy_hook |
| 154 | 3 | 2 | 684µs | 765µs | DBIx::Class::ResultSource::_compare_relationship_keys |
| 210 | 1 | 1 | 614µs | 939µs | DBIx::Class::ResultSource::__ANON__[:1397] |
| 38 | 2 | 2 | 598µs | 893µs | DBIx::Class::ResultSource::add_unique_constraint |
| 210 | 1 | 1 | 557µs | 10.7ms | DBIx::Class::ResultSource::__ANON__[:1394] |
| 1 | 1 | 1 | 553µs | 1.35ms | DBIx::Class::ResultSource::BEGIN@7 |
| 352 | 2 | 1 | 539µs | 539µs | DBIx::Class::ResultSource::CORE:match (opcode) |
| 35 | 1 | 1 | 463µs | 1.56ms | DBIx::Class::ResultSource::set_primary_key |
| 22 | 1 | 1 | 433µs | 688µs | DBIx::Class::ResultSource::unique_constraint_names |
| 37 | 2 | 1 | 218µs | 3.27ms | DBIx::Class::ResultSource::_invoke_sqlt_deploy_hook |
| 60 | 1 | 1 | 197µs | 290µs | DBIx::Class::ResultSource::__ANON__[:1378] |
| 60 | 1 | 1 | 175µs | 3.12ms | DBIx::Class::ResultSource::__ANON__[:1381] |
| 57 | 1 | 1 | 124µs | 124µs | DBIx::Class::ResultSource::DESTROY |
| 308 | 1 | 1 | 81µs | 81µs | DBIx::Class::ResultSource::CORE:sort (opcode) |
| 1 | 1 | 1 | 16µs | 21µs | DBIx::Class::ResultSource::BEGIN@3 |
| 1 | 1 | 1 | 11µs | 31µs | DBIx::Class::ResultSource::BEGIN@12 |
| 1 | 1 | 1 | 10µs | 27µs | DBIx::Class::ResultSource::BEGIN@4 |
| 1 | 1 | 1 | 10µs | 38µs | DBIx::Class::ResultSource::BEGIN@13 |
| 1 | 1 | 1 | 9µs | 81µs | DBIx::Class::ResultSource::BEGIN@10 |
| 1 | 1 | 1 | 8µs | 79µs | DBIx::Class::ResultSource::BEGIN@16 |
| 1 | 1 | 1 | 7µs | 206µs | DBIx::Class::ResultSource::BEGIN@14 |
| 1 | 1 | 1 | 7µs | 44µs | DBIx::Class::ResultSource::BEGIN@11 |
| 1 | 1 | 1 | 5µs | 5µs | DBIx::Class::ResultSource::END |
| 1 | 1 | 1 | 4µs | 4µs | DBIx::Class::ResultSource::BEGIN@9 |
| 1 | 1 | 1 | 4µs | 4µs | DBIx::Class::ResultSource::BEGIN@6 |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::STORABLE_freeze |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::STORABLE_thaw |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::__ANON__[:1271] |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::__ANON__[:1277] |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::__ANON__[:1522] |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::__ANON__[:1614] |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::__ANON__[:386] |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::__ANON__[:404] |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::__ANON__[:458] |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::__ANON__[:464] |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::__ANON__[:482] |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::__ANON__[:764] |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::_pk_depends_on |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::_resolve_prefetch |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::add_column |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::add_unique_constraints |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::compare_relationship_keys |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::from |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::handle |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::name_unique_constraint |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::pk_depends_on |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::related_class |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::remove_column |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::remove_columns |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::resolve_condition |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::sequence |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::throw_exception |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package DBIx::Class::ResultSource; | ||||
| 2 | |||||
| 3 | 3 | 21µs | 2 | 26µs | # spent 21µs (16+5) within DBIx::Class::ResultSource::BEGIN@3 which was called:
# once (16µs+5µs) by Class::C3::Componentised::ensure_class_loaded at line 3 # spent 21µs making 1 call to DBIx::Class::ResultSource::BEGIN@3
# spent 5µs making 1 call to strict::import |
| 4 | 3 | 21µs | 2 | 45µs | # spent 27µs (10+17) within DBIx::Class::ResultSource::BEGIN@4 which was called:
# once (10µs+17µs) by Class::C3::Componentised::ensure_class_loaded at line 4 # spent 27µs making 1 call to DBIx::Class::ResultSource::BEGIN@4
# spent 17µs making 1 call to warnings::import |
| 5 | |||||
| 6 | 3 | 16µs | 1 | 4µs | # spent 4µs within DBIx::Class::ResultSource::BEGIN@6 which was called:
# once (4µs+0s) by Class::C3::Componentised::ensure_class_loaded at line 6 # spent 4µs making 1 call to DBIx::Class::ResultSource::BEGIN@6 |
| 7 | 3 | 83µs | 1 | 1.35ms | # spent 1.35ms (553µs+797µs) within DBIx::Class::ResultSource::BEGIN@7 which was called:
# once (553µs+797µs) by Class::C3::Componentised::ensure_class_loaded at line 7 # spent 1.35ms making 1 call to DBIx::Class::ResultSource::BEGIN@7 |
| 8 | |||||
| 9 | 3 | 18µs | 1 | 4µs | # spent 4µs within DBIx::Class::ResultSource::BEGIN@9 which was called:
# once (4µs+0s) by Class::C3::Componentised::ensure_class_loaded at line 9 # spent 4µs making 1 call to DBIx::Class::ResultSource::BEGIN@9 |
| 10 | 3 | 21µs | 2 | 154µs | # spent 81µs (9+72) within DBIx::Class::ResultSource::BEGIN@10 which was called:
# once (9µs+72µs) by Class::C3::Componentised::ensure_class_loaded at line 10 # spent 81µs making 1 call to DBIx::Class::ResultSource::BEGIN@10
# spent 72µs making 1 call to DBIx::Class::Carp::import |
| 11 | 3 | 20µs | 2 | 80µs | # spent 44µs (7+37) within DBIx::Class::ResultSource::BEGIN@11 which was called:
# once (7µs+37µs) by Class::C3::Componentised::ensure_class_loaded at line 11 # spent 44µs making 1 call to DBIx::Class::ResultSource::BEGIN@11
# spent 37µs making 1 call to Exporter::import |
| 12 | 3 | 25µs | 2 | 52µs | # spent 31µs (11+20) within DBIx::Class::ResultSource::BEGIN@12 which was called:
# once (11µs+20µs) by Class::C3::Componentised::ensure_class_loaded at line 12 # spent 31µs making 1 call to DBIx::Class::ResultSource::BEGIN@12
# spent 20µs making 1 call to Exporter::import |
| 13 | 3 | 21µs | 2 | 67µs | # spent 38µs (10+29) within DBIx::Class::ResultSource::BEGIN@13 which was called:
# once (10µs+29µs) by Class::C3::Componentised::ensure_class_loaded at line 13 # spent 38µs making 1 call to DBIx::Class::ResultSource::BEGIN@13
# spent 29µs making 1 call to Exporter::import |
| 14 | 3 | 21µs | 2 | 404µs | # spent 206µs (7+199) within DBIx::Class::ResultSource::BEGIN@14 which was called:
# once (7µs+199µs) by Class::C3::Componentised::ensure_class_loaded at line 14 # spent 206µs making 1 call to DBIx::Class::ResultSource::BEGIN@14
# spent 199µs making 1 call to namespace::clean::import |
| 15 | |||||
| 16 | 3 | 4.42ms | 2 | 149µs | # spent 79µs (8+71) within DBIx::Class::ResultSource::BEGIN@16 which was called:
# once (8µs+71µs) by Class::C3::Componentised::ensure_class_loaded at line 16 # spent 79µs making 1 call to DBIx::Class::ResultSource::BEGIN@16
# spent 71µs making 1 call to base::import |
| 17 | |||||
| 18 | 1 | 17µs | 1 | 574µs | __PACKAGE__->mk_group_accessors(simple => qw/ # spent 574µs making 1 call to Class::Accessor::Grouped::mk_group_accessors |
| 19 | source_name name source_info | ||||
| 20 | _ordered_columns _columns _primaries _unique_constraints | ||||
| 21 | _relationships resultset_attributes | ||||
| 22 | column_info_from_storage | ||||
| 23 | /); | ||||
| 24 | |||||
| 25 | 1 | 2µs | 1 | 289µs | __PACKAGE__->mk_group_accessors(component_class => qw/ # spent 289µs making 1 call to Class::Accessor::Grouped::mk_group_accessors |
| 26 | resultset_class | ||||
| 27 | result_class | ||||
| 28 | /); | ||||
| 29 | |||||
| 30 | 1 | 5µs | 1 | 203µs | __PACKAGE__->mk_classdata( sqlt_deploy_callback => 'default_sqlt_deploy_hook' ); # spent 203µs making 1 call to DBIx::Class::mk_classdata |
| 31 | |||||
| 32 | =head1 NAME | ||||
| 33 | |||||
| 34 | DBIx::Class::ResultSource - Result source object | ||||
| 35 | |||||
| 36 | =head1 SYNOPSIS | ||||
| 37 | |||||
| 38 | # Create a table based result source, in a result class. | ||||
| 39 | |||||
| 40 | package MyApp::Schema::Result::Artist; | ||||
| 41 | use base qw/DBIx::Class::Core/; | ||||
| 42 | |||||
| 43 | __PACKAGE__->table('artist'); | ||||
| 44 | __PACKAGE__->add_columns(qw/ artistid name /); | ||||
| 45 | __PACKAGE__->set_primary_key('artistid'); | ||||
| 46 | __PACKAGE__->has_many(cds => 'MyApp::Schema::Result::CD'); | ||||
| 47 | |||||
| 48 | 1; | ||||
| 49 | |||||
| 50 | # Create a query (view) based result source, in a result class | ||||
| 51 | package MyApp::Schema::Result::Year2000CDs; | ||||
| 52 | use base qw/DBIx::Class::Core/; | ||||
| 53 | |||||
| 54 | __PACKAGE__->load_components('InflateColumn::DateTime'); | ||||
| 55 | __PACKAGE__->table_class('DBIx::Class::ResultSource::View'); | ||||
| 56 | |||||
| 57 | __PACKAGE__->table('year2000cds'); | ||||
| 58 | __PACKAGE__->result_source_instance->is_virtual(1); | ||||
| 59 | __PACKAGE__->result_source_instance->view_definition( | ||||
| 60 | "SELECT cdid, artist, title FROM cd WHERE year ='2000'" | ||||
| 61 | ); | ||||
| 62 | |||||
| 63 | |||||
| 64 | =head1 DESCRIPTION | ||||
| 65 | |||||
| 66 | A ResultSource is an object that represents a source of data for querying. | ||||
| 67 | |||||
| 68 | This class is a base class for various specialised types of result | ||||
| 69 | sources, for example L<DBIx::Class::ResultSource::Table>. Table is the | ||||
| 70 | default result source type, so one is created for you when defining a | ||||
| 71 | result class as described in the synopsis above. | ||||
| 72 | |||||
| 73 | More specifically, the L<DBIx::Class::Core> base class pulls in the | ||||
| 74 | L<DBIx::Class::ResultSourceProxy::Table> component, which defines | ||||
| 75 | the L<table|DBIx::Class::ResultSourceProxy::Table/table> method. | ||||
| 76 | When called, C<table> creates and stores an instance of | ||||
| 77 | L<DBIx::Class::ResultSoure::Table>. Luckily, to use tables as result | ||||
| 78 | sources, you don't need to remember any of this. | ||||
| 79 | |||||
| 80 | Result sources representing select queries, or views, can also be | ||||
| 81 | created, see L<DBIx::Class::ResultSource::View> for full details. | ||||
| 82 | |||||
| 83 | =head2 Finding result source objects | ||||
| 84 | |||||
| 85 | As mentioned above, a result source instance is created and stored for | ||||
| 86 | you when you define a L<Result Class|DBIx::Class::Manual::Glossary/Result Class>. | ||||
| 87 | |||||
| 88 | You can retrieve the result source at runtime in the following ways: | ||||
| 89 | |||||
| 90 | =over | ||||
| 91 | |||||
| 92 | =item From a Schema object: | ||||
| 93 | |||||
| 94 | $schema->source($source_name); | ||||
| 95 | |||||
| 96 | =item From a Row object: | ||||
| 97 | |||||
| 98 | $row->result_source; | ||||
| 99 | |||||
| 100 | =item From a ResultSet object: | ||||
| 101 | |||||
| 102 | $rs->result_source; | ||||
| 103 | |||||
| 104 | =back | ||||
| 105 | |||||
| 106 | =head1 METHODS | ||||
| 107 | |||||
| 108 | =pod | ||||
| 109 | |||||
| 110 | =cut | ||||
| 111 | |||||
| 112 | # spent 4.14ms within DBIx::Class::ResultSource::new which was called 188 times, avg 22µs/call:
# 90 times (1.78ms+0s) by DBIx::Class::Schema::_register_source at line 1366 of DBIx/Class/Schema.pm, avg 20µs/call
# 55 times (1.55ms+0s) by DBIx::Class::Schema::clone at line 1041 of DBIx/Class/Schema.pm, avg 28µs/call
# 35 times (645µs+0s) by DBIx::Class::ResultSourceProxy::Table::table at line 91 of DBIx/Class/ResultSourceProxy/Table.pm, avg 18µs/call
# 8 times (156µs+0s) by DBIx::Class::ResultSource::View::new at line 28 of mro.pm, avg 20µs/call | ||||
| 113 | 188 | 127µs | my ($class, $attrs) = @_; | ||
| 114 | 188 | 135µs | $class = ref $class if ref $class; | ||
| 115 | |||||
| 116 | 188 | 1.50ms | my $new = bless { %{$attrs || {}} }, $class; | ||
| 117 | 188 | 110µs | $new->{resultset_class} ||= 'DBIx::Class::ResultSet'; | ||
| 118 | 188 | 265µs | $new->{resultset_attributes} = { %{$new->{resultset_attributes} || {}} }; | ||
| 119 | 188 | 454µs | $new->{_ordered_columns} = [ @{$new->{_ordered_columns}||[]}]; | ||
| 120 | 188 | 709µs | $new->{_columns} = { %{$new->{_columns}||{}} }; | ||
| 121 | 188 | 360µs | $new->{_relationships} = { %{$new->{_relationships}||{}} }; | ||
| 122 | 188 | 101µs | $new->{name} ||= "!!NAME NOT SET!!"; | ||
| 123 | 188 | 102µs | $new->{_columns_info_loaded} ||= 0; | ||
| 124 | 188 | 518µs | return $new; | ||
| 125 | } | ||||
| 126 | |||||
| 127 | =pod | ||||
| 128 | |||||
| 129 | =head2 add_columns | ||||
| 130 | |||||
| 131 | =over | ||||
| 132 | |||||
| 133 | =item Arguments: @columns | ||||
| 134 | |||||
| 135 | =item Return value: The ResultSource object | ||||
| 136 | |||||
| 137 | =back | ||||
| 138 | |||||
| 139 | $source->add_columns(qw/col1 col2 col3/); | ||||
| 140 | |||||
| 141 | $source->add_columns('col1' => \%col1_info, 'col2' => \%col2_info, ...); | ||||
| 142 | |||||
| 143 | Adds columns to the result source. If supplied colname => hashref | ||||
| 144 | pairs, uses the hashref as the L</column_info> for that column. Repeated | ||||
| 145 | calls of this method will add more columns, not replace them. | ||||
| 146 | |||||
| 147 | The column names given will be created as accessor methods on your | ||||
| 148 | L<DBIx::Class::Row> objects. You can change the name of the accessor | ||||
| 149 | by supplying an L</accessor> in the column_info hash. | ||||
| 150 | |||||
| 151 | If a column name beginning with a plus sign ('+col1') is provided, the | ||||
| 152 | attributes provided will be merged with any existing attributes for the | ||||
| 153 | column, with the new attributes taking precedence in the case that an | ||||
| 154 | attribute already exists. Using this without a hashref | ||||
| 155 | (C<< $source->add_columns(qw/+col1 +col2/) >>) is legal, but useless -- | ||||
| 156 | it does the same thing it would do without the plus. | ||||
| 157 | |||||
| 158 | The contents of the column_info are not set in stone. The following | ||||
| 159 | keys are currently recognised/used by DBIx::Class: | ||||
| 160 | |||||
| 161 | =over 4 | ||||
| 162 | |||||
| 163 | =item accessor | ||||
| 164 | |||||
| 165 | { accessor => '_name' } | ||||
| 166 | |||||
| 167 | # example use, replace standard accessor with one of your own: | ||||
| 168 | sub name { | ||||
| 169 | my ($self, $value) = @_; | ||||
| 170 | |||||
| 171 | die "Name cannot contain digits!" if($value =~ /\d/); | ||||
| 172 | $self->_name($value); | ||||
| 173 | |||||
| 174 | return $self->_name(); | ||||
| 175 | } | ||||
| 176 | |||||
| 177 | Use this to set the name of the accessor method for this column. If unset, | ||||
| 178 | the name of the column will be used. | ||||
| 179 | |||||
| 180 | =item data_type | ||||
| 181 | |||||
| 182 | { data_type => 'integer' } | ||||
| 183 | |||||
| 184 | This contains the column type. It is automatically filled if you use the | ||||
| 185 | L<SQL::Translator::Producer::DBIx::Class::File> producer, or the | ||||
| 186 | L<DBIx::Class::Schema::Loader> module. | ||||
| 187 | |||||
| 188 | Currently there is no standard set of values for the data_type. Use | ||||
| 189 | whatever your database supports. | ||||
| 190 | |||||
| 191 | =item size | ||||
| 192 | |||||
| 193 | { size => 20 } | ||||
| 194 | |||||
| 195 | The length of your column, if it is a column type that can have a size | ||||
| 196 | restriction. This is currently only used to create tables from your | ||||
| 197 | schema, see L<DBIx::Class::Schema/deploy>. | ||||
| 198 | |||||
| 199 | =item is_nullable | ||||
| 200 | |||||
| 201 | { is_nullable => 1 } | ||||
| 202 | |||||
| 203 | Set this to a true value for a columns that is allowed to contain NULL | ||||
| 204 | values, default is false. This is currently only used to create tables | ||||
| 205 | from your schema, see L<DBIx::Class::Schema/deploy>. | ||||
| 206 | |||||
| 207 | =item is_auto_increment | ||||
| 208 | |||||
| 209 | { is_auto_increment => 1 } | ||||
| 210 | |||||
| 211 | Set this to a true value for a column whose value is somehow | ||||
| 212 | automatically set, defaults to false. This is used to determine which | ||||
| 213 | columns to empty when cloning objects using | ||||
| 214 | L<DBIx::Class::Row/copy>. It is also used by | ||||
| 215 | L<DBIx::Class::Schema/deploy>. | ||||
| 216 | |||||
| 217 | =item is_numeric | ||||
| 218 | |||||
| 219 | { is_numeric => 1 } | ||||
| 220 | |||||
| 221 | Set this to a true or false value (not C<undef>) to explicitly specify | ||||
| 222 | if this column contains numeric data. This controls how set_column | ||||
| 223 | decides whether to consider a column dirty after an update: if | ||||
| 224 | C<is_numeric> is true a numeric comparison C<< != >> will take place | ||||
| 225 | instead of the usual C<eq> | ||||
| 226 | |||||
| 227 | If not specified the storage class will attempt to figure this out on | ||||
| 228 | first access to the column, based on the column C<data_type>. The | ||||
| 229 | result will be cached in this attribute. | ||||
| 230 | |||||
| 231 | =item is_foreign_key | ||||
| 232 | |||||
| 233 | { is_foreign_key => 1 } | ||||
| 234 | |||||
| 235 | Set this to a true value for a column that contains a key from a | ||||
| 236 | foreign table, defaults to false. This is currently only used to | ||||
| 237 | create tables from your schema, see L<DBIx::Class::Schema/deploy>. | ||||
| 238 | |||||
| 239 | =item default_value | ||||
| 240 | |||||
| 241 | { default_value => \'now()' } | ||||
| 242 | |||||
| 243 | Set this to the default value which will be inserted into a column by | ||||
| 244 | the database. Can contain either a value or a function (use a | ||||
| 245 | reference to a scalar e.g. C<\'now()'> if you want a function). This | ||||
| 246 | is currently only used to create tables from your schema, see | ||||
| 247 | L<DBIx::Class::Schema/deploy>. | ||||
| 248 | |||||
| 249 | See the note on L<DBIx::Class::Row/new> for more information about possible | ||||
| 250 | issues related to db-side default values. | ||||
| 251 | |||||
| 252 | =item sequence | ||||
| 253 | |||||
| 254 | { sequence => 'my_table_seq' } | ||||
| 255 | |||||
| 256 | Set this on a primary key column to the name of the sequence used to | ||||
| 257 | generate a new key value. If not specified, L<DBIx::Class::PK::Auto> | ||||
| 258 | will attempt to retrieve the name of the sequence from the database | ||||
| 259 | automatically. | ||||
| 260 | |||||
| 261 | =item retrieve_on_insert | ||||
| 262 | |||||
| 263 | { retrieve_on_insert => 1 } | ||||
| 264 | |||||
| 265 | For every column where this is set to true, DBIC will retrieve the RDBMS-side | ||||
| 266 | value upon a new row insertion (normally only the autoincrement PK is | ||||
| 267 | retrieved on insert). C<INSERT ... RETURNING> is used automatically if | ||||
| 268 | supported by the underlying storage, otherwise an extra SELECT statement is | ||||
| 269 | executed to retrieve the missing data. | ||||
| 270 | |||||
| 271 | =item auto_nextval | ||||
| 272 | |||||
| 273 | { auto_nextval => 1 } | ||||
| 274 | |||||
| 275 | Set this to a true value for a column whose value is retrieved automatically | ||||
| 276 | from a sequence or function (if supported by your Storage driver.) For a | ||||
| 277 | sequence, if you do not use a trigger to get the nextval, you have to set the | ||||
| 278 | L</sequence> value as well. | ||||
| 279 | |||||
| 280 | Also set this for MSSQL columns with the 'uniqueidentifier' | ||||
| 281 | L<data_type|DBIx::Class::ResultSource/data_type> whose values you want to | ||||
| 282 | automatically generate using C<NEWID()>, unless they are a primary key in which | ||||
| 283 | case this will be done anyway. | ||||
| 284 | |||||
| 285 | =item extra | ||||
| 286 | |||||
| 287 | This is used by L<DBIx::Class::Schema/deploy> and L<SQL::Translator> | ||||
| 288 | to add extra non-generic data to the column. For example: C<< extra | ||||
| 289 | => { unsigned => 1} >> is used by the MySQL producer to set an integer | ||||
| 290 | column to unsigned. For more details, see | ||||
| 291 | L<SQL::Translator::Producer::MySQL>. | ||||
| 292 | |||||
| 293 | =back | ||||
| 294 | |||||
| 295 | =head2 add_column | ||||
| 296 | |||||
| 297 | =over | ||||
| 298 | |||||
| 299 | =item Arguments: $colname, \%columninfo? | ||||
| 300 | |||||
| 301 | =item Return value: 1/0 (true/false) | ||||
| 302 | |||||
| 303 | =back | ||||
| 304 | |||||
| 305 | $source->add_column('col' => \%info); | ||||
| 306 | |||||
| 307 | Add a single column and optional column info. Uses the same column | ||||
| 308 | info keys as L</add_columns>. | ||||
| 309 | |||||
| 310 | =cut | ||||
| 311 | |||||
| 312 | # spent 3.16ms (2.65+516µs) within DBIx::Class::ResultSource::add_columns which was called 37 times, avg 85µs/call:
# 37 times (2.65ms+516µs) by DBIx::Class::ResultSourceProxy::add_columns at line 29 of DBIx/Class/ResultSourceProxy.pm, avg 85µs/call | ||||
| 313 | 37 | 116µs | my ($self, @cols) = @_; | ||
| 314 | 37 | 85µs | 13 | 206µs | $self->_ordered_columns(\@cols) unless $self->_ordered_columns; # spent 192µs making 3 calls to DBIx::Class::ResultSource::_ordered_columns, avg 64µs/call
# spent 14µs making 10 calls to DBIx::Class::ResultSource::Table::_ordered_columns, avg 1µs/call |
| 315 | |||||
| 316 | 37 | 10µs | my @added; | ||
| 317 | 37 | 77µs | 13 | 189µs | my $columns = $self->_columns; # spent 179µs making 3 calls to DBIx::Class::ResultSource::_columns, avg 60µs/call
# spent 10µs making 10 calls to DBIx::Class::ResultSource::Table::_columns, avg 1µs/call |
| 318 | 37 | 230µs | while (my $col = shift @cols) { | ||
| 319 | 250 | 94µs | my $column_info = {}; | ||
| 320 | 250 | 513µs | 250 | 92µs | if ($col =~ s/^\+//) { # spent 92µs making 250 calls to DBIx::Class::ResultSource::CORE:subst, avg 367ns/call |
| 321 | $column_info = $self->column_info($col); | ||||
| 322 | } | ||||
| 323 | |||||
| 324 | # If next entry is { ... } use that for the column info, if not | ||||
| 325 | # use an empty hashref | ||||
| 326 | 250 | 241µs | if (ref $cols[0]) { | ||
| 327 | 250 | 64µs | my $new_info = shift(@cols); | ||
| 328 | 250 | 702µs | %$column_info = (%$column_info, %$new_info); | ||
| 329 | } | ||||
| 330 | 250 | 147µs | push(@added, $col) unless exists $columns->{$col}; | ||
| 331 | 250 | 245µs | $columns->{$col} = $column_info; | ||
| 332 | } | ||||
| 333 | 37 | 116µs | 12 | 25µs | push @{ $self->_ordered_columns }, @added; # spent 17µs making 2 calls to DBIx::Class::ResultSource::_ordered_columns, avg 9µs/call
# spent 8µs making 10 calls to DBIx::Class::ResultSource::Table::_ordered_columns, avg 780ns/call |
| 334 | 37 | 125µs | return $self; | ||
| 335 | } | ||||
| 336 | |||||
| 337 | sub add_column { shift->add_columns(@_); } # DO NOT CHANGE THIS TO GLOB | ||||
| 338 | |||||
| 339 | =head2 has_column | ||||
| 340 | |||||
| 341 | =over | ||||
| 342 | |||||
| 343 | =item Arguments: $colname | ||||
| 344 | |||||
| 345 | =item Return value: 1/0 (true/false) | ||||
| 346 | |||||
| 347 | =back | ||||
| 348 | |||||
| 349 | if ($source->has_column($colname)) { ... } | ||||
| 350 | |||||
| 351 | Returns true if the source has a column of this name, false otherwise. | ||||
| 352 | |||||
| 353 | =cut | ||||
| 354 | |||||
| 355 | # spent 21.5ms (21.5+700ns) within DBIx::Class::ResultSource::has_column which was called 4356 times, avg 5µs/call:
# 4275 times (21.3ms+700ns) by DBIx::Class::ResultSourceProxy::has_column at line 86 of DBIx/Class/ResultSourceProxy.pm, avg 5µs/call
# 42 times (67µs+0s) by DBIx::Class::ResultSource::add_unique_constraint at line 717, avg 2µs/call
# 39 times (101µs+0s) by DBIx::Class::ResultSource::set_primary_key at line 592, avg 3µs/call | ||||
| 356 | 4356 | 4.72ms | my ($self, $column) = @_; | ||
| 357 | 4356 | 23.8ms | 1 | 700ns | return exists $self->_columns->{$column}; # spent 700ns making 1 call to DBIx::Class::ResultSource::Table::_columns |
| 358 | } | ||||
| 359 | |||||
| 360 | =head2 column_info | ||||
| 361 | |||||
| 362 | =over | ||||
| 363 | |||||
| 364 | =item Arguments: $colname | ||||
| 365 | |||||
| 366 | =item Return value: Hashref of info | ||||
| 367 | |||||
| 368 | =back | ||||
| 369 | |||||
| 370 | my $info = $source->column_info($col); | ||||
| 371 | |||||
| 372 | Returns the column metadata hashref for a column, as originally passed | ||||
| 373 | to L</add_columns>. See L</add_columns> above for information on the | ||||
| 374 | contents of the hashref. | ||||
| 375 | |||||
| 376 | =cut | ||||
| 377 | |||||
| 378 | # spent 28.9ms (23.7+5.13) within DBIx::Class::ResultSource::column_info which was called 1528 times, avg 19µs/call:
# 1038 times (20.5ms+4.34ms) by DBIx::Class::ResultSourceProxy::column_info at line 86 of DBIx/Class/ResultSourceProxy.pm, avg 24µs/call
# 250 times (1.40ms+402µs) by DBIx::Class::ResultSourceProxy::add_columns at line 34 of DBIx/Class/ResultSourceProxy.pm, avg 7µs/call
# 240 times (1.87ms+393µs) by SQL::Translator::Parser::DBIx::Class::parse at line 115 of SQL/Translator/Parser/DBIx/Class.pm, avg 9µs/call | ||||
| 379 | 1528 | 1.63ms | my ($self, $column) = @_; | ||
| 380 | 1528 | 10.8ms | 1369 | 2.85ms | $self->throw_exception("No such column $column") # spent 2.77ms making 1359 calls to DBIx::Class::ResultSource::Table::_columns, avg 2µs/call
# spent 79µs making 10 calls to DBIx::Class::ResultSource::_columns, avg 8µs/call |
| 381 | unless exists $self->_columns->{$column}; | ||||
| 382 | |||||
| 383 | 1528 | 7.31ms | 1369 | 1.22ms | if ( ! $self->_columns->{$column}{data_type} # spent 1.15ms making 1359 calls to DBIx::Class::ResultSource::Table::_columns, avg 845ns/call
# spent 68µs making 10 calls to DBIx::Class::ResultSource::_columns, avg 7µs/call |
| 384 | and ! $self->{_columns_info_loaded} | ||||
| 385 | and $self->column_info_from_storage | ||||
| 386 | and my $stor = try { $self->storage } ) | ||||
| 387 | { | ||||
| 388 | $self->{_columns_info_loaded}++; | ||||
| 389 | |||||
| 390 | # try for the case of storage without table | ||||
| 391 | try { | ||||
| 392 | my $info = $stor->columns_info_for( $self->from ); | ||||
| 393 | my $lc_info = { map | ||||
| 394 | { (lc $_) => $info->{$_} } | ||||
| 395 | ( keys %$info ) | ||||
| 396 | }; | ||||
| 397 | |||||
| 398 | foreach my $col ( keys %{$self->_columns} ) { | ||||
| 399 | $self->_columns->{$col} = { | ||||
| 400 | %{ $self->_columns->{$col} }, | ||||
| 401 | %{ $info->{$col} || $lc_info->{lc $col} || {} } | ||||
| 402 | }; | ||||
| 403 | } | ||||
| 404 | }; | ||||
| 405 | } | ||||
| 406 | |||||
| 407 | 1528 | 10.3ms | 1369 | 1.06ms | return $self->_columns->{$column}; # spent 992µs making 1359 calls to DBIx::Class::ResultSource::Table::_columns, avg 730ns/call
# spent 66µs making 10 calls to DBIx::Class::ResultSource::_columns, avg 7µs/call |
| 408 | } | ||||
| 409 | |||||
| 410 | =head2 columns | ||||
| 411 | |||||
| 412 | =over | ||||
| 413 | |||||
| 414 | =item Arguments: None | ||||
| 415 | |||||
| 416 | =item Return value: Ordered list of column names | ||||
| 417 | |||||
| 418 | =back | ||||
| 419 | |||||
| 420 | my @column_names = $source->columns; | ||||
| 421 | |||||
| 422 | Returns all column names in the order they were declared to L</add_columns>. | ||||
| 423 | |||||
| 424 | =cut | ||||
| 425 | |||||
| 426 | # spent 106ms within DBIx::Class::ResultSource::columns which was called 17444 times, avg 6µs/call:
# 8073 times (49.9ms+0s) by DBIx::Class::Storage::DBIHacks::_resolve_column_info at line 485 of DBIx/Class/Storage/DBIHacks.pm, avg 6µs/call
# 6871 times (45.1ms+0s) by DBIx::Class::ResultSet::_resolved_attrs at line 3159 of DBIx/Class/ResultSet.pm, avg 7µs/call
# 1954 times (5.87ms+0s) by DBIx::Class::ResultSetColumn::new at line 65 of DBIx/Class/ResultSetColumn.pm, avg 3µs/call
# 449 times (4.60ms+0s) by DBIx::Class::Storage::DBI::insert at line 1645 of DBIx/Class/Storage/DBI.pm, avg 10µs/call
# 60 times (276µs+0s) by SQL::Translator::Parser::DBIx::Class::parse at line 174 of SQL/Translator/Parser/DBIx/Class.pm, avg 5µs/call
# 35 times (137µs+0s) by SQL::Translator::Parser::DBIx::Class::parse at line 105 of SQL/Translator/Parser/DBIx/Class.pm, avg 4µs/call
# 2 times (9µs+0s) by SQL::Translator::Parser::DBIx::Class::parse at line 337 of SQL/Translator/Parser/DBIx/Class.pm, avg 4µs/call | ||||
| 427 | 17444 | 8.32ms | my $self = shift; | ||
| 428 | 17444 | 7.21ms | $self->throw_exception( | ||
| 429 | "columns() is a read-only accessor, did you mean add_columns()?" | ||||
| 430 | ) if @_; | ||||
| 431 | 17444 | 121ms | return @{$self->{_ordered_columns}||[]}; | ||
| 432 | } | ||||
| 433 | |||||
| 434 | =head2 columns_info | ||||
| 435 | |||||
| 436 | =over | ||||
| 437 | |||||
| 438 | =item Arguments: \@colnames ? | ||||
| 439 | |||||
| 440 | =item Return value: Hashref of column name/info pairs | ||||
| 441 | |||||
| 442 | =back | ||||
| 443 | |||||
| 444 | my $columns_info = $source->columns_info; | ||||
| 445 | |||||
| 446 | Like L</column_info> but returns information for the requested columns. If | ||||
| 447 | the optional column-list arrayref is omitted it returns info on all columns | ||||
| 448 | currently defined on the ResultSource via L</add_columns>. | ||||
| 449 | |||||
| 450 | =cut | ||||
| 451 | |||||
| 452 | # spent 309ms (223+86.2) within DBIx::Class::ResultSource::columns_info which was called 8975 times, avg 34µs/call:
# 8073 times (196ms+75.5ms) by DBIx::Class::Storage::DBIHacks::_resolve_column_info at line 511 of DBIx/Class/Storage/DBIHacks.pm, avg 34µs/call
# 449 times (16.2ms+7.26ms) by DBIx::Class::Storage::DBI::_prefetch_autovalues at line 1606 of DBIx/Class/Storage/DBI.pm, avg 52µs/call
# 449 times (10.4ms+3.36ms) by DBIx::Class::Storage::DBI::insert at line 1642 of DBIx/Class/Storage/DBI.pm, avg 31µs/call
# 4 times (81µs+34µs) by DBIx::Class::DynamicDefault::add_columns at line 66 of DBIx/Class/DynamicDefault.pm, avg 29µs/call | ||||
| 453 | 8975 | 6.91ms | my ($self, $columns) = @_; | ||
| 454 | |||||
| 455 | 8975 | 18.1ms | 1 | 1µs | my $colinfo = $self->_columns; # spent 1µs making 1 call to DBIx::Class::ResultSource::Table::_columns |
| 456 | |||||
| 457 | 8975 | 60.6ms | 8975 | 86.2ms | if ( # spent 86.2ms making 8975 calls to List::Util::first, avg 10µs/call |
| 458 | 60233 | 117ms | first { ! $_->{data_type} } values %$colinfo | ||
| 459 | and | ||||
| 460 | ! $self->{_columns_info_loaded} | ||||
| 461 | and | ||||
| 462 | $self->column_info_from_storage | ||||
| 463 | and | ||||
| 464 | my $stor = try { $self->storage } | ||||
| 465 | ) { | ||||
| 466 | $self->{_columns_info_loaded}++; | ||||
| 467 | |||||
| 468 | # try for the case of storage without table | ||||
| 469 | try { | ||||
| 470 | my $info = $stor->columns_info_for( $self->from ); | ||||
| 471 | my $lc_info = { map | ||||
| 472 | { (lc $_) => $info->{$_} } | ||||
| 473 | ( keys %$info ) | ||||
| 474 | }; | ||||
| 475 | |||||
| 476 | foreach my $col ( keys %$colinfo ) { | ||||
| 477 | $colinfo->{$col} = { | ||||
| 478 | %{ $colinfo->{$col} }, | ||||
| 479 | %{ $info->{$col} || $lc_info->{lc $col} || {} } | ||||
| 480 | }; | ||||
| 481 | } | ||||
| 482 | }; | ||||
| 483 | } | ||||
| 484 | |||||
| 485 | 8975 | 3.57ms | my %ret; | ||
| 486 | |||||
| 487 | 8975 | 23.0ms | if ($columns) { | ||
| 488 | for (@$columns) { | ||||
| 489 | if (my $inf = $colinfo->{$_}) { | ||||
| 490 | $ret{$_} = $inf; | ||||
| 491 | } | ||||
| 492 | else { | ||||
| 493 | $self->throw_exception( sprintf ( | ||||
| 494 | "No such column '%s' on source %s", | ||||
| 495 | $_, | ||||
| 496 | $self->source_name, | ||||
| 497 | )); | ||||
| 498 | } | ||||
| 499 | } | ||||
| 500 | } | ||||
| 501 | else { | ||||
| 502 | 8975 | 56.7ms | %ret = %$colinfo; | ||
| 503 | } | ||||
| 504 | |||||
| 505 | 8975 | 39.5ms | return \%ret; | ||
| 506 | } | ||||
| 507 | |||||
| 508 | =head2 remove_columns | ||||
| 509 | |||||
| 510 | =over | ||||
| 511 | |||||
| 512 | =item Arguments: @colnames | ||||
| 513 | |||||
| 514 | =item Return value: undefined | ||||
| 515 | |||||
| 516 | =back | ||||
| 517 | |||||
| 518 | $source->remove_columns(qw/col1 col2 col3/); | ||||
| 519 | |||||
| 520 | Removes the given list of columns by name, from the result source. | ||||
| 521 | |||||
| 522 | B<Warning>: Removing a column that is also used in the sources primary | ||||
| 523 | key, or in one of the sources unique constraints, B<will> result in a | ||||
| 524 | broken result source. | ||||
| 525 | |||||
| 526 | =head2 remove_column | ||||
| 527 | |||||
| 528 | =over | ||||
| 529 | |||||
| 530 | =item Arguments: $colname | ||||
| 531 | |||||
| 532 | =item Return value: undefined | ||||
| 533 | |||||
| 534 | =back | ||||
| 535 | |||||
| 536 | $source->remove_column('col'); | ||||
| 537 | |||||
| 538 | Remove a single column by name from the result source, similar to | ||||
| 539 | L</remove_columns>. | ||||
| 540 | |||||
| 541 | B<Warning>: Removing a column that is also used in the sources primary | ||||
| 542 | key, or in one of the sources unique constraints, B<will> result in a | ||||
| 543 | broken result source. | ||||
| 544 | |||||
| 545 | =cut | ||||
| 546 | |||||
| 547 | sub remove_columns { | ||||
| 548 | my ($self, @to_remove) = @_; | ||||
| 549 | |||||
| 550 | my $columns = $self->_columns | ||||
| 551 | or return; | ||||
| 552 | |||||
| 553 | my %to_remove; | ||||
| 554 | for (@to_remove) { | ||||
| 555 | delete $columns->{$_}; | ||||
| 556 | ++$to_remove{$_}; | ||||
| 557 | } | ||||
| 558 | |||||
| 559 | $self->_ordered_columns([ grep { not $to_remove{$_} } @{$self->_ordered_columns} ]); | ||||
| 560 | } | ||||
| 561 | |||||
| 562 | sub remove_column { shift->remove_columns(@_); } # DO NOT CHANGE THIS TO GLOB | ||||
| 563 | |||||
| 564 | =head2 set_primary_key | ||||
| 565 | |||||
| 566 | =over 4 | ||||
| 567 | |||||
| 568 | =item Arguments: @cols | ||||
| 569 | |||||
| 570 | =item Return value: undefined | ||||
| 571 | |||||
| 572 | =back | ||||
| 573 | |||||
| 574 | Defines one or more columns as primary key for this source. Must be | ||||
| 575 | called after L</add_columns>. | ||||
| 576 | |||||
| 577 | Additionally, defines a L<unique constraint|add_unique_constraint> | ||||
| 578 | named C<primary>. | ||||
| 579 | |||||
| 580 | Note: you normally do want to define a primary key on your sources | ||||
| 581 | B<even if the underlying database table does not have a primary key>. | ||||
| 582 | See | ||||
| 583 | L<DBIx::Class::Manual::Intro/The Significance and Importance of Primary Keys> | ||||
| 584 | for more info. | ||||
| 585 | |||||
| 586 | =cut | ||||
| 587 | |||||
| 588 | # spent 1.56ms (463µs+1.10) within DBIx::Class::ResultSource::set_primary_key which was called 35 times, avg 45µs/call:
# 35 times (463µs+1.10ms) by DBIx::Class::ResultSourceProxy::set_primary_key at line 86 of DBIx/Class/ResultSourceProxy.pm, avg 45µs/call | ||||
| 589 | 35 | 42µs | my ($self, @cols) = @_; | ||
| 590 | # check if primary key columns are valid columns | ||||
| 591 | 35 | 33µs | foreach my $col (@cols) { | ||
| 592 | 39 | 98µs | 39 | 101µs | $self->throw_exception("No such column $col on table " . $self->name) # spent 101µs making 39 calls to DBIx::Class::ResultSource::has_column, avg 3µs/call |
| 593 | unless $self->has_column($col); | ||||
| 594 | } | ||||
| 595 | 35 | 65µs | 2 | 143µs | $self->_primaries(\@cols); # spent 141µs making 1 call to DBIx::Class::ResultSource::_primaries
# spent 2µs making 1 call to DBIx::Class::ResultSource::Table::_primaries |
| 596 | |||||
| 597 | 35 | 156µs | 35 | 852µs | $self->add_unique_constraint(primary => \@cols); # spent 852µs making 35 calls to DBIx::Class::ResultSource::add_unique_constraint, avg 24µs/call |
| 598 | } | ||||
| 599 | |||||
| 600 | =head2 primary_columns | ||||
| 601 | |||||
| 602 | =over 4 | ||||
| 603 | |||||
| 604 | =item Arguments: None | ||||
| 605 | |||||
| 606 | =item Return value: Ordered list of primary column names | ||||
| 607 | |||||
| 608 | =back | ||||
| 609 | |||||
| 610 | Read-only accessor which returns the list of primary keys, supplied by | ||||
| 611 | L</set_primary_key>. | ||||
| 612 | |||||
| 613 | =cut | ||||
| 614 | |||||
| 615 | # spent 14.8ms (14.8+1µs) within DBIx::Class::ResultSource::primary_columns which was called 3166 times, avg 5µs/call:
# 1690 times (5.31ms+0s) by DBIx::Class::ResultSource::_pri_cols at line 624, avg 3µs/call
# 992 times (6.15ms+0s) by DBIx::Class::ResultSourceProxy::primary_columns at line 86 of DBIx/Class/ResultSourceProxy.pm, avg 6µs/call
# 449 times (3.22ms+0s) by DBIx::Class::Storage::DBI::insert at line 1643 of DBIx/Class/Storage/DBI.pm, avg 7µs/call
# 35 times (136µs+1µs) by SQL::Translator::Parser::DBIx::Class::parse at line 124 of SQL/Translator/Parser/DBIx/Class.pm, avg 4µs/call | ||||
| 616 | 3166 | 22.7ms | 1 | 1µs | return @{shift->_primaries||[]}; # spent 1µs making 1 call to DBIx::Class::ResultSource::Table::_primaries |
| 617 | } | ||||
| 618 | |||||
| 619 | # a helper method that will automatically die with a descriptive message if | ||||
| 620 | # no pk is defined on the source in question. For internal use to save | ||||
| 621 | # on if @pks... boilerplate | ||||
| 622 | # spent 21.7ms (16.4+5.31) within DBIx::Class::ResultSource::_pri_cols which was called 1690 times, avg 13µs/call:
# 1690 times (16.4ms+5.31ms) by DBIx::Class::ResultSourceProxy::_pri_cols at line 86 of DBIx/Class/ResultSourceProxy.pm, avg 13µs/call | ||||
| 623 | 1690 | 1.28ms | my $self = shift; | ||
| 624 | 1690 | 6.36ms | 1690 | 5.31ms | my @pcols = $self->primary_columns # spent 5.31ms making 1690 calls to DBIx::Class::ResultSource::primary_columns, avg 3µs/call |
| 625 | or $self->throw_exception (sprintf( | ||||
| 626 | "Operation requires a primary key to be declared on '%s' via set_primary_key", | ||||
| 627 | # source_name is set only after schema-registration | ||||
| 628 | $self->source_name || $self->result_class || $self->name || 'Unknown source...?', | ||||
| 629 | )); | ||||
| 630 | 1690 | 7.38ms | return @pcols; | ||
| 631 | } | ||||
| 632 | |||||
| 633 | =head2 sequence | ||||
| 634 | |||||
| 635 | Manually define the correct sequence for your table, to avoid the overhead | ||||
| 636 | associated with looking up the sequence automatically. The supplied sequence | ||||
| 637 | will be applied to the L</column_info> of each L<primary_key|/set_primary_key> | ||||
| 638 | |||||
| 639 | =over 4 | ||||
| 640 | |||||
| 641 | =item Arguments: $sequence_name | ||||
| 642 | |||||
| 643 | =item Return value: undefined | ||||
| 644 | |||||
| 645 | =back | ||||
| 646 | |||||
| 647 | =cut | ||||
| 648 | |||||
| 649 | sub sequence { | ||||
| 650 | my ($self,$seq) = @_; | ||||
| 651 | |||||
| 652 | my @pks = $self->primary_columns | ||||
| 653 | or return; | ||||
| 654 | |||||
| 655 | $_->{sequence} = $seq | ||||
| 656 | for values %{ $self->columns_info (\@pks) }; | ||||
| 657 | } | ||||
| 658 | |||||
| 659 | |||||
| 660 | =head2 add_unique_constraint | ||||
| 661 | |||||
| 662 | =over 4 | ||||
| 663 | |||||
| 664 | =item Arguments: $name?, \@colnames | ||||
| 665 | |||||
| 666 | =item Return value: undefined | ||||
| 667 | |||||
| 668 | =back | ||||
| 669 | |||||
| 670 | Declare a unique constraint on this source. Call once for each unique | ||||
| 671 | constraint. | ||||
| 672 | |||||
| 673 | # For UNIQUE (column1, column2) | ||||
| 674 | __PACKAGE__->add_unique_constraint( | ||||
| 675 | constraint_name => [ qw/column1 column2/ ], | ||||
| 676 | ); | ||||
| 677 | |||||
| 678 | Alternatively, you can specify only the columns: | ||||
| 679 | |||||
| 680 | __PACKAGE__->add_unique_constraint([ qw/column1 column2/ ]); | ||||
| 681 | |||||
| 682 | This will result in a unique constraint named | ||||
| 683 | C<table_column1_column2>, where C<table> is replaced with the table | ||||
| 684 | name. | ||||
| 685 | |||||
| 686 | Unique constraints are used, for example, when you pass the constraint | ||||
| 687 | name as the C<key> attribute to L<DBIx::Class::ResultSet/find>. Then | ||||
| 688 | only columns in the constraint are searched. | ||||
| 689 | |||||
| 690 | Throws an error if any of the given column names do not yet exist on | ||||
| 691 | the result source. | ||||
| 692 | |||||
| 693 | =cut | ||||
| 694 | |||||
| 695 | # spent 893µs (598+295) within DBIx::Class::ResultSource::add_unique_constraint which was called 38 times, avg 24µs/call:
# 35 times (568µs+284µs) by DBIx::Class::ResultSource::set_primary_key at line 597, avg 24µs/call
# 3 times (29µs+12µs) by DBIx::Class::ResultSourceProxy::add_unique_constraint at line 86 of DBIx/Class/ResultSourceProxy.pm, avg 14µs/call | ||||
| 696 | 38 | 19µs | my $self = shift; | ||
| 697 | |||||
| 698 | 38 | 24µs | if (@_ > 2) { | ||
| 699 | $self->throw_exception( | ||||
| 700 | 'add_unique_constraint() does not accept multiple constraints, use ' | ||||
| 701 | . 'add_unique_constraints() instead' | ||||
| 702 | ); | ||||
| 703 | } | ||||
| 704 | |||||
| 705 | 38 | 26µs | my $cols = pop @_; | ||
| 706 | 38 | 36µs | if (ref $cols ne 'ARRAY') { | ||
| 707 | $self->throw_exception ( | ||||
| 708 | 'Expecting an arrayref of constraint columns, got ' . ($cols||'NOTHING') | ||||
| 709 | ); | ||||
| 710 | } | ||||
| 711 | |||||
| 712 | 38 | 17µs | my $name = shift @_; | ||
| 713 | |||||
| 714 | 38 | 13µs | $name ||= $self->name_unique_constraint($cols); | ||
| 715 | |||||
| 716 | 38 | 36µs | foreach my $col (@$cols) { | ||
| 717 | 42 | 74µs | 42 | 67µs | $self->throw_exception("No such column $col on table " . $self->name) # spent 67µs making 42 calls to DBIx::Class::ResultSource::has_column, avg 2µs/call |
| 718 | unless $self->has_column($col); | ||||
| 719 | } | ||||
| 720 | |||||
| 721 | 38 | 119µs | 38 | 228µs | my %unique_constraints = $self->unique_constraints; # spent 228µs making 38 calls to DBIx::Class::ResultSource::unique_constraints, avg 6µs/call |
| 722 | 38 | 38µs | $unique_constraints{$name} = $cols; | ||
| 723 | 38 | 130µs | 1 | 1µs | $self->_unique_constraints(\%unique_constraints); # spent 1µs making 1 call to DBIx::Class::ResultSource::Table::_unique_constraints |
| 724 | } | ||||
| 725 | |||||
| 726 | =head2 add_unique_constraints | ||||
| 727 | |||||
| 728 | =over 4 | ||||
| 729 | |||||
| 730 | =item Arguments: @constraints | ||||
| 731 | |||||
| 732 | =item Return value: undefined | ||||
| 733 | |||||
| 734 | =back | ||||
| 735 | |||||
| 736 | Declare multiple unique constraints on this source. | ||||
| 737 | |||||
| 738 | __PACKAGE__->add_unique_constraints( | ||||
| 739 | constraint_name1 => [ qw/column1 column2/ ], | ||||
| 740 | constraint_name2 => [ qw/column2 column3/ ], | ||||
| 741 | ); | ||||
| 742 | |||||
| 743 | Alternatively, you can specify only the columns: | ||||
| 744 | |||||
| 745 | __PACKAGE__->add_unique_constraints( | ||||
| 746 | [ qw/column1 column2/ ], | ||||
| 747 | [ qw/column3 column4/ ] | ||||
| 748 | ); | ||||
| 749 | |||||
| 750 | This will result in unique constraints named C<table_column1_column2> and | ||||
| 751 | C<table_column3_column4>, where C<table> is replaced with the table name. | ||||
| 752 | |||||
| 753 | Throws an error if any of the given column names do not yet exist on | ||||
| 754 | the result source. | ||||
| 755 | |||||
| 756 | See also L</add_unique_constraint>. | ||||
| 757 | |||||
| 758 | =cut | ||||
| 759 | |||||
| 760 | sub add_unique_constraints { | ||||
| 761 | my $self = shift; | ||||
| 762 | my @constraints = @_; | ||||
| 763 | |||||
| 764 | if ( !(@constraints % 2) && first { ref $_ ne 'ARRAY' } @constraints ) { | ||||
| 765 | # with constraint name | ||||
| 766 | while (my ($name, $constraint) = splice @constraints, 0, 2) { | ||||
| 767 | $self->add_unique_constraint($name => $constraint); | ||||
| 768 | } | ||||
| 769 | } | ||||
| 770 | else { | ||||
| 771 | # no constraint name | ||||
| 772 | foreach my $constraint (@constraints) { | ||||
| 773 | $self->add_unique_constraint($constraint); | ||||
| 774 | } | ||||
| 775 | } | ||||
| 776 | } | ||||
| 777 | |||||
| 778 | =head2 name_unique_constraint | ||||
| 779 | |||||
| 780 | =over 4 | ||||
| 781 | |||||
| 782 | =item Arguments: \@colnames | ||||
| 783 | |||||
| 784 | =item Return value: Constraint name | ||||
| 785 | |||||
| 786 | =back | ||||
| 787 | |||||
| 788 | $source->table('mytable'); | ||||
| 789 | $source->name_unique_constraint(['col1', 'col2']); | ||||
| 790 | # returns | ||||
| 791 | 'mytable_col1_col2' | ||||
| 792 | |||||
| 793 | Return a name for a unique constraint containing the specified | ||||
| 794 | columns. The name is created by joining the table name and each column | ||||
| 795 | name, using an underscore character. | ||||
| 796 | |||||
| 797 | For example, a constraint on a table named C<cd> containing the columns | ||||
| 798 | C<artist> and C<title> would result in a constraint name of C<cd_artist_title>. | ||||
| 799 | |||||
| 800 | This is used by L</add_unique_constraint> if you do not specify the | ||||
| 801 | optional constraint name. | ||||
| 802 | |||||
| 803 | =cut | ||||
| 804 | |||||
| 805 | sub name_unique_constraint { | ||||
| 806 | my ($self, $cols) = @_; | ||||
| 807 | |||||
| 808 | my $name = $self->name; | ||||
| 809 | $name = $$name if (ref $name eq 'SCALAR'); | ||||
| 810 | |||||
| 811 | return join '_', $name, @$cols; | ||||
| 812 | } | ||||
| 813 | |||||
| 814 | =head2 unique_constraints | ||||
| 815 | |||||
| 816 | =over 4 | ||||
| 817 | |||||
| 818 | =item Arguments: None | ||||
| 819 | |||||
| 820 | =item Return value: Hash of unique constraint data | ||||
| 821 | |||||
| 822 | =back | ||||
| 823 | |||||
| 824 | $source->unique_constraints(); | ||||
| 825 | |||||
| 826 | Read-only accessor which returns a hash of unique constraints on this | ||||
| 827 | source. | ||||
| 828 | |||||
| 829 | The hash is keyed by constraint name, and contains an arrayref of | ||||
| 830 | column names as values. | ||||
| 831 | |||||
| 832 | =cut | ||||
| 833 | |||||
| 834 | # spent 3.65ms (3.56+94µs) within DBIx::Class::ResultSource::unique_constraints which was called 809 times, avg 5µs/call:
# 714 times (3.01ms+0s) by DBIx::Class::ResultSource::unique_constraint_columns at line 881, avg 4µs/call
# 38 times (133µs+94µs) by DBIx::Class::ResultSource::add_unique_constraint at line 721, avg 6µs/call
# 35 times (165µs+0s) by SQL::Translator::Parser::DBIx::Class::parse at line 128 of SQL/Translator/Parser/DBIx/Class.pm, avg 5µs/call
# 22 times (255µs+0s) by DBIx::Class::ResultSource::unique_constraint_names at line 857, avg 12µs/call | ||||
| 835 | 809 | 5.32ms | 2 | 94µs | return %{shift->_unique_constraints||{}}; # spent 93µs making 1 call to DBIx::Class::ResultSource::_unique_constraints
# spent 1µs making 1 call to DBIx::Class::ResultSource::Table::_unique_constraints |
| 836 | } | ||||
| 837 | |||||
| 838 | =head2 unique_constraint_names | ||||
| 839 | |||||
| 840 | =over 4 | ||||
| 841 | |||||
| 842 | =item Arguments: None | ||||
| 843 | |||||
| 844 | =item Return value: Unique constraint names | ||||
| 845 | |||||
| 846 | =back | ||||
| 847 | |||||
| 848 | $source->unique_constraint_names(); | ||||
| 849 | |||||
| 850 | Returns the list of unique constraint names defined on this source. | ||||
| 851 | |||||
| 852 | =cut | ||||
| 853 | |||||
| 854 | # spent 688µs (433+255) within DBIx::Class::ResultSource::unique_constraint_names which was called 22 times, avg 31µs/call:
# 22 times (433µs+255µs) by DBIx::Class::ResultSet::find at line 786 of DBIx/Class/ResultSet.pm, avg 31µs/call | ||||
| 855 | 22 | 28µs | my ($self) = @_; | ||
| 856 | |||||
| 857 | 22 | 184µs | 22 | 255µs | my %unique_constraints = $self->unique_constraints; # spent 255µs making 22 calls to DBIx::Class::ResultSource::unique_constraints, avg 12µs/call |
| 858 | |||||
| 859 | 22 | 187µs | return keys %unique_constraints; | ||
| 860 | } | ||||
| 861 | |||||
| 862 | =head2 unique_constraint_columns | ||||
| 863 | |||||
| 864 | =over 4 | ||||
| 865 | |||||
| 866 | =item Arguments: $constraintname | ||||
| 867 | |||||
| 868 | =item Return value: List of constraint columns | ||||
| 869 | |||||
| 870 | =back | ||||
| 871 | |||||
| 872 | $source->unique_constraint_columns('myconstraint'); | ||||
| 873 | |||||
| 874 | Returns the list of columns that make up the specified unique constraint. | ||||
| 875 | |||||
| 876 | =cut | ||||
| 877 | |||||
| 878 | # spent 10.8ms (7.75+3.01) within DBIx::Class::ResultSource::unique_constraint_columns which was called 714 times, avg 15µs/call:
# 357 times (2.86ms+821µs) by DBIx::Class::ResultSet::_build_unique_cond at line 853 of DBIx/Class/ResultSet.pm, avg 10µs/call
# 331 times (4.42ms+2.08ms) by DBIx::Class::ResultSet::find at line 723 of DBIx/Class/ResultSet.pm, avg 20µs/call
# 26 times (464µs+108µs) by DBIx::Class::ResultSet::find at line 788 of DBIx/Class/ResultSet.pm, avg 22µs/call | ||||
| 879 | 714 | 666µs | my ($self, $constraint_name) = @_; | ||
| 880 | |||||
| 881 | 714 | 2.83ms | 714 | 3.01ms | my %unique_constraints = $self->unique_constraints; # spent 3.01ms making 714 calls to DBIx::Class::ResultSource::unique_constraints, avg 4µs/call |
| 882 | |||||
| 883 | 714 | 385µs | $self->throw_exception( | ||
| 884 | "Unknown unique constraint $constraint_name on '" . $self->name . "'" | ||||
| 885 | ) unless exists $unique_constraints{$constraint_name}; | ||||
| 886 | |||||
| 887 | 714 | 3.55ms | return @{ $unique_constraints{$constraint_name} }; | ||
| 888 | } | ||||
| 889 | |||||
| 890 | =head2 sqlt_deploy_callback | ||||
| 891 | |||||
| 892 | =over | ||||
| 893 | |||||
| 894 | =item Arguments: $callback_name | \&callback_code | ||||
| 895 | |||||
| 896 | =item Return value: $callback_name | \&callback_code | ||||
| 897 | |||||
| 898 | =back | ||||
| 899 | |||||
| 900 | __PACKAGE__->sqlt_deploy_callback('mycallbackmethod'); | ||||
| 901 | |||||
| 902 | or | ||||
| 903 | |||||
| 904 | __PACKAGE__->sqlt_deploy_callback(sub { | ||||
| 905 | my ($source_instance, $sqlt_table) = @_; | ||||
| 906 | ... | ||||
| 907 | } ); | ||||
| 908 | |||||
| 909 | An accessor to set a callback to be called during deployment of | ||||
| 910 | the schema via L<DBIx::Class::Schema/create_ddl_dir> or | ||||
| 911 | L<DBIx::Class::Schema/deploy>. | ||||
| 912 | |||||
| 913 | The callback can be set as either a code reference or the name of a | ||||
| 914 | method in the current result class. | ||||
| 915 | |||||
| 916 | Defaults to L</default_sqlt_deploy_hook>. | ||||
| 917 | |||||
| 918 | Your callback will be passed the $source object representing the | ||||
| 919 | ResultSource instance being deployed, and the | ||||
| 920 | L<SQL::Translator::Schema::Table> object being created from it. The | ||||
| 921 | callback can be used to manipulate the table object or add your own | ||||
| 922 | customised indexes. If you need to manipulate a non-table object, use | ||||
| 923 | the L<DBIx::Class::Schema/sqlt_deploy_hook>. | ||||
| 924 | |||||
| 925 | See L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To | ||||
| 926 | Your SQL> for examples. | ||||
| 927 | |||||
| 928 | This sqlt deployment callback can only be used to manipulate | ||||
| 929 | SQL::Translator objects as they get turned into SQL. To execute | ||||
| 930 | post-deploy statements which SQL::Translator does not currently | ||||
| 931 | handle, override L<DBIx::Class::Schema/deploy> in your Schema class | ||||
| 932 | and call L<dbh_do|DBIx::Class::Storage::DBI/dbh_do>. | ||||
| 933 | |||||
| 934 | =head2 default_sqlt_deploy_hook | ||||
| 935 | |||||
| 936 | This is the default deploy hook implementation which checks if your | ||||
| 937 | current Result class has a C<sqlt_deploy_hook> method, and if present | ||||
| 938 | invokes it B<on the Result class directly>. This is to preserve the | ||||
| 939 | semantics of C<sqlt_deploy_hook> which was originally designed to expect | ||||
| 940 | the Result class name and the | ||||
| 941 | L<$sqlt_table instance|SQL::Translator::Schema::Table> of the table being | ||||
| 942 | deployed. | ||||
| 943 | |||||
| 944 | =cut | ||||
| 945 | |||||
| 946 | # spent 2.17ms (731µs+1.44) within DBIx::Class::ResultSource::default_sqlt_deploy_hook which was called 37 times, avg 59µs/call:
# 37 times (731µs+1.44ms) by DBIx::Class::ResultSource::_invoke_sqlt_deploy_hook at line 958, avg 59µs/call | ||||
| 947 | 37 | 10µs | my $self = shift; | ||
| 948 | |||||
| 949 | 37 | 46µs | 37 | 502µs | my $class = $self->result_class; # spent 502µs making 37 calls to DBIx::Class::ResultSource::result_class, avg 14µs/call |
| 950 | |||||
| 951 | 37 | 1.28ms | 39 | 941µs | if ($class and $class->can('sqlt_deploy_hook')) { # spent 610µs making 37 calls to UNIVERSAL::can, avg 16µs/call
# spent 202µs making 1 call to Tapper::Schema::ReportsDB::Result::Report::sqlt_deploy_hook
# spent 129µs making 1 call to Tapper::Schema::ReportsDB::Result::Suite::sqlt_deploy_hook |
| 952 | $class->sqlt_deploy_hook(@_); | ||||
| 953 | } | ||||
| 954 | } | ||||
| 955 | |||||
| 956 | # spent 3.27ms (218µs+3.05) within DBIx::Class::ResultSource::_invoke_sqlt_deploy_hook which was called 37 times, avg 88µs/call:
# 35 times (204µs+2.88ms) by SQL::Translator::Parser::DBIx::Class::parse at line 284 of SQL/Translator/Parser/DBIx/Class.pm, avg 88µs/call
# 2 times (15µs+169µs) by SQL::Translator::Parser::DBIx::Class::parse at line 343 of SQL/Translator/Parser/DBIx/Class.pm, avg 92µs/call | ||||
| 957 | 37 | 11µs | my $self = shift; | ||
| 958 | 37 | 170µs | 74 | 3.05ms | if ( my $hook = $self->sqlt_deploy_callback) { # spent 2.17ms making 37 calls to DBIx::Class::ResultSource::default_sqlt_deploy_hook, avg 59µs/call
# spent 876µs making 37 calls to DBIx::Class::ResultSource::sqlt_deploy_callback, avg 24µs/call |
| 959 | $self->$hook(@_); | ||||
| 960 | } | ||||
| 961 | } | ||||
| 962 | |||||
| 963 | =head2 resultset | ||||
| 964 | |||||
| 965 | =over 4 | ||||
| 966 | |||||
| 967 | =item Arguments: None | ||||
| 968 | |||||
| 969 | =item Return value: $resultset | ||||
| 970 | |||||
| 971 | =back | ||||
| 972 | |||||
| 973 | Returns a resultset for the given source. This will initially be created | ||||
| 974 | on demand by calling | ||||
| 975 | |||||
| 976 | $self->resultset_class->new($self, $self->resultset_attributes) | ||||
| 977 | |||||
| 978 | but is cached from then on unless resultset_class changes. | ||||
| 979 | |||||
| 980 | =head2 resultset_class | ||||
| 981 | |||||
| 982 | =over 4 | ||||
| 983 | |||||
| 984 | =item Arguments: $classname | ||||
| 985 | |||||
| 986 | =item Return value: $classname | ||||
| 987 | |||||
| 988 | =back | ||||
| 989 | |||||
| 990 | package My::Schema::ResultSet::Artist; | ||||
| 991 | use base 'DBIx::Class::ResultSet'; | ||||
| 992 | ... | ||||
| 993 | |||||
| 994 | # In the result class | ||||
| 995 | __PACKAGE__->resultset_class('My::Schema::ResultSet::Artist'); | ||||
| 996 | |||||
| 997 | # Or in code | ||||
| 998 | $source->resultset_class('My::Schema::ResultSet::Artist'); | ||||
| 999 | |||||
| 1000 | Set the class of the resultset. This is useful if you want to create your | ||||
| 1001 | own resultset methods. Create your own class derived from | ||||
| 1002 | L<DBIx::Class::ResultSet>, and set it here. If called with no arguments, | ||||
| 1003 | this method returns the name of the existing resultset class, if one | ||||
| 1004 | exists. | ||||
| 1005 | |||||
| 1006 | =head2 resultset_attributes | ||||
| 1007 | |||||
| 1008 | =over 4 | ||||
| 1009 | |||||
| 1010 | =item Arguments: \%attrs | ||||
| 1011 | |||||
| 1012 | =item Return value: \%attrs | ||||
| 1013 | |||||
| 1014 | =back | ||||
| 1015 | |||||
| 1016 | # In the result class | ||||
| 1017 | __PACKAGE__->resultset_attributes({ order_by => [ 'id' ] }); | ||||
| 1018 | |||||
| 1019 | # Or in code | ||||
| 1020 | $source->resultset_attributes({ order_by => [ 'id' ] }); | ||||
| 1021 | |||||
| 1022 | Store a collection of resultset attributes, that will be set on every | ||||
| 1023 | L<DBIx::Class::ResultSet> produced from this result source. For a full | ||||
| 1024 | list see L<DBIx::Class::ResultSet/ATTRIBUTES>. | ||||
| 1025 | |||||
| 1026 | =cut | ||||
| 1027 | |||||
| 1028 | # spent 1.28s (117ms+1.16) within DBIx::Class::ResultSource::resultset which was called 5708 times, avg 224µs/call:
# 3531 times (61.4ms+583ms) by DBIx::Class::Relationship::Base::related_resultset at line 493 of DBIx/Class/Relationship/Base.pm, avg 183µs/call
# 2030 times (53.5ms+561ms) by DBIx::Class::Schema::resultset at line 552 of DBIx/Class/Schema.pm, avg 303µs/call
# 147 times (2.09ms+18.7ms) by DBIx::Class::ResultSet::related_resultset at line 2909 of DBIx/Class/ResultSet.pm, avg 141µs/call | ||||
| 1029 | 5708 | 3.62ms | my $self = shift; | ||
| 1030 | 5708 | 2.81ms | $self->throw_exception( | ||
| 1031 | 'resultset does not take any arguments. If you want another resultset, '. | ||||
| 1032 | 'call it on the schema instead.' | ||||
| 1033 | ) if scalar @_; | ||||
| 1034 | |||||
| 1035 | $self->resultset_class->new( | ||||
| 1036 | $self, | ||||
| 1037 | { | ||||
| 1038 | 5708 | 44.7ms | 11416 | 286ms | # spent 344ms (57.5+286) within DBIx::Class::ResultSource::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/ResultSource.pm:1038] which was called 5708 times, avg 60µs/call:
# 5708 times (57.5ms+286ms) by Try::Tiny::try at line 71 of Try/Tiny.pm, avg 60µs/call # spent 271ms making 5708 calls to DBIx::Class::Schema::default_resultset_attributes, avg 47µs/call
# spent 15.2ms making 5708 calls to DBIx::Class::ResultSource::schema, avg 3µs/call |
| 1039 | 5708 | 98.2ms | 17124 | 1.16s | %{$self->{resultset_attributes}}, # spent 576ms making 5708 calls to DBIx::Class::ResultSet::new, avg 101µs/call
# spent 418ms making 5708 calls to Try::Tiny::try, avg 73µs/call
# spent 169ms making 5708 calls to DBIx::Class::ResultSource::resultset_class, avg 30µs/call |
| 1040 | }, | ||||
| 1041 | ); | ||||
| 1042 | } | ||||
| 1043 | |||||
| 1044 | =head2 name | ||||
| 1045 | |||||
| 1046 | =over 4 | ||||
| 1047 | |||||
| 1048 | =item Arguments: None | ||||
| 1049 | |||||
| 1050 | =item Result value: $name | ||||
| 1051 | |||||
| 1052 | =back | ||||
| 1053 | |||||
| 1054 | Returns the name of the result source, which will typically be the table | ||||
| 1055 | name. This may be a scalar reference if the result source has a non-standard | ||||
| 1056 | name. | ||||
| 1057 | |||||
| 1058 | =head2 source_name | ||||
| 1059 | |||||
| 1060 | =over 4 | ||||
| 1061 | |||||
| 1062 | =item Arguments: $source_name | ||||
| 1063 | |||||
| 1064 | =item Result value: $source_name | ||||
| 1065 | |||||
| 1066 | =back | ||||
| 1067 | |||||
| 1068 | Set an alternate name for the result source when it is loaded into a schema. | ||||
| 1069 | This is useful if you want to refer to a result source by a name other than | ||||
| 1070 | its class name. | ||||
| 1071 | |||||
| 1072 | package ArchivedBooks; | ||||
| 1073 | use base qw/DBIx::Class/; | ||||
| 1074 | __PACKAGE__->table('books_archive'); | ||||
| 1075 | __PACKAGE__->source_name('Books'); | ||||
| 1076 | |||||
| 1077 | # from your schema... | ||||
| 1078 | $schema->resultset('Books')->find(1); | ||||
| 1079 | |||||
| 1080 | =head2 from | ||||
| 1081 | |||||
| 1082 | =over 4 | ||||
| 1083 | |||||
| 1084 | =item Arguments: None | ||||
| 1085 | |||||
| 1086 | =item Return value: FROM clause | ||||
| 1087 | |||||
| 1088 | =back | ||||
| 1089 | |||||
| 1090 | my $from_clause = $source->from(); | ||||
| 1091 | |||||
| 1092 | Returns an expression of the source to be supplied to storage to specify | ||||
| 1093 | retrieval from this source. In the case of a database, the required FROM | ||||
| 1094 | clause contents. | ||||
| 1095 | |||||
| 1096 | =cut | ||||
| 1097 | |||||
| 1098 | sub from { die 'Virtual method!' } | ||||
| 1099 | |||||
| 1100 | =head2 schema | ||||
| 1101 | |||||
| 1102 | =over 4 | ||||
| 1103 | |||||
| 1104 | =item Arguments: $schema | ||||
| 1105 | |||||
| 1106 | =item Return value: A schema object | ||||
| 1107 | |||||
| 1108 | =back | ||||
| 1109 | |||||
| 1110 | my $schema = $source->schema(); | ||||
| 1111 | |||||
| 1112 | Sets and/or returns the L<DBIx::Class::Schema> object to which this | ||||
| 1113 | result source instance has been attached to. | ||||
| 1114 | |||||
| 1115 | =cut | ||||
| 1116 | |||||
| 1117 | # spent 65.8ms within DBIx::Class::ResultSource::schema which was called 23459 times, avg 3µs/call:
# 10410 times (28.5ms+0s) by DBIx::Class::ResultSource::storage at line 1154, avg 3µs/call
# 5708 times (15.2ms+0s) by DBIx::Class::ResultSource::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/ResultSource.pm:1038] at line 1038, avg 3µs/call
# 4155 times (12.8ms+0s) by DBIx::Class::ResultSource::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/ResultSource.pm:1853] at line 1853, avg 3µs/call
# 1954 times (4.29ms+0s) by DBIx::Class::ResultSetColumn::new at line 68 of DBIx/Class/ResultSetColumn.pm, avg 2µs/call
# 210 times (325µs+0s) by DBIx::Class::ResultSource::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/ResultSource.pm:1397] at line 1397, avg 2µs/call
# 147 times (1.31ms+0s) by Tapper::Schema::TestrunDB::Result::Testrun::rerun at line 151 of Tapper/Schema/TestrunDB/Result/Testrun.pm, avg 9µs/call
# 147 times (829µs+0s) by DBIx::Class::Relationship::CascadeActions::update at line 55 of DBIx/Class/Relationship/CascadeActions.pm, avg 6µs/call
# 147 times (502µs+0s) by Tapper::Schema::TestrunDB::Result::Testrun::rerun at line 122 of Tapper/Schema/TestrunDB/Result/Testrun.pm, avg 3µs/call
# 147 times (360µs+0s) by Tapper::Schema::TestrunDB::Result::Testrun::rerun at line 132 of Tapper/Schema/TestrunDB/Result/Testrun.pm, avg 2µs/call
# 147 times (215µs+0s) by DBIx::Class::ResultSet::related_resultset at line 2881 of DBIx/Class/ResultSet.pm, avg 1µs/call
# 129 times (1.20ms+0s) by Tapper::Schema::TestrunDB::Result::Testrun::assign_preconditions at line 193 of Tapper/Schema/TestrunDB/Result/Testrun.pm, avg 9µs/call
# 94 times (207µs+0s) by DBIx::Class::Schema::_register_source at line 1368 of DBIx/Class/Schema.pm, avg 2µs/call
# 60 times (93µs+0s) by DBIx::Class::ResultSource::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/ResultSource.pm:1378] at line 1378, avg 2µs/call
# 3 times (15µs+0s) by DBIx::Class::Row::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/Row.pm:797] at line 797 of DBIx/Class/Row.pm, avg 5µs/call
# once (4µs+0s) by Tapper::Schema::TestrunDB::Result::TestrunScheduling::gen_schema_functions at line 93 of Tapper/Schema/TestrunDB/Result/TestrunScheduling.pm | ||||
| 1118 | 23459 | 90.8ms | if (@_ > 1) { | ||
| 1119 | $_[0]->{schema} = $_[1]; | ||||
| 1120 | } | ||||
| 1121 | else { | ||||
| 1122 | 23365 | 23.4ms | $_[0]->{schema} || do { | ||
| 1123 | my $name = $_[0]->{source_name} || '_unnamed_'; | ||||
| 1124 | my $err = 'Unable to perform storage-dependent operations with a detached result source ' | ||||
| 1125 | . "(source '$name' is not associated with a schema)."; | ||||
| 1126 | |||||
| 1127 | $err .= ' You need to use $schema->thaw() or manually set' | ||||
| 1128 | . ' $DBIx::Class::ResultSourceHandle::thaw_schema while thawing.' | ||||
| 1129 | if $_[0]->{_detached_thaw}; | ||||
| 1130 | |||||
| 1131 | DBIx::Class::Exception->throw($err); | ||||
| 1132 | }; | ||||
| 1133 | } | ||||
| 1134 | } | ||||
| 1135 | |||||
| 1136 | =head2 storage | ||||
| 1137 | |||||
| 1138 | =over 4 | ||||
| 1139 | |||||
| 1140 | =item Arguments: None | ||||
| 1141 | |||||
| 1142 | =item Return value: A Storage object | ||||
| 1143 | |||||
| 1144 | =back | ||||
| 1145 | |||||
| 1146 | $source->storage->debug(1); | ||||
| 1147 | |||||
| 1148 | Returns the storage handle for the current schema. | ||||
| 1149 | |||||
| 1150 | See also: L<DBIx::Class::Storage> | ||||
| 1151 | |||||
| 1152 | =cut | ||||
| 1153 | |||||
| 1154 | 10410 | 85.7ms | 20820 | 201ms | # spent 301ms (101+201) within DBIx::Class::ResultSource::storage which was called 10410 times, avg 29µs/call:
# 4699 times (35.4ms+75.2ms) by DBIx::Class::ResultSet::cursor at line 957 of DBIx/Class/ResultSet.pm, avg 24µs/call
# 2007 times (20.4ms+43.1ms) by DBIx::Class::ResultSet::single at line 1031 of DBIx/Class/ResultSet.pm, avg 32µs/call
# 1949 times (25.0ms+36.9ms) by DBIx::Class::ResultSet::_count_rs at line 1494 of DBIx/Class/ResultSet.pm, avg 32µs/call
# 845 times (11.2ms+27.3ms) by DBIx::Class::Row::update at line 503 of DBIx/Class/Row.pm, avg 46µs/call
# 449 times (5.81ms+11.8ms) by DBIx::Class::Row::insert at line 289 of DBIx/Class/Row.pm, avg 39µs/call
# 147 times (1.15ms+2.26ms) by DBIx::Class::ResultSource::_resolve_join at line 1504, avg 23µs/call
# 147 times (685µs+1.61ms) by DBIx::Class::ResultSet::related_resultset at line 2874 of DBIx/Class/ResultSet.pm, avg 16µs/call
# 147 times (654µs+1.61ms) by DBIx::Class::InflateColumn::DateTime::_datetime_parser at line 221 of DBIx/Class/InflateColumn/DateTime.pm, avg 15µs/call
# 19 times (318µs+715µs) by DBIx::Class::ResultSet::_rs_update_delete at line 1773 of DBIx/Class/ResultSet.pm, avg 54µs/call
# once (7µs+13µs) by DBIx::Class::ResultSet::_resolved_attrs at line 3280 of DBIx/Class/ResultSet.pm # spent 172ms making 10410 calls to DBIx::Class::Schema::storage, avg 17µs/call
# spent 28.5ms making 10410 calls to DBIx::Class::ResultSource::schema, avg 3µs/call |
| 1155 | |||||
| 1156 | =head2 add_relationship | ||||
| 1157 | |||||
| 1158 | =over 4 | ||||
| 1159 | |||||
| 1160 | =item Arguments: $relname, $related_source_name, \%cond, [ \%attrs ] | ||||
| 1161 | |||||
| 1162 | =item Return value: 1/true if it succeeded | ||||
| 1163 | |||||
| 1164 | =back | ||||
| 1165 | |||||
| 1166 | $source->add_relationship('relname', 'related_source', $cond, $attrs); | ||||
| 1167 | |||||
| 1168 | L<DBIx::Class::Relationship> describes a series of methods which | ||||
| 1169 | create pre-defined useful types of relationships. Look there first | ||||
| 1170 | before using this method directly. | ||||
| 1171 | |||||
| 1172 | The relationship name can be arbitrary, but must be unique for each | ||||
| 1173 | relationship attached to this result source. 'related_source' should | ||||
| 1174 | be the name with which the related result source was registered with | ||||
| 1175 | the current schema. For example: | ||||
| 1176 | |||||
| 1177 | $schema->source('Book')->add_relationship('reviews', 'Review', { | ||||
| 1178 | 'foreign.book_id' => 'self.id', | ||||
| 1179 | }); | ||||
| 1180 | |||||
| 1181 | The condition C<$cond> needs to be an L<SQL::Abstract>-style | ||||
| 1182 | representation of the join between the tables. For example, if you're | ||||
| 1183 | creating a relation from Author to Book, | ||||
| 1184 | |||||
| 1185 | { 'foreign.author_id' => 'self.id' } | ||||
| 1186 | |||||
| 1187 | will result in the JOIN clause | ||||
| 1188 | |||||
| 1189 | author me JOIN book foreign ON foreign.author_id = me.id | ||||
| 1190 | |||||
| 1191 | You can specify as many foreign => self mappings as necessary. | ||||
| 1192 | |||||
| 1193 | Valid attributes are as follows: | ||||
| 1194 | |||||
| 1195 | =over 4 | ||||
| 1196 | |||||
| 1197 | =item join_type | ||||
| 1198 | |||||
| 1199 | Explicitly specifies the type of join to use in the relationship. Any | ||||
| 1200 | SQL join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in | ||||
| 1201 | the SQL command immediately before C<JOIN>. | ||||
| 1202 | |||||
| 1203 | =item proxy | ||||
| 1204 | |||||
| 1205 | An arrayref containing a list of accessors in the foreign class to proxy in | ||||
| 1206 | the main class. If, for example, you do the following: | ||||
| 1207 | |||||
| 1208 | CD->might_have(liner_notes => 'LinerNotes', undef, { | ||||
| 1209 | proxy => [ qw/notes/ ], | ||||
| 1210 | }); | ||||
| 1211 | |||||
| 1212 | Then, assuming LinerNotes has an accessor named notes, you can do: | ||||
| 1213 | |||||
| 1214 | my $cd = CD->find(1); | ||||
| 1215 | # set notes -- LinerNotes object is created if it doesn't exist | ||||
| 1216 | $cd->notes('Notes go here'); | ||||
| 1217 | |||||
| 1218 | =item accessor | ||||
| 1219 | |||||
| 1220 | Specifies the type of accessor that should be created for the | ||||
| 1221 | relationship. Valid values are C<single> (for when there is only a single | ||||
| 1222 | related object), C<multi> (when there can be many), and C<filter> (for | ||||
| 1223 | when there is a single related object, but you also want the relationship | ||||
| 1224 | accessor to double as a column accessor). For C<multi> accessors, an | ||||
| 1225 | add_to_* method is also created, which calls C<create_related> for the | ||||
| 1226 | relationship. | ||||
| 1227 | |||||
| 1228 | =back | ||||
| 1229 | |||||
| 1230 | Throws an exception if the condition is improperly supplied, or cannot | ||||
| 1231 | be resolved. | ||||
| 1232 | |||||
| 1233 | =cut | ||||
| 1234 | |||||
| 1235 | # spent 1.17ms (959µs+208µs) within DBIx::Class::ResultSource::add_relationship which was called 60 times, avg 19µs/call:
# 60 times (959µs+208µs) by DBIx::Class::ResultSourceProxy::add_relationship at line 44 of DBIx/Class/ResultSourceProxy.pm, avg 19µs/call | ||||
| 1236 | 60 | 62µs | my ($self, $rel, $f_source_name, $cond, $attrs) = @_; | ||
| 1237 | 60 | 13µs | $self->throw_exception("Can't create relationship without join condition") | ||
| 1238 | unless $cond; | ||||
| 1239 | 60 | 12µs | $attrs ||= {}; | ||
| 1240 | |||||
| 1241 | # Check foreign and self are right in cond | ||||
| 1242 | 60 | 59µs | if ( (ref $cond ||'') eq 'HASH') { | ||
| 1243 | 60 | 68µs | for (keys %$cond) { | ||
| 1244 | 60 | 353µs | 120 | 110µs | $self->throw_exception("Keys of condition should be of form 'foreign.col', not '$_'") # spent 110µs making 120 calls to DBIx::Class::ResultSource::CORE:match, avg 919ns/call |
| 1245 | if /\./ && !/^foreign\./; | ||||
| 1246 | } | ||||
| 1247 | } | ||||
| 1248 | |||||
| 1249 | 60 | 142µs | 2 | 97µs | my %rels = %{ $self->_relationships }; # spent 96µs making 1 call to DBIx::Class::ResultSource::_relationships
# spent 700ns making 1 call to DBIx::Class::ResultSource::Table::_relationships |
| 1250 | 60 | 197µs | $rels{$rel} = { class => $f_source_name, | ||
| 1251 | source => $f_source_name, | ||||
| 1252 | cond => $cond, | ||||
| 1253 | attrs => $attrs }; | ||||
| 1254 | 60 | 62µs | 1 | 1µs | $self->_relationships(\%rels); # spent 1µs making 1 call to DBIx::Class::ResultSource::Table::_relationships |
| 1255 | |||||
| 1256 | 60 | 150µs | return $self; | ||
| 1257 | |||||
| 1258 | # XXX disabled. doesn't work properly currently. skip in tests. | ||||
| 1259 | |||||
| 1260 | my $f_source = $self->schema->source($f_source_name); | ||||
| 1261 | unless ($f_source) { | ||||
| 1262 | $self->ensure_class_loaded($f_source_name); | ||||
| 1263 | $f_source = $f_source_name->result_source; | ||||
| 1264 | #my $s_class = ref($self->schema); | ||||
| 1265 | #$f_source_name =~ m/^${s_class}::(.*)$/; | ||||
| 1266 | #$self->schema->register_class(($1 || $f_source_name), $f_source_name); | ||||
| 1267 | #$f_source = $self->schema->source($f_source_name); | ||||
| 1268 | } | ||||
| 1269 | return unless $f_source; # Can't test rel without f_source | ||||
| 1270 | |||||
| 1271 | try { $self->_resolve_join($rel, 'me', {}, []) } | ||||
| 1272 | catch { | ||||
| 1273 | # If the resolve failed, back out and re-throw the error | ||||
| 1274 | delete $rels{$rel}; | ||||
| 1275 | $self->_relationships(\%rels); | ||||
| 1276 | $self->throw_exception("Error creating relationship $rel: $_"); | ||||
| 1277 | }; | ||||
| 1278 | |||||
| 1279 | 1; | ||||
| 1280 | } | ||||
| 1281 | |||||
| 1282 | =head2 relationships | ||||
| 1283 | |||||
| 1284 | =over 4 | ||||
| 1285 | |||||
| 1286 | =item Arguments: None | ||||
| 1287 | |||||
| 1288 | =item Return value: List of relationship names | ||||
| 1289 | |||||
| 1290 | =back | ||||
| 1291 | |||||
| 1292 | my @relnames = $source->relationships(); | ||||
| 1293 | |||||
| 1294 | Returns all relationship names for this source. | ||||
| 1295 | |||||
| 1296 | =cut | ||||
| 1297 | |||||
| 1298 | # spent 7.31ms (7.31+1µs) within DBIx::Class::ResultSource::relationships which was called 972 times, avg 8µs/call:
# 877 times (7.03ms+0s) by DBIx::Class::Relationship::CascadeActions::update at line 51 of DBIx/Class/Relationship/CascadeActions.pm, avg 8µs/call
# 60 times (162µs+0s) by DBIx::Class::ResultSource::reverse_relationship_info at line 1387, avg 3µs/call
# 35 times (121µs+1µs) by SQL::Translator::Parser::DBIx::Class::parse at line 139 of SQL/Translator/Parser/DBIx/Class.pm, avg 3µs/call | ||||
| 1299 | 972 | 9.03ms | 1 | 1µs | return keys %{shift->_relationships}; # spent 1µs making 1 call to DBIx::Class::ResultSource::Table::_relationships |
| 1300 | } | ||||
| 1301 | |||||
| 1302 | =head2 relationship_info | ||||
| 1303 | |||||
| 1304 | =over 4 | ||||
| 1305 | |||||
| 1306 | =item Arguments: $relname | ||||
| 1307 | |||||
| 1308 | =item Return value: Hashref of relation data, | ||||
| 1309 | |||||
| 1310 | =back | ||||
| 1311 | |||||
| 1312 | Returns a hash of relationship information for the specified relationship | ||||
| 1313 | name. The keys/values are as specified for L</add_relationship>. | ||||
| 1314 | |||||
| 1315 | =cut | ||||
| 1316 | |||||
| 1317 | # spent 58.9ms (58.9+600ns) within DBIx::Class::ResultSource::relationship_info which was called 14007 times, avg 4µs/call:
# 5476 times (34.8ms+0s) by DBIx::Class::ResultSourceProxy::relationship_info at line 86 of DBIx/Class/ResultSourceProxy.pm, avg 6µs/call
# 4155 times (8.41ms+0s) by DBIx::Class::ResultSource::related_source at line 1853, avg 2µs/call
# 3698 times (13.7ms+0s) by DBIx::Class::Relationship::CascadeActions::update at line 51 of DBIx/Class/Relationship/CascadeActions.pm, avg 4µs/call
# 147 times (801µs+0s) by DBIx::Class::Row::new at line 187 of DBIx/Class/Row.pm, avg 5µs/call
# 147 times (417µs+0s) by DBIx::Class::ResultSet::related_resultset at line 2863 of DBIx/Class/ResultSet.pm, avg 3µs/call
# 147 times (308µs+0s) by DBIx::Class::ResultSource::_resolve_join at line 1508, avg 2µs/call
# 60 times (153µs+600ns) by DBIx::Class::ResultSourceProxy::add_relationship at line 45 of DBIx/Class/ResultSourceProxy.pm, avg 3µs/call
# 60 times (147µs+0s) by SQL::Translator::Parser::DBIx::Class::parse at line 149 of SQL/Translator/Parser/DBIx/Class.pm, avg 2µs/call
# 60 times (87µs+0s) by DBIx::Class::ResultSource::reverse_relationship_info at line 1368, avg 1µs/call
# 57 times (105µs+0s) by DBIx::Class::ResultSource::reverse_relationship_info at line 1404, avg 2µs/call | ||||
| 1318 | 14007 | 11.4ms | my ($self, $rel) = @_; | ||
| 1319 | 14007 | 66.4ms | 1 | 600ns | return $self->_relationships->{$rel}; # spent 600ns making 1 call to DBIx::Class::ResultSource::Table::_relationships |
| 1320 | } | ||||
| 1321 | |||||
| 1322 | =head2 has_relationship | ||||
| 1323 | |||||
| 1324 | =over 4 | ||||
| 1325 | |||||
| 1326 | =item Arguments: $rel | ||||
| 1327 | |||||
| 1328 | =item Return value: 1/0 (true/false) | ||||
| 1329 | |||||
| 1330 | =back | ||||
| 1331 | |||||
| 1332 | Returns true if the source has a relationship of this name, false otherwise. | ||||
| 1333 | |||||
| 1334 | =cut | ||||
| 1335 | |||||
| 1336 | # spent 15.3ms (15.3+600ns) within DBIx::Class::ResultSource::has_relationship which was called 4302 times, avg 4µs/call:
# 4155 times (14.6ms+600ns) by DBIx::Class::ResultSource::related_source at line 1846, avg 4µs/call
# 147 times (762µs+0s) by DBIx::Class::Row::insert at line 375 of DBIx/Class/Row.pm, avg 5µs/call | ||||
| 1337 | 4302 | 2.57ms | my ($self, $rel) = @_; | ||
| 1338 | 4302 | 18.1ms | 1 | 600ns | return exists $self->_relationships->{$rel}; # spent 600ns making 1 call to DBIx::Class::ResultSource::Table::_relationships |
| 1339 | } | ||||
| 1340 | |||||
| 1341 | =head2 reverse_relationship_info | ||||
| 1342 | |||||
| 1343 | =over 4 | ||||
| 1344 | |||||
| 1345 | =item Arguments: $relname | ||||
| 1346 | |||||
| 1347 | =item Return value: Hashref of relationship data | ||||
| 1348 | |||||
| 1349 | =back | ||||
| 1350 | |||||
| 1351 | Looks through all the relationships on the source this relationship | ||||
| 1352 | points to, looking for one whose condition is the reverse of the | ||||
| 1353 | condition on this relationship. | ||||
| 1354 | |||||
| 1355 | A common use of this is to find the name of the C<belongs_to> relation | ||||
| 1356 | opposing a C<has_many> relation. For definition of these look in | ||||
| 1357 | L<DBIx::Class::Relationship>. | ||||
| 1358 | |||||
| 1359 | The returned hashref is keyed by the name of the opposing | ||||
| 1360 | relationship, and contains its data in the same manner as | ||||
| 1361 | L</relationship_info>. | ||||
| 1362 | |||||
| 1363 | =cut | ||||
| 1364 | |||||
| 1365 | # spent 25.0ms (3.69+21.3) within DBIx::Class::ResultSource::reverse_relationship_info which was called 60 times, avg 416µs/call:
# 60 times (3.69ms+21.3ms) by SQL::Translator::Parser::DBIx::Class::parse at line 169 of SQL/Translator/Parser/DBIx/Class.pm, avg 416µs/call | ||||
| 1366 | 60 | 38µs | my ($self, $rel) = @_; | ||
| 1367 | |||||
| 1368 | 60 | 67µs | 60 | 87µs | my $rel_info = $self->relationship_info($rel) # spent 87µs making 60 calls to DBIx::Class::ResultSource::relationship_info, avg 1µs/call |
| 1369 | or $self->throw_exception("No such relationship '$rel'"); | ||||
| 1370 | |||||
| 1371 | 60 | 29µs | my $ret = {}; | ||
| 1372 | |||||
| 1373 | 60 | 42µs | return $ret unless ((ref $rel_info->{cond}) eq 'HASH'); | ||
| 1374 | |||||
| 1375 | 60 | 122µs | 60 | 683µs | my $stripped_cond = $self->__strip_relcond ($rel_info->{cond}); # spent 683µs making 60 calls to DBIx::Class::ResultSource::__strip_relcond, avg 11µs/call |
| 1376 | |||||
| 1377 | my $rsrc_schema_moniker = $self->source_name | ||||
| 1378 | 120 | 388µs | 121 | 861µs | # spent 290µs (197+93) within DBIx::Class::ResultSource::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/ResultSource.pm:1378] which was called 60 times, avg 5µs/call:
# 60 times (197µs+93µs) by Try::Tiny::try at line 71 of Try/Tiny.pm, avg 5µs/call # spent 767µs making 60 calls to Try::Tiny::try, avg 13µs/call
# spent 93µs making 60 calls to DBIx::Class::ResultSource::schema, avg 2µs/call
# spent 700ns making 1 call to DBIx::Class::ResultSource::Table::source_name |
| 1379 | |||||
| 1380 | # this may be a partial schema or something else equally esoteric | ||||
| 1381 | 60 | 155µs | 60 | 2.95ms | # spent 3.12ms (175µs+2.95) within DBIx::Class::ResultSource::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/ResultSource.pm:1381] which was called 60 times, avg 52µs/call:
# 60 times (175µs+2.95ms) by Try::Tiny::try at line 71 of Try/Tiny.pm, avg 52µs/call # spent 2.95ms making 60 calls to DBIx::Class::ResultSource::related_source, avg 49µs/call |
| 1382 | 60 | 173µs | 60 | 3.61ms | or return $ret; # spent 3.61ms making 60 calls to Try::Tiny::try, avg 60µs/call |
| 1383 | |||||
| 1384 | # Get all the relationships for that source that related to this source | ||||
| 1385 | # whose foreign column set are our self columns on $rel and whose self | ||||
| 1386 | # columns are our foreign columns on $rel | ||||
| 1387 | 60 | 170µs | 60 | 162µs | foreach my $other_rel ($other_rsrc->relationships) { # spent 162µs making 60 calls to DBIx::Class::ResultSource::relationships, avg 3µs/call |
| 1388 | |||||
| 1389 | # only consider stuff that points back to us | ||||
| 1390 | # "us" here is tricky - if we are in a schema registration, we want | ||||
| 1391 | # to use the source_names, otherwise we will use the actual classes | ||||
| 1392 | |||||
| 1393 | # the schema may be partial | ||||
| 1394 | 210 | 509µs | 210 | 10.2ms | # spent 10.7ms (557µs+10.2) within DBIx::Class::ResultSource::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/ResultSource.pm:1394] which was called 210 times, avg 51µs/call:
# 210 times (557µs+10.2ms) by Try::Tiny::try at line 71 of Try/Tiny.pm, avg 51µs/call # spent 10.2ms making 210 calls to DBIx::Class::ResultSource::related_source, avg 48µs/call |
| 1395 | 210 | 555µs | 210 | 12.4ms | or next; # spent 12.4ms making 210 calls to Try::Tiny::try, avg 59µs/call |
| 1396 | |||||
| 1397 | 420 | 980µs | 420 | 2.76ms | # spent 939µs (614+325) within DBIx::Class::ResultSource::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/ResultSource.pm:1397] which was called 210 times, avg 4µs/call:
# 210 times (614µs+325µs) by Try::Tiny::try at line 71 of Try/Tiny.pm, avg 4µs/call # spent 2.43ms making 210 calls to Try::Tiny::try, avg 12µs/call
# spent 325µs making 210 calls to DBIx::Class::ResultSource::schema, avg 2µs/call |
| 1398 | 210 | 283µs | 1 | 700ns | next unless $rsrc_schema_moniker eq $roundtrip_rsrc->source_name; # spent 700ns making 1 call to DBIx::Class::ResultSource::Table::source_name |
| 1399 | } | ||||
| 1400 | else { | ||||
| 1401 | next unless $self->result_class eq $roundtrip_rsrc->result_class; | ||||
| 1402 | } | ||||
| 1403 | |||||
| 1404 | 57 | 75µs | 57 | 105µs | my $other_rel_info = $other_rsrc->relationship_info($other_rel); # spent 105µs making 57 calls to DBIx::Class::ResultSource::relationship_info, avg 2µs/call |
| 1405 | |||||
| 1406 | # this can happen when we have a self-referential class | ||||
| 1407 | 57 | 51µs | next if $other_rel_info eq $rel_info; | ||
| 1408 | |||||
| 1409 | 56 | 40µs | next unless ref $other_rel_info->{cond} eq 'HASH'; | ||
| 1410 | 56 | 94µs | 56 | 554µs | my $other_stripped_cond = $self->__strip_relcond($other_rel_info->{cond}); # spent 554µs making 56 calls to DBIx::Class::ResultSource::__strip_relcond, avg 10µs/call |
| 1411 | |||||
| 1412 | 56 | 407µs | 110 | 498µs | $ret->{$other_rel} = $other_rel_info if ( # spent 498µs making 110 calls to DBIx::Class::ResultSource::_compare_relationship_keys, avg 5µs/call |
| 1413 | $self->_compare_relationship_keys ( | ||||
| 1414 | [ keys %$stripped_cond ], [ values %$other_stripped_cond ] | ||||
| 1415 | ) | ||||
| 1416 | and | ||||
| 1417 | $self->_compare_relationship_keys ( | ||||
| 1418 | [ values %$stripped_cond ], [ keys %$other_stripped_cond ] | ||||
| 1419 | ) | ||||
| 1420 | ); | ||||
| 1421 | } | ||||
| 1422 | |||||
| 1423 | 60 | 163µs | return $ret; | ||
| 1424 | } | ||||
| 1425 | |||||
| 1426 | # all this does is removes the foreign/self prefix from a condition | ||||
| 1427 | # spent 1.24ms (808µs+429µs) within DBIx::Class::ResultSource::__strip_relcond which was called 116 times, avg 11µs/call:
# 60 times (440µs+244µs) by DBIx::Class::ResultSource::reverse_relationship_info at line 1375, avg 11µs/call
# 56 times (368µs+186µs) by DBIx::Class::ResultSource::reverse_relationship_info at line 1410, avg 10µs/call | ||||
| 1428 | +{ | ||||
| 1429 | 232 | 796µs | 232 | 429µs | map # spent 429µs making 232 calls to DBIx::Class::ResultSource::CORE:match, avg 2µs/call |
| 1430 | 116 | 123µs | { map { /^ (?:foreign|self) \. (\w+) $/x } ($_, $_[1]{$_}) } | ||
| 1431 | 116 | 424µs | keys %{$_[1]} | ||
| 1432 | } | ||||
| 1433 | } | ||||
| 1434 | |||||
| 1435 | sub compare_relationship_keys { | ||||
| 1436 | carp 'compare_relationship_keys is a private method, stop calling it'; | ||||
| 1437 | my $self = shift; | ||||
| 1438 | $self->_compare_relationship_keys (@_); | ||||
| 1439 | } | ||||
| 1440 | |||||
| 1441 | # Returns true if both sets of keynames are the same, false otherwise. | ||||
| 1442 | # spent 765µs (684+81) within DBIx::Class::ResultSource::_compare_relationship_keys which was called 154 times, avg 5µs/call:
# 110 times (443µs+55µs) by DBIx::Class::ResultSource::reverse_relationship_info at line 1412, avg 5µs/call
# 38 times (217µs+24µs) by SQL::Translator::Parser::DBIx::Class::parse at line 130 of SQL/Translator/Parser/DBIx/Class.pm, avg 6µs/call
# 6 times (24µs+3µs) by SQL::Translator::Parser::DBIx::Class::parse at line 197 of SQL/Translator/Parser/DBIx/Class.pm, avg 5µs/call | ||||
| 1443 | # my ($self, $keys1, $keys2) = @_; | ||||
| 1444 | return | ||||
| 1445 | join ("\x00", sort @{$_[1]}) | ||||
| 1446 | eq | ||||
| 1447 | 154 | 887µs | 308 | 81µs | join ("\x00", sort @{$_[2]}) # spent 81µs making 308 calls to DBIx::Class::ResultSource::CORE:sort, avg 263ns/call |
| 1448 | ; | ||||
| 1449 | } | ||||
| 1450 | |||||
| 1451 | # Returns the {from} structure used to express JOIN conditions | ||||
| 1452 | # spent 25.3ms (7.18+18.2) within DBIx::Class::ResultSource::_resolve_join which was called 294 times, avg 86µs/call:
# 147 times (6.21ms+18.2ms) by DBIx::Class::ResultSet::_chain_relationship at line 3129 of DBIx/Class/ResultSet.pm, avg 166µs/call
# 147 times (971µs+0s) by DBIx::Class::ResultSet::_chain_relationship at line 3102 of DBIx/Class/ResultSet.pm, avg 7µs/call | ||||
| 1453 | 294 | 354µs | my ($self, $join, $alias, $seen, $jpath, $parent_force_left) = @_; | ||
| 1454 | |||||
| 1455 | # we need a supplied one, because we do in-place modifications, no returns | ||||
| 1456 | 294 | 191µs | $self->throw_exception ('You must supply a seen hashref as the 3rd argument to _resolve_join') | ||
| 1457 | unless ref $seen eq 'HASH'; | ||||
| 1458 | |||||
| 1459 | 294 | 158µs | $self->throw_exception ('You must supply a joinpath arrayref as the 4th argument to _resolve_join') | ||
| 1460 | unless ref $jpath eq 'ARRAY'; | ||||
| 1461 | |||||
| 1462 | 294 | 152µs | $jpath = [@$jpath]; # copy | ||
| 1463 | |||||
| 1464 | 294 | 850µs | if (not defined $join or not length $join) { | ||
| 1465 | return (); | ||||
| 1466 | } | ||||
| 1467 | elsif (ref $join eq 'ARRAY') { | ||||
| 1468 | return | ||||
| 1469 | map { | ||||
| 1470 | $self->_resolve_join($_, $alias, $seen, $jpath, $parent_force_left); | ||||
| 1471 | } @$join; | ||||
| 1472 | } | ||||
| 1473 | elsif (ref $join eq 'HASH') { | ||||
| 1474 | |||||
| 1475 | my @ret; | ||||
| 1476 | for my $rel (keys %$join) { | ||||
| 1477 | |||||
| 1478 | my $rel_info = $self->relationship_info($rel) | ||||
| 1479 | or $self->throw_exception("No such relationship '$rel' on " . $self->source_name); | ||||
| 1480 | |||||
| 1481 | my $force_left = $parent_force_left; | ||||
| 1482 | $force_left ||= lc($rel_info->{attrs}{join_type}||'') eq 'left'; | ||||
| 1483 | |||||
| 1484 | # the actual seen value will be incremented by the recursion | ||||
| 1485 | my $as = $self->storage->relname_to_table_alias( | ||||
| 1486 | $rel, ($seen->{$rel} && $seen->{$rel} + 1) | ||||
| 1487 | ); | ||||
| 1488 | |||||
| 1489 | push @ret, ( | ||||
| 1490 | $self->_resolve_join($rel, $alias, $seen, [@$jpath], $force_left), | ||||
| 1491 | $self->related_source($rel)->_resolve_join( | ||||
| 1492 | $join->{$rel}, $as, $seen, [@$jpath, { $rel => $as }], $force_left | ||||
| 1493 | ) | ||||
| 1494 | ); | ||||
| 1495 | } | ||||
| 1496 | return @ret; | ||||
| 1497 | |||||
| 1498 | } | ||||
| 1499 | elsif (ref $join) { | ||||
| 1500 | $self->throw_exception("No idea how to resolve join reftype ".ref $join); | ||||
| 1501 | } | ||||
| 1502 | else { | ||||
| 1503 | 147 | 162µs | my $count = ++$seen->{$join}; | ||
| 1504 | 147 | 985µs | 294 | 4.09ms | my $as = $self->storage->relname_to_table_alias( # spent 3.41ms making 147 calls to DBIx::Class::ResultSource::storage, avg 23µs/call
# spent 681µs making 147 calls to DBIx::Class::Storage::DBI::relname_to_table_alias, avg 5µs/call |
| 1505 | $join, ($count > 1 && $count) | ||||
| 1506 | ); | ||||
| 1507 | |||||
| 1508 | 147 | 275µs | 147 | 308µs | my $rel_info = $self->relationship_info($join) # spent 308µs making 147 calls to DBIx::Class::ResultSource::relationship_info, avg 2µs/call |
| 1509 | or $self->throw_exception("No such relationship $join on " . $self->source_name); | ||||
| 1510 | |||||
| 1511 | 147 | 445µs | 147 | 9.32ms | my $rel_src = $self->related_source($join); # spent 9.32ms making 147 calls to DBIx::Class::ResultSource::related_source, avg 63µs/call |
| 1512 | return [ { $as => $rel_src->from, | ||||
| 1513 | -rsrc => $rel_src, | ||||
| 1514 | -join_type => $parent_force_left | ||||
| 1515 | ? 'left' | ||||
| 1516 | : $rel_info->{attrs}{join_type} | ||||
| 1517 | , | ||||
| 1518 | -join_path => [@$jpath, { $join => $as } ], | ||||
| 1519 | -is_single => ( | ||||
| 1520 | $rel_info->{attrs}{accessor} | ||||
| 1521 | && | ||||
| 1522 | 294 | 3.37ms | 441 | 4.44ms | first { $rel_info->{attrs}{accessor} eq $_ } (qw/single filter/) # spent 3.74ms making 147 calls to DBIx::Class::ResultSource::_resolve_condition, avg 25µs/call
# spent 397µs making 147 calls to List::Util::first, avg 3µs/call
# spent 302µs making 147 calls to DBIx::Class::ResultSource::Table::from, avg 2µs/call |
| 1523 | ), | ||||
| 1524 | -alias => $as, | ||||
| 1525 | -relation_chain_depth => $seen->{-relation_chain_depth} || 0, | ||||
| 1526 | }, | ||||
| 1527 | scalar $self->_resolve_condition($rel_info->{cond}, $as, $alias, $join) | ||||
| 1528 | ]; | ||||
| 1529 | } | ||||
| 1530 | } | ||||
| 1531 | |||||
| 1532 | sub pk_depends_on { | ||||
| 1533 | carp 'pk_depends_on is a private method, stop calling it'; | ||||
| 1534 | my $self = shift; | ||||
| 1535 | $self->_pk_depends_on (@_); | ||||
| 1536 | } | ||||
| 1537 | |||||
| 1538 | # Determines whether a relation is dependent on an object from this source | ||||
| 1539 | # having already been inserted. Takes the name of the relationship and a | ||||
| 1540 | # hashref of columns of the related object. | ||||
| 1541 | sub _pk_depends_on { | ||||
| 1542 | my ($self, $relname, $rel_data) = @_; | ||||
| 1543 | |||||
| 1544 | my $relinfo = $self->relationship_info($relname); | ||||
| 1545 | |||||
| 1546 | # don't assume things if the relationship direction is specified | ||||
| 1547 | return $relinfo->{attrs}{is_foreign_key_constraint} | ||||
| 1548 | if exists ($relinfo->{attrs}{is_foreign_key_constraint}); | ||||
| 1549 | |||||
| 1550 | my $cond = $relinfo->{cond}; | ||||
| 1551 | return 0 unless ref($cond) eq 'HASH'; | ||||
| 1552 | |||||
| 1553 | # map { foreign.foo => 'self.bar' } to { bar => 'foo' } | ||||
| 1554 | my $keyhash = { map { my $x = $_; $x =~ s/.*\.//; $x; } reverse %$cond }; | ||||
| 1555 | |||||
| 1556 | # assume anything that references our PK probably is dependent on us | ||||
| 1557 | # rather than vice versa, unless the far side is (a) defined or (b) | ||||
| 1558 | # auto-increment | ||||
| 1559 | my $rel_source = $self->related_source($relname); | ||||
| 1560 | |||||
| 1561 | foreach my $p ($self->primary_columns) { | ||||
| 1562 | if (exists $keyhash->{$p}) { | ||||
| 1563 | unless (defined($rel_data->{$keyhash->{$p}}) | ||||
| 1564 | || $rel_source->column_info($keyhash->{$p}) | ||||
| 1565 | ->{is_auto_increment}) { | ||||
| 1566 | return 0; | ||||
| 1567 | } | ||||
| 1568 | } | ||||
| 1569 | } | ||||
| 1570 | |||||
| 1571 | return 1; | ||||
| 1572 | } | ||||
| 1573 | |||||
| 1574 | sub resolve_condition { | ||||
| 1575 | carp 'resolve_condition is a private method, stop calling it'; | ||||
| 1576 | my $self = shift; | ||||
| 1577 | $self->_resolve_condition (@_); | ||||
| 1578 | } | ||||
| 1579 | |||||
| 1580 | 1 | 300ns | our $UNRESOLVABLE_CONDITION = \ '1 = 0'; | ||
| 1581 | |||||
| 1582 | # Resolves the passed condition to a concrete query fragment and a flag | ||||
| 1583 | # indicating whether this is a cross-table condition. Also an optional | ||||
| 1584 | # list of non-triviail values (notmally conditions) returned as a part | ||||
| 1585 | # of a joinfree condition hash | ||||
| 1586 | # spent 229ms (154+75.5) within DBIx::Class::ResultSource::_resolve_condition which was called 5332 times, avg 43µs/call:
# 3531 times (86.3ms+41.9ms) by DBIx::Class::Relationship::Base::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/Relationship/Base.pm:422] at line 421 of DBIx/Class/Relationship/Base.pm, avg 36µs/call
# 1654 times (64.4ms+33.0ms) by Tapper::Schema::TestrunDB::Result::QueueHost::queue or Tapper::Schema::TestrunDB::Result::Testrun::scenario_element or Tapper::Schema::TestrunDB::Result::TestrunScheduling::host or Tapper::Schema::TestrunDB::Result::TestrunScheduling::queue or Tapper::Schema::TestrunDB::Result::TestrunScheduling::testrun at line 34 of DBIx/Class/Relationship/Accessor.pm, avg 59µs/call
# 147 times (3.15ms+588µs) by DBIx::Class::ResultSource::_resolve_join at line 1522, avg 25µs/call | ||||
| 1587 | 5332 | 7.30ms | my ($self, $cond, $as, $for, $relname) = @_; | ||
| 1588 | |||||
| 1589 | 5332 | 25.1ms | 5332 | 7.55ms | my $obj_rel = !!blessed $for; # spent 7.55ms making 5332 calls to Scalar::Util::blessed, avg 1µs/call |
| 1590 | |||||
| 1591 | 5332 | 10.1ms | if (ref $cond eq 'CODE') { | ||
| 1592 | my $relalias = $obj_rel ? 'me' : $as; | ||||
| 1593 | |||||
| 1594 | my ($crosstable_cond, $joinfree_cond) = $cond->({ | ||||
| 1595 | self_alias => $obj_rel ? $as : $for, | ||||
| 1596 | foreign_alias => $relalias, | ||||
| 1597 | self_resultsource => $self, | ||||
| 1598 | foreign_relname => $relname || ($obj_rel ? $as : $for), | ||||
| 1599 | self_rowobj => $obj_rel ? $for : undef | ||||
| 1600 | }); | ||||
| 1601 | |||||
| 1602 | my $cond_cols; | ||||
| 1603 | if ($joinfree_cond) { | ||||
| 1604 | |||||
| 1605 | # FIXME sanity check until things stabilize, remove at some point | ||||
| 1606 | $self->throw_exception ( | ||||
| 1607 | "A join-free condition returned for relationship '$relname' without a row-object to chain from" | ||||
| 1608 | ) unless $obj_rel; | ||||
| 1609 | |||||
| 1610 | # FIXME another sanity check | ||||
| 1611 | if ( | ||||
| 1612 | ref $joinfree_cond ne 'HASH' | ||||
| 1613 | or | ||||
| 1614 | first { $_ !~ /^\Q$relalias.\E.+/ } keys %$joinfree_cond | ||||
| 1615 | ) { | ||||
| 1616 | $self->throw_exception ( | ||||
| 1617 | "The join-free condition returned for relationship '$relname' must be a hash " | ||||
| 1618 | .'reference with all keys being valid columns on the related result source' | ||||
| 1619 | ); | ||||
| 1620 | } | ||||
| 1621 | |||||
| 1622 | # normalize | ||||
| 1623 | for (values %$joinfree_cond) { | ||||
| 1624 | $_ = $_->{'='} if ( | ||||
| 1625 | ref $_ eq 'HASH' | ||||
| 1626 | and | ||||
| 1627 | keys %$_ == 1 | ||||
| 1628 | and | ||||
| 1629 | exists $_->{'='} | ||||
| 1630 | ); | ||||
| 1631 | } | ||||
| 1632 | |||||
| 1633 | # see which parts of the joinfree cond are conditionals | ||||
| 1634 | my $relcol_list = { map { $_ => 1 } $self->related_source($relname)->columns }; | ||||
| 1635 | |||||
| 1636 | for my $c (keys %$joinfree_cond) { | ||||
| 1637 | my ($colname) = $c =~ /^ (?: \Q$relalias.\E )? (.+)/x; | ||||
| 1638 | |||||
| 1639 | unless ($relcol_list->{$colname}) { | ||||
| 1640 | push @$cond_cols, $colname; | ||||
| 1641 | next; | ||||
| 1642 | } | ||||
| 1643 | |||||
| 1644 | if ( | ||||
| 1645 | ref $joinfree_cond->{$c} | ||||
| 1646 | and | ||||
| 1647 | ref $joinfree_cond->{$c} ne 'SCALAR' | ||||
| 1648 | and | ||||
| 1649 | ref $joinfree_cond->{$c} ne 'REF' | ||||
| 1650 | ) { | ||||
| 1651 | push @$cond_cols, $colname; | ||||
| 1652 | next; | ||||
| 1653 | } | ||||
| 1654 | } | ||||
| 1655 | |||||
| 1656 | return wantarray ? ($joinfree_cond, 0, $cond_cols) : $joinfree_cond; | ||||
| 1657 | } | ||||
| 1658 | else { | ||||
| 1659 | return wantarray ? ($crosstable_cond, 1) : $crosstable_cond; | ||||
| 1660 | } | ||||
| 1661 | } | ||||
| 1662 | elsif (ref $cond eq 'HASH') { | ||||
| 1663 | 5332 | 2.06ms | my %ret; | ||
| 1664 | 5332 | 11.5ms | foreach my $k (keys %{$cond}) { | ||
| 1665 | 5332 | 4.82ms | my $v = $cond->{$k}; | ||
| 1666 | # XXX should probably check these are valid columns | ||||
| 1667 | 5332 | 38.5ms | 5332 | 19.6ms | $k =~ s/^foreign\.// || # spent 19.6ms making 5332 calls to DBIx::Class::ResultSource::CORE:subst, avg 4µs/call |
| 1668 | $self->throw_exception("Invalid rel cond key ${k}"); | ||||
| 1669 | 5332 | 16.3ms | 5332 | 4.87ms | $v =~ s/^self\.// || # spent 4.87ms making 5332 calls to DBIx::Class::ResultSource::CORE:subst, avg 914ns/call |
| 1670 | $self->throw_exception("Invalid rel cond val ${v}"); | ||||
| 1671 | 5332 | 10.00ms | if (ref $for) { # Object | ||
| 1672 | #warn "$self $k $for $v"; | ||||
| 1673 | 5185 | 13.0ms | 5185 | 25.7ms | unless ($for->has_column_loaded($v)) { # spent 25.7ms making 5185 calls to DBIx::Class::Row::has_column_loaded, avg 5µs/call |
| 1674 | if ($for->in_storage) { | ||||
| 1675 | $self->throw_exception(sprintf | ||||
| 1676 | "Unable to resolve relationship '%s' from object %s: column '%s' not " | ||||
| 1677 | . 'loaded from storage (or not passed to new() prior to insert()). You ' | ||||
| 1678 | . 'probably need to call ->discard_changes to get the server-side defaults ' | ||||
| 1679 | . 'from the database.', | ||||
| 1680 | $as, | ||||
| 1681 | $for, | ||||
| 1682 | $v, | ||||
| 1683 | ); | ||||
| 1684 | } | ||||
| 1685 | return $UNRESOLVABLE_CONDITION; | ||||
| 1686 | } | ||||
| 1687 | 5185 | 15.5ms | 5185 | 17.7ms | $ret{$k} = $for->get_column($v); # spent 17.7ms making 5185 calls to DBIx::Class::Row::get_column, avg 3µs/call |
| 1688 | #$ret{$k} = $for->get_column($v) if $for->has_column_loaded($v); | ||||
| 1689 | #warn %ret; | ||||
| 1690 | } elsif (!defined $for) { # undef, i.e. "no object" | ||||
| 1691 | $ret{$k} = undef; | ||||
| 1692 | } elsif (ref $as eq 'HASH') { # reverse hashref | ||||
| 1693 | $ret{$v} = $as->{$k}; | ||||
| 1694 | } elsif (ref $as) { # reverse object | ||||
| 1695 | $ret{$v} = $as->get_column($k); | ||||
| 1696 | } elsif (!defined $as) { # undef, i.e. "no reverse object" | ||||
| 1697 | $ret{$v} = undef; | ||||
| 1698 | } else { | ||||
| 1699 | 147 | 566µs | $ret{"${as}.${k}"} = { -ident => "${for}.${v}" }; | ||
| 1700 | } | ||||
| 1701 | } | ||||
| 1702 | |||||
| 1703 | return wantarray | ||||
| 1704 | 5332 | 24.5ms | ? ( \%ret, ($obj_rel || !defined $as || ref $as) ? 0 : 1 ) | ||
| 1705 | : \%ret | ||||
| 1706 | ; | ||||
| 1707 | } | ||||
| 1708 | elsif (ref $cond eq 'ARRAY') { | ||||
| 1709 | my (@ret, $crosstable); | ||||
| 1710 | for (@$cond) { | ||||
| 1711 | my ($cond, $crosstab) = $self->_resolve_condition($_, $as, $for, $relname); | ||||
| 1712 | push @ret, $cond; | ||||
| 1713 | $crosstable ||= $crosstab; | ||||
| 1714 | } | ||||
| 1715 | return wantarray ? (\@ret, $crosstable) : \@ret; | ||||
| 1716 | } | ||||
| 1717 | else { | ||||
| 1718 | $self->throw_exception ("Can't handle condition $cond for relationship '$relname' yet :("); | ||||
| 1719 | } | ||||
| 1720 | } | ||||
| 1721 | |||||
| 1722 | # Accepts one or more relationships for the current source and returns an | ||||
| 1723 | # array of column names for each of those relationships. Column names are | ||||
| 1724 | # prefixed relative to the current source, in accordance with where they appear | ||||
| 1725 | # in the supplied relationships. | ||||
| 1726 | |||||
| 1727 | sub _resolve_prefetch { | ||||
| 1728 | my ($self, $pre, $alias, $alias_map, $order, $collapse, $pref_path) = @_; | ||||
| 1729 | $pref_path ||= []; | ||||
| 1730 | |||||
| 1731 | if (not defined $pre or not length $pre) { | ||||
| 1732 | return (); | ||||
| 1733 | } | ||||
| 1734 | elsif( ref $pre eq 'ARRAY' ) { | ||||
| 1735 | return | ||||
| 1736 | map { $self->_resolve_prefetch( $_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ) } | ||||
| 1737 | @$pre; | ||||
| 1738 | } | ||||
| 1739 | elsif( ref $pre eq 'HASH' ) { | ||||
| 1740 | my @ret = | ||||
| 1741 | map { | ||||
| 1742 | $self->_resolve_prefetch($_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ), | ||||
| 1743 | $self->related_source($_)->_resolve_prefetch( | ||||
| 1744 | $pre->{$_}, "${alias}.$_", $alias_map, $order, $collapse, [ @$pref_path, $_] ) | ||||
| 1745 | } keys %$pre; | ||||
| 1746 | return @ret; | ||||
| 1747 | } | ||||
| 1748 | elsif( ref $pre ) { | ||||
| 1749 | $self->throw_exception( | ||||
| 1750 | "don't know how to resolve prefetch reftype ".ref($pre)); | ||||
| 1751 | } | ||||
| 1752 | else { | ||||
| 1753 | my $p = $alias_map; | ||||
| 1754 | $p = $p->{$_} for (@$pref_path, $pre); | ||||
| 1755 | |||||
| 1756 | $self->throw_exception ( | ||||
| 1757 | "Unable to resolve prefetch '$pre' - join alias map does not contain an entry for path: " | ||||
| 1758 | . join (' -> ', @$pref_path, $pre) | ||||
| 1759 | ) if (ref $p->{-join_aliases} ne 'ARRAY' or not @{$p->{-join_aliases}} ); | ||||
| 1760 | |||||
| 1761 | my $as = shift @{$p->{-join_aliases}}; | ||||
| 1762 | |||||
| 1763 | my $rel_info = $self->relationship_info( $pre ); | ||||
| 1764 | $self->throw_exception( $self->source_name . " has no such relationship '$pre'" ) | ||||
| 1765 | unless $rel_info; | ||||
| 1766 | my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : ''); | ||||
| 1767 | my $rel_source = $self->related_source($pre); | ||||
| 1768 | |||||
| 1769 | if ($rel_info->{attrs}{accessor} && $rel_info->{attrs}{accessor} eq 'multi') { | ||||
| 1770 | $self->throw_exception( | ||||
| 1771 | "Can't prefetch has_many ${pre} (join cond too complex)") | ||||
| 1772 | unless ref($rel_info->{cond}) eq 'HASH'; | ||||
| 1773 | my $dots = @{[$as_prefix =~ m/\./g]} + 1; # +1 to match the ".${as_prefix}" | ||||
| 1774 | |||||
| 1775 | if (my ($fail) = grep { @{[$_ =~ m/\./g]} == $dots } | ||||
| 1776 | keys %{$collapse}) { | ||||
| 1777 | my ($last) = ($fail =~ /([^\.]+)$/); | ||||
| 1778 | carp ( | ||||
| 1779 | "Prefetching multiple has_many rels ${last} and ${pre} " | ||||
| 1780 | .(length($as_prefix) | ||||
| 1781 | ? "at the same level (${as_prefix}) " | ||||
| 1782 | : "at top level " | ||||
| 1783 | ) | ||||
| 1784 | . 'will explode the number of row objects retrievable via ->next or ->all. ' | ||||
| 1785 | . 'Use at your own risk.' | ||||
| 1786 | ); | ||||
| 1787 | } | ||||
| 1788 | |||||
| 1789 | #my @col = map { (/^self\.(.+)$/ ? ("${as_prefix}.$1") : ()); } | ||||
| 1790 | # values %{$rel_info->{cond}}; | ||||
| 1791 | $collapse->{".${as_prefix}${pre}"} = [ $rel_source->_pri_cols ]; | ||||
| 1792 | # action at a distance. prepending the '.' allows simpler code | ||||
| 1793 | # in ResultSet->_collapse_result | ||||
| 1794 | my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); } | ||||
| 1795 | keys %{$rel_info->{cond}}; | ||||
| 1796 | push @$order, map { "${as}.$_" } @key; | ||||
| 1797 | |||||
| 1798 | if (my $rel_order = $rel_info->{attrs}{order_by}) { | ||||
| 1799 | # this is kludgy and incomplete, I am well aware | ||||
| 1800 | # but the parent method is going away entirely anyway | ||||
| 1801 | # so sod it | ||||
| 1802 | my $sql_maker = $self->storage->sql_maker; | ||||
| 1803 | my ($orig_ql, $orig_qr) = $sql_maker->_quote_chars; | ||||
| 1804 | my $sep = $sql_maker->name_sep; | ||||
| 1805 | |||||
| 1806 | # install our own quoter, so we can catch unqualified stuff | ||||
| 1807 | local $sql_maker->{quote_char} = ["\x00", "\xFF"]; | ||||
| 1808 | |||||
| 1809 | my $quoted_prefix = "\x00${as}\xFF"; | ||||
| 1810 | |||||
| 1811 | for my $chunk ( $sql_maker->_order_by_chunks ($rel_order) ) { | ||||
| 1812 | my @bind; | ||||
| 1813 | ($chunk, @bind) = @$chunk if ref $chunk; | ||||
| 1814 | |||||
| 1815 | $chunk = "${quoted_prefix}${sep}${chunk}" | ||||
| 1816 | unless $chunk =~ /\Q$sep/; | ||||
| 1817 | |||||
| 1818 | $chunk =~ s/\x00/$orig_ql/g; | ||||
| 1819 | $chunk =~ s/\xFF/$orig_qr/g; | ||||
| 1820 | push @$order, \[$chunk, @bind]; | ||||
| 1821 | } | ||||
| 1822 | } | ||||
| 1823 | } | ||||
| 1824 | |||||
| 1825 | return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] } | ||||
| 1826 | $rel_source->columns; | ||||
| 1827 | } | ||||
| 1828 | } | ||||
| 1829 | |||||
| 1830 | =head2 related_source | ||||
| 1831 | |||||
| 1832 | =over 4 | ||||
| 1833 | |||||
| 1834 | =item Arguments: $relname | ||||
| 1835 | |||||
| 1836 | =item Return value: $source | ||||
| 1837 | |||||
| 1838 | =back | ||||
| 1839 | |||||
| 1840 | Returns the result source object for the given relationship. | ||||
| 1841 | |||||
| 1842 | =cut | ||||
| 1843 | |||||
| 1844 | # spent 333ms (66.6+266) within DBIx::Class::ResultSource::related_source which was called 4155 times, avg 80µs/call:
# 3531 times (59.8ms+239ms) by DBIx::Class::Relationship::Base::related_resultset at line 493 of DBIx/Class/Relationship/Base.pm, avg 85µs/call
# 210 times (2.04ms+8.12ms) by DBIx::Class::ResultSource::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/ResultSource.pm:1394] at line 1394, avg 48µs/call
# 147 times (1.89ms+7.43ms) by DBIx::Class::ResultSource::_resolve_join at line 1511, avg 63µs/call
# 147 times (1.50ms+6.15ms) by DBIx::Class::ResultSet::related_resultset at line 2896 of DBIx/Class/ResultSet.pm, avg 52µs/call
# 60 times (716µs+3.00ms) by SQL::Translator::Parser::DBIx::Class::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/SQL/Translator/Parser/DBIx/Class.pm:154] at line 154 of SQL/Translator/Parser/DBIx/Class.pm, avg 62µs/call
# 60 times (621µs+2.33ms) by DBIx::Class::ResultSource::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/ResultSource.pm:1381] at line 1381, avg 49µs/call | ||||
| 1845 | 4155 | 4.04ms | my ($self, $rel) = @_; | ||
| 1846 | 4155 | 9.43ms | 4155 | 14.6ms | if( !$self->has_relationship( $rel ) ) { # spent 14.6ms making 4155 calls to DBIx::Class::ResultSource::has_relationship, avg 4µs/call |
| 1847 | $self->throw_exception("No such relationship '$rel' on " . $self->source_name); | ||||
| 1848 | } | ||||
| 1849 | |||||
| 1850 | # if we are not registered with a schema - just use the prototype | ||||
| 1851 | # however if we do have a schema - ask for the source by name (and | ||||
| 1852 | # throw in the process if all fails) | ||||
| 1853 | 8310 | 64.0ms | 16620 | 260ms | # spent 31.9ms (19.1+12.8) within DBIx::Class::ResultSource::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/ResultSource.pm:1853] which was called 4155 times, avg 8µs/call:
# 4155 times (19.1ms+12.8ms) by Try::Tiny::try at line 71 of Try/Tiny.pm, avg 8µs/call # spent 171ms making 4155 calls to DBIx::Class::Schema::source, avg 41µs/call
# spent 72.2ms making 4155 calls to Try::Tiny::try, avg 17µs/call, recursion: max depth 1, sum of overlapping time 3.96ms
# spent 12.8ms making 4155 calls to DBIx::Class::ResultSource::schema, avg 3µs/call
# spent 8.41ms making 4155 calls to DBIx::Class::ResultSource::relationship_info, avg 2µs/call |
| 1854 | $schema->source($self->relationship_info($rel)->{source}); | ||||
| 1855 | } | ||||
| 1856 | else { | ||||
| 1857 | my $class = $self->relationship_info($rel)->{class}; | ||||
| 1858 | $self->ensure_class_loaded($class); | ||||
| 1859 | $class->result_source_instance; | ||||
| 1860 | } | ||||
| 1861 | } | ||||
| 1862 | |||||
| 1863 | =head2 related_class | ||||
| 1864 | |||||
| 1865 | =over 4 | ||||
| 1866 | |||||
| 1867 | =item Arguments: $relname | ||||
| 1868 | |||||
| 1869 | =item Return value: $classname | ||||
| 1870 | |||||
| 1871 | =back | ||||
| 1872 | |||||
| 1873 | Returns the class name for objects in the given relationship. | ||||
| 1874 | |||||
| 1875 | =cut | ||||
| 1876 | |||||
| 1877 | sub related_class { | ||||
| 1878 | my ($self, $rel) = @_; | ||||
| 1879 | if( !$self->has_relationship( $rel ) ) { | ||||
| 1880 | $self->throw_exception("No such relationship '$rel' on " . $self->source_name); | ||||
| 1881 | } | ||||
| 1882 | return $self->schema->class($self->relationship_info($rel)->{source}); | ||||
| 1883 | } | ||||
| 1884 | |||||
| 1885 | =head2 handle | ||||
| 1886 | |||||
| 1887 | =over 4 | ||||
| 1888 | |||||
| 1889 | =item Arguments: None | ||||
| 1890 | |||||
| 1891 | =item Return value: $source_handle | ||||
| 1892 | |||||
| 1893 | =back | ||||
| 1894 | |||||
| 1895 | Obtain a new L<result source handle instance|DBIx::Class::ResultSourceHandle> | ||||
| 1896 | for this source. Used as a serializable pointer to this resultsource, as it is not | ||||
| 1897 | easy (nor advisable) to serialize CODErefs which may very well be present in e.g. | ||||
| 1898 | relationship definitions. | ||||
| 1899 | |||||
| 1900 | =cut | ||||
| 1901 | |||||
| 1902 | sub handle { | ||||
| 1903 | return DBIx::Class::ResultSourceHandle->new({ | ||||
| 1904 | source_moniker => $_[0]->source_name, | ||||
| 1905 | |||||
| 1906 | # so that a detached thaw can be re-frozen | ||||
| 1907 | $_[0]->{_detached_thaw} | ||||
| 1908 | ? ( _detached_source => $_[0] ) | ||||
| 1909 | : ( schema => $_[0]->schema ) | ||||
| 1910 | , | ||||
| 1911 | }); | ||||
| 1912 | } | ||||
| 1913 | |||||
| 1914 | { | ||||
| 1915 | 2 | 900ns | my $global_phase_destroy; | ||
| 1916 | |||||
| 1917 | # SpeedyCGI runs END blocks every cycle but keeps object instances | ||||
| 1918 | # hence we have to disable the globaldestroy hatch, and rely on the | ||||
| 1919 | # eval trap below (which appears to work, but is risky done so late) | ||||
| 1920 | 1 | 10µs | # spent 5µs within DBIx::Class::ResultSource::END which was called:
# once (5µs+0s) by main::RUNTIME at line 0 of xt/tapper-mcp-scheduler-with-db-longrun.t | ||
| 1921 | |||||
| 1922 | # spent 124µs within DBIx::Class::ResultSource::DESTROY which was called 57 times, avg 2µs/call:
# 57 times (124µs+0s) by DBIx::Class::Schema::clone at line 1044 of DBIx/Class/Schema.pm, avg 2µs/call | ||||
| 1923 | 57 | 18µs | return if $global_phase_destroy; | ||
| 1924 | |||||
| 1925 | ###### | ||||
| 1926 | # !!! ACHTUNG !!!! | ||||
| 1927 | ###### | ||||
| 1928 | # | ||||
| 1929 | # Under no circumstances shall $_[0] be stored anywhere else (like copied to | ||||
| 1930 | # a lexical variable, or shifted, or anything else). Doing so will mess up | ||||
| 1931 | # the refcount of this particular result source, and will allow the $schema | ||||
| 1932 | # we are trying to save to reattach back to the source we are destroying. | ||||
| 1933 | # The relevant code checking refcounts is in ::Schema::DESTROY() | ||||
| 1934 | |||||
| 1935 | # if we are not a schema instance holder - we don't matter | ||||
| 1936 | return if( | ||||
| 1937 | 57 | 163µs | ! ref $_[0]->{schema} | ||
| 1938 | or | ||||
| 1939 | isweak $_[0]->{schema} | ||||
| 1940 | ); | ||||
| 1941 | |||||
| 1942 | # weaken our schema hold forcing the schema to find somewhere else to live | ||||
| 1943 | # during global destruction (if we have not yet bailed out) this will throw | ||||
| 1944 | # which will serve as a signal to not try doing anything else | ||||
| 1945 | local $@; | ||||
| 1946 | eval { | ||||
| 1947 | weaken $_[0]->{schema}; | ||||
| 1948 | 1; | ||||
| 1949 | } or do { | ||||
| 1950 | $global_phase_destroy = 1; | ||||
| 1951 | return; | ||||
| 1952 | }; | ||||
| 1953 | |||||
| 1954 | |||||
| 1955 | # if schema is still there reintroduce ourselves with strong refs back to us | ||||
| 1956 | if ($_[0]->{schema}) { | ||||
| 1957 | my $srcregs = $_[0]->{schema}->source_registrations; | ||||
| 1958 | for (keys %$srcregs) { | ||||
| 1959 | next unless $srcregs->{$_}; | ||||
| 1960 | $srcregs->{$_} = $_[0] if $srcregs->{$_} == $_[0]; | ||||
| 1961 | } | ||||
| 1962 | } | ||||
| 1963 | } | ||||
| 1964 | } | ||||
| 1965 | |||||
| 1966 | sub STORABLE_freeze { Storable::nfreeze($_[0]->handle) } | ||||
| 1967 | |||||
| 1968 | sub STORABLE_thaw { | ||||
| 1969 | my ($self, $cloning, $ice) = @_; | ||||
| 1970 | %$self = %{ (Storable::thaw($ice))->resolve }; | ||||
| 1971 | } | ||||
| 1972 | |||||
| 1973 | =head2 throw_exception | ||||
| 1974 | |||||
| 1975 | See L<DBIx::Class::Schema/"throw_exception">. | ||||
| 1976 | |||||
| 1977 | =cut | ||||
| 1978 | |||||
| 1979 | sub throw_exception { | ||||
| 1980 | my $self = shift; | ||||
| 1981 | |||||
| 1982 | $self->{schema} | ||||
| 1983 | ? $self->{schema}->throw_exception(@_) | ||||
| 1984 | : DBIx::Class::Exception->throw(@_) | ||||
| 1985 | ; | ||||
| 1986 | } | ||||
| 1987 | |||||
| 1988 | =head2 source_info | ||||
| 1989 | |||||
| 1990 | Stores a hashref of per-source metadata. No specific key names | ||||
| 1991 | have yet been standardized, the examples below are purely hypothetical | ||||
| 1992 | and don't actually accomplish anything on their own: | ||||
| 1993 | |||||
| 1994 | __PACKAGE__->source_info({ | ||||
| 1995 | "_tablespace" => 'fast_disk_array_3', | ||||
| 1996 | "_engine" => 'InnoDB', | ||||
| 1997 | }); | ||||
| 1998 | |||||
| 1999 | =head2 new | ||||
| 2000 | |||||
| 2001 | $class->new(); | ||||
| 2002 | |||||
| 2003 | $class->new({attribute_name => value}); | ||||
| 2004 | |||||
| 2005 | Creates a new ResultSource object. Not normally called directly by end users. | ||||
| 2006 | |||||
| 2007 | =head2 column_info_from_storage | ||||
| 2008 | |||||
| 2009 | =over | ||||
| 2010 | |||||
| 2011 | =item Arguments: 1/0 (default: 0) | ||||
| 2012 | |||||
| 2013 | =item Return value: 1/0 | ||||
| 2014 | |||||
| 2015 | =back | ||||
| 2016 | |||||
| 2017 | __PACKAGE__->column_info_from_storage(1); | ||||
| 2018 | |||||
| 2019 | Enables the on-demand automatic loading of the above column | ||||
| 2020 | metadata from storage as necessary. This is *deprecated*, and | ||||
| 2021 | should not be used. It will be removed before 1.0. | ||||
| 2022 | |||||
| 2023 | |||||
| 2024 | =head1 AUTHORS | ||||
| 2025 | |||||
| 2026 | Matt S. Trout <mst@shadowcatsystems.co.uk> | ||||
| 2027 | |||||
| 2028 | =head1 LICENSE | ||||
| 2029 | |||||
| 2030 | You may distribute this code under the same terms as Perl itself. | ||||
| 2031 | |||||
| 2032 | =cut | ||||
| 2033 | |||||
| 2034 | 1 | 37µs | 1 | 655µs | 1; # spent 655µs making 1 call to B::Hooks::EndOfScope::__ANON__[B/Hooks/EndOfScope.pm:26] |
sub DBIx::Class::ResultSource::CORE:match; # opcode | |||||
# spent 81µs within DBIx::Class::ResultSource::CORE:sort which was called 308 times, avg 263ns/call:
# 308 times (81µs+0s) by DBIx::Class::ResultSource::_compare_relationship_keys at line 1447, avg 263ns/call | |||||
# spent 24.6ms within DBIx::Class::ResultSource::CORE:subst which was called 10914 times, avg 2µs/call:
# 5332 times (19.6ms+0s) by DBIx::Class::ResultSource::_resolve_condition at line 1667, avg 4µs/call
# 5332 times (4.87ms+0s) by DBIx::Class::ResultSource::_resolve_condition at line 1669, avg 914ns/call
# 250 times (92µs+0s) by DBIx::Class::ResultSource::add_columns at line 320, avg 367ns/call |