Profile of DBIx/Class/ResultSource.pm

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

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

Subroutines
Calls | P | F | Exclusive Time | Inclusive Time | Subroutine
--- | --- | --- | --- | --- | ---
8975 | 4 | 3 | 223ms | 309ms | DBIx::Class::ResultSource::::columns_infoDBIx::Class::ResultSource::columns_info
5332 | 3 | 3 | 154ms | 229ms | DBIx::Class::ResultSource::::_resolve_conditionDBIx::Class::ResultSource::_resolve_condition
5708 | 3 | 3 | 117ms | 1.28s | DBIx::Class::ResultSource::::resultsetDBIx::Class::ResultSource::resultset
17444 | 7 | 5 | 106ms | 106ms | DBIx::Class::ResultSource::::columnsDBIx::Class::ResultSource::columns
10410 | 10 | 4 | 101ms | 301ms | DBIx::Class::ResultSource::::storageDBIx::Class::ResultSource::storage
4155 | 6 | 4 | 66.6ms | 333ms | DBIx::Class::ResultSource::::related_sourceDBIx::Class::ResultSource::related_source
23459 | 15 | 8 | 65.8ms | 65.8ms | DBIx::Class::ResultSource::::schemaDBIx::Class::ResultSource::schema
14007 | 10 | 6 | 58.9ms | 58.9ms | DBIx::Class::ResultSource::::relationship_infoDBIx::Class::ResultSource::relationship_info
5708 | 1 | 1 | 57.5ms | 344ms | DBIx::Class::ResultSource::::__ANON__[:1038]DBIx::Class::ResultSource::__ANON__[:1038]
10914 | 3 | 1 | 24.6ms | 24.6ms | DBIx::Class::ResultSource::::CORE:substDBIx::Class::ResultSource::CORE:subst (opcode)
1528 | 3 | 2 | 23.7ms | 28.9ms | DBIx::Class::ResultSource::::column_infoDBIx::Class::ResultSource::column_info
4356 | 3 | 2 | 21.5ms | 21.5ms | DBIx::Class::ResultSource::::has_columnDBIx::Class::ResultSource::has_column
4155 | 1 | 1 | 19.1ms | 31.9ms | DBIx::Class::ResultSource::::__ANON__[:1853]DBIx::Class::ResultSource::__ANON__[:1853]
1690 | 1 | 1 | 16.4ms | 21.7ms | DBIx::Class::ResultSource::::_pri_colsDBIx::Class::ResultSource::_pri_cols
4302 | 2 | 2 | 15.3ms | 15.3ms | DBIx::Class::ResultSource::::has_relationshipDBIx::Class::ResultSource::has_relationship
3166 | 4 | 4 | 14.8ms | 14.8ms | DBIx::Class::ResultSource::::primary_columnsDBIx::Class::ResultSource::primary_columns
714 | 3 | 1 | 7.75ms | 10.8ms | DBIx::Class::ResultSource::::unique_constraint_columnsDBIx::Class::ResultSource::unique_constraint_columns
972 | 3 | 3 | 7.31ms | 7.31ms | DBIx::Class::ResultSource::::relationshipsDBIx::Class::ResultSource::relationships
294 | 2 | 1 | 7.18ms | 25.3ms | DBIx::Class::ResultSource::::_resolve_joinDBIx::Class::ResultSource::_resolve_join
188 | 4 | 3 | 4.14ms | 4.14ms | DBIx::Class::ResultSource::::newDBIx::Class::ResultSource::new
60 | 1 | 1 | 3.69ms | 25.0ms | DBIx::Class::ResultSource::::reverse_relationship_infoDBIx::Class::ResultSource::reverse_relationship_info
809 | 4 | 2 | 3.56ms | 3.65ms | DBIx::Class::ResultSource::::unique_constraintsDBIx::Class::ResultSource::unique_constraints
37 | 1 | 1 | 2.65ms | 3.16ms | DBIx::Class::ResultSource::::add_columnsDBIx::Class::ResultSource::add_columns
60 | 1 | 1 | 959µs | 1.17ms | DBIx::Class::ResultSource::::add_relationshipDBIx::Class::ResultSource::add_relationship
116 | 2 | 1 | 808µs | 1.24ms | DBIx::Class::ResultSource::::__strip_relcondDBIx::Class::ResultSource::__strip_relcond
37 | 1 | 1 | 731µs | 2.17ms | DBIx::Class::ResultSource::::default_sqlt_deploy_hookDBIx::Class::ResultSource::default_sqlt_deploy_hook
154 | 3 | 2 | 684µs | 765µs | DBIx::Class::ResultSource::::_compare_relationship_keysDBIx::Class::ResultSource::_compare_relationship_keys
210 | 1 | 1 | 614µs | 939µs | DBIx::Class::ResultSource::::__ANON__[:1397]DBIx::Class::ResultSource::__ANON__[:1397]
38 | 2 | 2 | 598µs | 893µs | DBIx::Class::ResultSource::::add_unique_constraintDBIx::Class::ResultSource::add_unique_constraint
210 | 1 | 1 | 557µs | 10.7ms | DBIx::Class::ResultSource::::__ANON__[:1394]DBIx::Class::ResultSource::__ANON__[:1394]
1 | 1 | 1 | 553µs | 1.35ms | DBIx::Class::ResultSource::::BEGIN@7DBIx::Class::ResultSource::BEGIN@7
352 | 2 | 1 | 539µs | 539µs | DBIx::Class::ResultSource::::CORE:matchDBIx::Class::ResultSource::CORE:match (opcode)
35 | 1 | 1 | 463µs | 1.56ms | DBIx::Class::ResultSource::::set_primary_keyDBIx::Class::ResultSource::set_primary_key
22 | 1 | 1 | 433µs | 688µs | DBIx::Class::ResultSource::::unique_constraint_namesDBIx::Class::ResultSource::unique_constraint_names
37 | 2 | 1 | 218µs | 3.27ms | DBIx::Class::ResultSource::::_invoke_sqlt_deploy_hookDBIx::Class::ResultSource::_invoke_sqlt_deploy_hook
60 | 1 | 1 | 197µs | 290µs | DBIx::Class::ResultSource::::__ANON__[:1378]DBIx::Class::ResultSource::__ANON__[:1378]
60 | 1 | 1 | 175µs | 3.12ms | DBIx::Class::ResultSource::::__ANON__[:1381]DBIx::Class::ResultSource::__ANON__[:1381]
57 | 1 | 1 | 124µs | 124µs | DBIx::Class::ResultSource::::DESTROYDBIx::Class::ResultSource::DESTROY
308 | 1 | 1 | 81µs | 81µs | DBIx::Class::ResultSource::::CORE:sortDBIx::Class::ResultSource::CORE:sort (opcode)
1 | 1 | 1 | 16µs | 21µs | DBIx::Class::ResultSource::::BEGIN@3DBIx::Class::ResultSource::BEGIN@3
1 | 1 | 1 | 11µs | 31µs | DBIx::Class::ResultSource::::BEGIN@12DBIx::Class::ResultSource::BEGIN@12
1 | 1 | 1 | 10µs | 27µs | DBIx::Class::ResultSource::::BEGIN@4DBIx::Class::ResultSource::BEGIN@4
1 | 1 | 1 | 10µs | 38µs | DBIx::Class::ResultSource::::BEGIN@13DBIx::Class::ResultSource::BEGIN@13
1 | 1 | 1 | 9µs | 81µs | DBIx::Class::ResultSource::::BEGIN@10DBIx::Class::ResultSource::BEGIN@10
1 | 1 | 1 | 8µs | 79µs | DBIx::Class::ResultSource::::BEGIN@16DBIx::Class::ResultSource::BEGIN@16
1 | 1 | 1 | 7µs | 206µs | DBIx::Class::ResultSource::::BEGIN@14DBIx::Class::ResultSource::BEGIN@14
1 | 1 | 1 | 7µs | 44µs | DBIx::Class::ResultSource::::BEGIN@11DBIx::Class::ResultSource::BEGIN@11
1 | 1 | 1 | 5µs | 5µs | DBIx::Class::ResultSource::::ENDDBIx::Class::ResultSource::END
1 | 1 | 1 | 4µs | 4µs | DBIx::Class::ResultSource::::BEGIN@9DBIx::Class::ResultSource::BEGIN@9
1 | 1 | 1 | 4µs | 4µs | DBIx::Class::ResultSource::::BEGIN@6DBIx::Class::ResultSource::BEGIN@6
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::STORABLE_freezeDBIx::Class::ResultSource::STORABLE_freeze
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::STORABLE_thawDBIx::Class::ResultSource::STORABLE_thaw
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::__ANON__[:1271]DBIx::Class::ResultSource::__ANON__[:1271]
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::__ANON__[:1277]DBIx::Class::ResultSource::__ANON__[:1277]
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::__ANON__[:1522]DBIx::Class::ResultSource::__ANON__[:1522]
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::__ANON__[:1614]DBIx::Class::ResultSource::__ANON__[:1614]
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::__ANON__[:386]DBIx::Class::ResultSource::__ANON__[:386]
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::__ANON__[:404]DBIx::Class::ResultSource::__ANON__[:404]
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::__ANON__[:458]DBIx::Class::ResultSource::__ANON__[:458]
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::__ANON__[:464]DBIx::Class::ResultSource::__ANON__[:464]
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::__ANON__[:482]DBIx::Class::ResultSource::__ANON__[:482]
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::__ANON__[:764]DBIx::Class::ResultSource::__ANON__[:764]
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::_pk_depends_onDBIx::Class::ResultSource::_pk_depends_on
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::_resolve_prefetchDBIx::Class::ResultSource::_resolve_prefetch
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::add_columnDBIx::Class::ResultSource::add_column
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::add_unique_constraintsDBIx::Class::ResultSource::add_unique_constraints
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::compare_relationship_keysDBIx::Class::ResultSource::compare_relationship_keys
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::fromDBIx::Class::ResultSource::from
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::handleDBIx::Class::ResultSource::handle
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::name_unique_constraintDBIx::Class::ResultSource::name_unique_constraint
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::pk_depends_onDBIx::Class::ResultSource::pk_depends_on
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::related_classDBIx::Class::ResultSource::related_class
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::remove_columnDBIx::Class::ResultSource::remove_column
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::remove_columnsDBIx::Class::ResultSource::remove_columns
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::resolve_conditionDBIx::Class::ResultSource::resolve_condition
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::sequenceDBIx::Class::ResultSource::sequence
0 | 0 | 0 | 0s | 0s | DBIx::Class::ResultSource::::throw_exceptionDBIx::Class::ResultSource::throw_exception

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

Line | State ments | Time on line | Calls | Time in subs | Code
--- | --- | --- | --- | --- | ---
1 |  |  |  |  | package DBIx::Class::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 use strict; # 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 use warnings; # 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 use DBIx::Class::ResultSet; # 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 use DBIx::Class::ResultSourceHandle; # 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 use DBIx::Class::Exception; # 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 use DBIx::Class::Carp; # 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 use Try::Tiny; # 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 use List::Util 'first'; # 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 use Scalar::Util qw/blessed weaken isweak/; # 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 use namespace::clean; # 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 use base qw/DBIx::Class/; # 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 sub new {
113 | 2068 | 4.38ms |  |  | my ($class, $attrs) = @_;
114 |  |  |  |  | $class = ref $class if ref $class;
115 |  |  |  |  |
116 |  |  |  |  | my $new = bless { %{$attrs || {}} }, $class;
117 |  |  |  |  | $new->{resultset_class} ||= 'DBIx::Class::ResultSet';
118 |  |  |  |  | $new->{resultset_attributes} = { %{$new->{resultset_attributes} || {}} };
119 |  |  |  |  | $new->{_ordered_columns} = [ @{$new->{_ordered_columns}||[]}];
120 |  |  |  |  | $new->{_columns} = { %{$new->{_columns}||{}} };
121 |  |  |  |  | $new->{_relationships} = { %{$new->{_relationships}||{}} };
122 |  |  |  |  | $new->{name} ||= "!!NAME NOT SET!!";
123 |  |  |  |  | $new->{_columns_info_loaded} ||= 0;
124 |  |  |  |  | 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 sub add_columns {
313 | 259 | 760µs |  |  | my ($self, @cols) = @_;
314 |  |  | 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 |  |  |  |  | my @added;
317 |  |  | 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 | 1250 | 1.24ms |  |  | while (my $col = shift @cols) {
319 |  |  |  |  | my $column_info = {};
320 |  |  | 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 | 500 | 765µs |  |  | if (ref $cols[0]) {
327 |  |  |  |  | my $new_info = shift(@cols);
328 |  |  |  |  | %$column_info = (%$column_info, %$new_info);
329 |  |  |  |  | }
330 |  |  |  |  | push(@added, $col) unless exists $columns->{$col};
331 |  |  |  |  | $columns->{$col} = $column_info;
332 |  |  |  |  | }
333 |  |  | 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 |  |  |  |  | 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 sub has_column {
356 | 8712 | 28.5ms |  |  | my ($self, $column) = @_;
357 |  |  | 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 sub column_info {
379 | 6112 | 30.0ms |  |  | my ($self, $column) = @_;
380 |  |  | 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 |  |  | 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 |  |  | 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 sub columns {
427 | 52332 | 137ms |  |  | my $self = shift;
428 |  |  |  |  | $self->throw_exception(
429 |  |  |  |  | "columns() is a read-only accessor, did you mean add_columns()?"
430 |  |  |  |  | ) if @_;
431 |  |  |  |  | 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 sub columns_info {
453 | 53850 | 152ms |  |  | my ($self, $columns) = @_;
454 |  |  |  |  |
455 |  |  | 1 | 1µs | my $colinfo = $self->_columns; # spent 1µs making 1 call to DBIx::Class::ResultSource::Table::_columns
456 |  |  |  |  |
457 |  |  | 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 |  |  |  |  | my %ret;
486 |  |  |  |  |
487 | 8975 | 56.7ms |  |  | 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 |  |  |  |  | %ret = %$colinfo;
503 |  |  |  |  | }
504 |  |  |  |  |
505 |  |  |  |  | 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 sub set_primary_key {
589 | 140 | 297µs |  |  | my ($self, @cols) = @_;
590 |  |  |  |  | # check if primary key columns are valid columns
591 |  |  |  |  | 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 |  |  | 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 | 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 sub primary_columns {
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 sub _pri_cols {
623 | 5070 | 15.0ms |  |  | my $self = shift;
624 |  |  | 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 |  |  |  |  | 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 sub add_unique_constraint {
696 | 380 | 459µs |  |  | my $self = shift;
697 |  |  |  |  |
698 |  |  |  |  | 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 |  |  |  |  | my $cols = pop @_;
706 |  |  |  |  | if (ref $cols ne 'ARRAY') {
707 |  |  |  |  | $self->throw_exception (
708 |  |  |  |  | 'Expecting an arrayref of constraint columns, got ' . ($cols||'NOTHING')
709 |  |  |  |  | );
710 |  |  |  |  | }
711 |  |  |  |  |
712 |  |  |  |  | my $name = shift @_;
713 |  |  |  |  |
714 |  |  |  |  | $name ||= $self->name_unique_constraint($cols);
715 |  |  |  |  |
716 |  |  |  |  | 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 | 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 |  |  |  |  | $unique_constraints{$name} = $cols;
723 |  |  | 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 sub unique_constraints {
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 sub unique_constraint_names {
855 | 66 | 399µs |  |  | my ($self) = @_;
856 |  |  |  |  |
857 |  |  | 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 |  |  |  |  | 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 sub unique_constraint_columns {
879 | 2856 | 7.44ms |  |  | my ($self, $constraint_name) = @_;
880 |  |  |  |  |
881 |  |  | 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 |  |  |  |  | $self->throw_exception(
884 |  |  |  |  | "Unknown unique constraint $constraint_name on '" . $self->name . "'"
885 |  |  |  |  | ) unless exists $unique_constraints{$constraint_name};
886 |  |  |  |  |
887 |  |  |  |  | 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 sub default_sqlt_deploy_hook {
947 | 111 | 1.33ms |  |  | my $self = shift;
948 |  |  |  |  |
949 |  |  | 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 |  |  | 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 sub _invoke_sqlt_deploy_hook {
957 | 74 | 181µs |  |  | my $self = shift;
958 |  |  | 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 sub resultset {
1029 | 17124 | 105ms |  |  | my $self = shift;
1030 |  |  |  |  | $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 try { %{$self->schema->default_resultset_attributes} }, # 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 |  |  | 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 sub schema {
1118 | 46824 | 114ms |  |  | if (@_ > 1) {
1119 |  |  |  |  | $_[0]->{schema} = $_[1];
1120 |  |  |  |  | }
1121 |  |  |  |  | else {
1122 |  |  |  |  | $_[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 sub storage { shift->schema->storage; } # 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 sub add_relationship {
1236 | 480 | 697µs |  |  | my ($self, $rel, $f_source_name, $cond, $attrs) = @_;
1237 |  |  |  |  | $self->throw_exception("Can't create relationship without join condition")
1238 |  |  |  |  | unless $cond;
1239 |  |  |  |  | $attrs ||= {};
1240 |  |  |  |  |
1241 |  |  |  |  | # Check foreign and self are right in cond
1242 | 60 | 68µs |  |  | if ( (ref $cond ||'') eq 'HASH') {
1243 |  |  |  |  | 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 |  |  | 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 |  |  |  |  | $rels{$rel} = { class => $f_source_name,
1251 |  |  |  |  | source => $f_source_name,
1252 |  |  |  |  | cond => $cond,
1253 |  |  |  |  | attrs => $attrs };
1254 |  |  | 1 | 1µs | $self->_relationships(\%rels); # spent 1µs making 1 call to DBIx::Class::ResultSource::Table::_relationships
1255 |  |  |  |  |
1256 |  |  |  |  | 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 sub relationships {
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 sub relationship_info {
1318 | 28014 | 77.8ms |  |  | my ($self, $rel) = @_;
1319 |  |  | 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 sub has_relationship {
1337 | 8604 | 20.6ms |  |  | my ($self, $rel) = @_;
1338 |  |  | 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 sub reverse_relationship_info {
1366 | 540 | 981µs |  |  | my ($self, $rel) = @_;
1367 |  |  |  |  |
1368 |  |  | 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 |  |  |  |  | my $ret = {};
1372 |  |  |  |  |
1373 |  |  |  |  | return $ret unless ((ref $rel_info->{cond}) eq 'HASH');
1374 |  |  |  |  |
1375 |  |  | 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 | 60 | 163µ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 if try { $self->schema }; # 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 my $other_rsrc = try { $self->related_source($rel) } # spent 2.95ms making 60 calls to DBIx::Class::ResultSource::related_source, avg 49µs/call
1382 |  |  | 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 | 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 my $roundtrip_rsrc = try { $other_rsrc->related_source($other_rel) } # spent 10.2ms making 210 calls to DBIx::Class::ResultSource::related_source, avg 48µs/call
1395 | 702 | 1.73ms | 210 | 12.4ms | or next; # spent 12.4ms making 210 calls to Try::Tiny::try, avg 59µs/call
1396 |  |  |  |  |
1397 | 420 | 797µ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 if ($rsrc_schema_moniker and try { $roundtrip_rsrc->schema } ) { # 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 |  |  | 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 | 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 |  |  |  |  | next if $other_rel_info eq $rel_info;
1408 |  |  |  |  |
1409 |  |  |  |  | next unless ref $other_rel_info->{cond} eq 'HASH';
1410 |  |  | 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 |  |  | 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 |  |  |  |  | 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 sub __strip_relcond {
1428 |  |  |  |  | +{
1429 |  |  | 232 | 429µs | map # spent 429µs making 232 calls to DBIx::Class::ResultSource::CORE:match, avg 2µs/call
1430 | 232 | 796µs |  |  | { map { /^ (?:foreign|self) \. (\w+) $/x } ($_, $_[1]{$_}) }
1431 | 232 | 547µ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 sub _compare_relationship_keys {
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 sub _resolve_join {
1453 | 1470 | 1.71ms |  |  | 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 |  |  |  |  | $self->throw_exception ('You must supply a seen hashref as the 3rd argument to _resolve_join')
1457 |  |  |  |  | unless ref $seen eq 'HASH';
1458 |  |  |  |  |
1459 |  |  |  |  | $self->throw_exception ('You must supply a joinpath arrayref as the 4th argument to _resolve_join')
1460 |  |  |  |  | unless ref $jpath eq 'ARRAY';
1461 |  |  |  |  |
1462 |  |  |  |  | $jpath = [@$jpath]; # copy
1463 |  |  |  |  |
1464 | 735 | 3.67ms |  |  | 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 |  |  |  |  | my $count = ++$seen->{$join};
1504 |  |  | 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 | 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 | 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 | 147 | 1.56ms | 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 sub _resolve_condition {
1587 | 15996 | 42.5ms |  |  | my ($self, $cond, $as, $for, $relname) = @_;
1588 |  |  |  |  |
1589 |  |  | 5332 | 7.55ms | my $obj_rel = !!blessed $for; # spent 7.55ms making 5332 calls to Scalar::Util::blessed, avg 1µs/call
1590 |  |  |  |  |
1591 | 15996 | 38.0ms |  |  | 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 |  |  |  |  | my %ret;
1664 |  |  |  |  | foreach my $k (keys %{$cond}) {
1665 | 21328 | 69.6ms |  |  | my $v = $cond->{$k};
1666 |  |  |  |  | # XXX should probably check these are valid columns
1667 |  |  | 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 | 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 | 10517 | 29.1ms |  |  | if (ref $for) { # Object
1672 |  |  |  |  | #warn "$self $k $for $v";
1673 |  |  | 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 | 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 |  |  |  |  | $ret{"${as}.${k}"} = { -ident => "${for}.${v}" };
1700 |  |  |  |  | }
1701 |  |  |  |  | }
1702 |  |  |  |  |
1703 |  |  |  |  | return wantarray
1704 |  |  |  |  | ? ( \%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 sub related_source {
1845 | 12465 | 59.3ms |  |  | my ($self, $rel) = @_;
1846 |  |  | 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 | 4155 | 18.1ms | 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 if (my $schema = try { $self->schema }) { # 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 END { $global_phase_destroy = 1 unless $CGI::SpeedyCGI::i_am_speedy }
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 sub DESTROY {
1923 | 114 | 181µ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 |  |  |  |  | ! 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]
|  |  |  |  | # spent 539µs within DBIx::Class::ResultSource::CORE:match which was called 352 times, avg 2µs/call: # 232 times (429µs+0s) by DBIx::Class::ResultSource::__strip_relcond at line 1429, avg 2µs/call # 120 times (110µs+0s) by DBIx::Class::ResultSource::add_relationship at line 1244, avg 919ns/call 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 sub DBIx::Class::ResultSource::CORE:sort; # opcode
|  |  |  |  | # 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 sub DBIx::Class::ResultSource::CORE:subst; # opcode