File Coverage

blib/lib/DBIx/Class/Schema/Loader/RelBuilder.pm
Criterion Covered Total %
statement 1229 1267 97.0
branch 119 146 81.5
condition 33 56 58.9
subroutine 133 138 96.3
pod 2 2 100.0
total 1516 1609 94.2


line stmt bran cond sub pod time code
1             package DBIx::Class::Schema::Loader::RelBuilder;
2              
3 18     18   129 use strict;
  18         41  
  18         515  
4 18     18   120 use warnings;
  18         42  
  18         459  
5 18     18   110 use base 'Class::Accessor::Grouped';
  18         41  
  18         1831  
6 18     18   121 use mro 'c3';
  18         64  
  18         203  
7 18     18   538 use Carp::Clan qw/^DBIx::Class/;
  18         178  
  18         143  
8 18     18   1924 use Scalar::Util 'weaken';
  18         85  
  18         1226  
9 18     18   785 use DBIx::Class::Schema::Loader::Utils qw/split_name slurp_file array_eq apply uniq/;
  18         65  
  18         1281  
10 18     18   238 use Try::Tiny;
  18         48  
  18         1130  
11 18     18   115 use List::Util qw/all any first/;
  18         40  
  18         1299  
12 18     18   135 use namespace::clean;
  18         39  
  18         140  
13 18     18   16959 use Lingua::EN::Inflect::Phrase ();
  18         1625721  
  18         599  
14 18     18   189 use Lingua::EN::Tagger ();
  18         48  
  18         312  
15 18     18   9111 use String::ToIdentifier::EN ();
  18         644023  
  18         635  
16 18     18   8336 use String::ToIdentifier::EN::Unicode ();
  18         6271  
  18         389  
17 18     18   6462 use Class::Unload ();
  18         58653  
  18         399  
18 18     18   145 use Class::Inspector ();
  18         57  
  18         110397  
19              
20             our $VERSION = '0.07050';
21              
22             # Glossary:
23             #
24             # local_relname -- name of relationship from the local table referring to the remote table
25             # remote_relname -- name of relationship from the remote table referring to the local table
26             # remote_method -- relationship type from remote table to local table, usually has_many
27              
28             =head1 NAME
29              
30             DBIx::Class::Schema::Loader::RelBuilder - Builds relationships for DBIx::Class::Schema::Loader
31              
32             =head1 SYNOPSIS
33              
34             See L and L.
35              
36             =head1 DESCRIPTION
37              
38             This class builds relationships for L. This
39             is module is not (yet) for external use.
40              
41             =head1 METHODS
42              
43             =head2 new
44              
45             Arguments: $loader object
46              
47             =head2 generate_code
48              
49             Arguments:
50              
51             [
52             [ local_moniker1 (scalar), fk_info1 (arrayref), uniq_info1 (arrayref) ]
53             [ local_moniker2 (scalar), fk_info2 (arrayref), uniq_info2 (arrayref) ]
54             ...
55             ]
56              
57             This generates the code for the relationships of each table.
58              
59             C is the moniker name of the table which had the REFERENCES
60             statements. The fk_info arrayref's contents should take the form:
61              
62             [
63             {
64             local_table => 'some_table',
65             local_moniker => 'SomeTable',
66             local_columns => [ 'col2', 'col3' ],
67             remote_table => 'another_table_moniker',
68             remote_moniker => 'AnotherTableMoniker',
69             remote_columns => [ 'col5', 'col7' ],
70             },
71             {
72             local_table => 'some_other_table',
73             local_moniker => 'SomeOtherTable',
74             local_columns => [ 'col1', 'col4' ],
75             remote_table => 'yet_another_table_moniker',
76             remote_moniker => 'YetAnotherTableMoniker',
77             remote_columns => [ 'col1', 'col2' ],
78             },
79             # ...
80             ],
81              
82             The uniq_info arrayref's contents should take the form:
83              
84             [
85             [
86             uniq_constraint_name => [ 'col1', 'col2' ],
87             ],
88             [
89             another_uniq_constraint_name => [ 'col1', 'col2' ],
90             ],
91             ],
92              
93             This method will return the generated relationships as a hashref keyed on the
94             class names. The values are arrayrefs of hashes containing method name and
95             arguments, like so:
96              
97             {
98             'Some::Source::Class' => [
99             { method => 'belongs_to', arguments => [
100             'col1', 'Another::Source::Class' ] },
101             { method => 'has_many', arguments => [
102             'anothers', 'Yet::Another::Source::Class', 'col15' ] },
103             ],
104             'Another::Source::Class' => [
105             # ...
106             ],
107             # ...
108             }
109              
110             =cut
111              
112             __PACKAGE__->mk_group_accessors('simple', qw/
113             loader
114             schema
115             inflect_plural
116             inflect_singular
117             relationship_attrs
118             rel_collision_map
119             rel_name_map
120             allow_extra_m2m_cols
121             _temp_classes
122             __tagger
123             /);
124              
125             sub new {
126 113     113 1 635 my ($class, $loader) = @_;
127              
128             # from old POD about this constructor:
129             # C<$schema_class> should be a schema class name, where the source
130             # classes have already been set up and registered. Column info,
131             # primary key, and unique constraints will be drawn from this
132             # schema for all of the existing source monikers.
133              
134             # Options inflect_plural and inflect_singular are optional, and
135             # are better documented in L.
136              
137             my $self = {
138             loader => $loader,
139 113         584 (map { $_ => $loader->$_ } qw(
  791         17902  
140             schema inflect_plural inflect_singular
141             relationship_attrs rel_collision_map
142             rel_name_map allow_extra_m2m_cols
143             )),
144             _temp_classes => [],
145             };
146              
147 113         4496 weaken $self->{loader}; #< don't leak
148              
149 113         457 bless $self => $class;
150              
151             # validate the relationship_attrs arg
152 113 100       986 if( defined $self->relationship_attrs ) {
153 5 100 100     297 (ref $self->relationship_attrs eq 'HASH' || ref $self->relationship_attrs eq 'CODE')
154             or croak "relationship_attrs must be a hashref or coderef";
155             }
156              
157 111         5685 return $self;
158             }
159              
160              
161             # pluralize a relationship name
162             sub _inflect_plural {
163 856     856   2551 my ($self, $relname) = @_;
164              
165 856 50 33     4686 return '' if !defined $relname || $relname eq '';
166              
167 856         1603 my $result;
168 856         1782 my $mapped = 0;
169              
170 856 100       4173 if( ref $self->inflect_plural eq 'HASH' ) {
    50          
171 404 100       1537 if (exists $self->inflect_plural->{$relname}) {
172 6         51 $result = $self->inflect_plural->{$relname};
173 6         20 $mapped = 1;
174             }
175             }
176             elsif( ref $self->inflect_plural eq 'CODE' ) {
177 0         0 my $inflected = $self->inflect_plural->($relname);
178 0 0       0 if ($inflected) {
179 0         0 $result = $inflected;
180 0         0 $mapped = 1;
181             }
182             }
183              
184 856 100       6318 return ($result, $mapped) if $mapped;
185              
186 850         2785 return ($self->_to_PL($relname), 0);
187             }
188              
189             # Singularize a relationship name
190             sub _inflect_singular {
191 696     696   1947 my ($self, $relname) = @_;
192              
193 696 50 33     4038 return '' if !defined $relname || $relname eq '';
194              
195 696         1381 my $result;
196 696         1517 my $mapped = 0;
197              
198 696 100       3667 if( ref $self->inflect_singular eq 'HASH' ) {
    50          
199 297 100       1238 if (exists $self->inflect_singular->{$relname}) {
200 6         32 $result = $self->inflect_singular->{$relname};
201 6         30 $mapped = 1;
202             }
203             }
204             elsif( ref $self->inflect_singular eq 'CODE' ) {
205 0         0 my $inflected = $self->inflect_singular->($relname);
206 0 0       0 if ($inflected) {
207 0         0 $result = $inflected;
208 0         0 $mapped = 1;
209             }
210             }
211              
212 696 100       5856 return ($result, $mapped) if $mapped;
213              
214 690         2561 return ($self->_to_S($relname), 0);
215             }
216              
217             sub _to_PL {
218 785     785   2045 my ($self, $name) = @_;
219              
220 785         2966 $name =~ s/_/ /g;
221 785         3210 my $plural = Lingua::EN::Inflect::Phrase::to_PL($name);
222 785         2384159 $plural =~ s/ /_/g;
223              
224 785         3445 return $plural;
225             }
226              
227             sub _to_S {
228 624     624   1585 my ($self, $name) = @_;
229              
230 624         2082 $name =~ s/_/ /g;
231 624         2628 my $singular = Lingua::EN::Inflect::Phrase::to_S($name);
232 624         1655634 $singular =~ s/ /_/g;
233              
234 624         2611 return $singular;
235             }
236              
237             sub _default_relationship_attrs { +{
238 1154     1154   15042 has_many => {
239             cascade_delete => 0,
240             cascade_copy => 0,
241             },
242             might_have => {
243             cascade_delete => 0,
244             cascade_copy => 0,
245             },
246             belongs_to => {
247             on_delete => 'CASCADE',
248             on_update => 'CASCADE',
249             is_deferrable => 1,
250             },
251             } }
252              
253             # Accessor for options to be passed to each generated relationship type. takes
254             # the relationship type name and optionally any attributes from the database
255             # (such as FK ON DELETE/UPDATE and DEFERRABLE clauses), and returns a
256             # hashref or undef if nothing is set.
257             #
258             # The attributes from the database override the default attributes, which in
259             # turn are overridden by user supplied attributes.
260             sub _relationship_attrs {
261 1226     1226   9568 my ( $self, $reltype, $db_attrs, $params ) = @_;
262 1226         3560 my $r = $self->relationship_attrs;
263              
264             my %composite = (
265 1226 100       3471 %{ $self->_default_relationship_attrs->{$reltype} || {} },
266 1226 50       7839 %{ $db_attrs || {} },
267             (
268             ref $r eq 'HASH' ? (
269 546 100       2691 %{ $r->{all} || {} },
270 1226 100       2161 %{ $r->{$reltype} || {} },
  546 100       3475  
271             )
272             :
273             ()
274             ),
275             );
276              
277 1226 100       5344 if (ref $r eq 'CODE') {
278 2         5 $params->{attrs} = \%composite;
279              
280 2 50       5 my %ret = %{ $r->(%$params) || {} };
  2         14  
281              
282 2 50       3349 %composite = %ret if %ret;
283             }
284              
285 1226 100       10878 return %composite ? \%composite : undef;
286             }
287              
288             sub _strip_id_postfix {
289 0     0   0 my ($self, $name) = @_;
290              
291 0         0 $name =~ s/_?(?:id|ref|cd|code|num)\z//i;
292              
293 0         0 return $name;
294             }
295              
296             sub _remote_attrs {
297 552     552   1949 my ($self, $local_moniker, $local_cols, $fk_attrs, $params) = @_;
298              
299             # get our set of attrs from _relationship_attrs, which uses the FK attrs if available
300 552   50     2318 my $attrs = $self->_relationship_attrs('belongs_to', $fk_attrs, $params) || {};
301              
302             # If any referring column is nullable, make 'belongs_to' an
303             # outer join, unless explicitly set by relationship_attrs
304 552     601   4322 my $nullable = first { $self->schema->source($local_moniker)->column_info($_)->{is_nullable} } @$local_cols;
  601         5882  
305 552 100 66     38693 $attrs->{join_type} = 'LEFT' if $nullable && !defined $attrs->{join_type};
306              
307 552         4790 return $attrs;
308             }
309              
310             sub _sanitize_name {
311 2003     2003   4317 my ($self, $name) = @_;
312              
313 2003         8883 $name = $self->loader->_to_identifier('relationships', $name, '_');
314              
315 2003         6771 $name =~ s/\W+/_/g; # if naming >= 8 to_identifier takes care of it
316              
317 2003         4622 return $name;
318             }
319              
320             sub _normalize_name {
321 1971     1971   4823 my ($self, $name) = @_;
322              
323 1971         5601 $name = $self->_sanitize_name($name);
324              
325 1971         6971 my @words = split_name $name, $self->loader->_get_naming_v('relationships');
326              
327 1971         15711 return join '_', map lc, @words;
328             }
329              
330             sub _local_relname {
331 553     553   1796 my ($self, $remote_table, $cond) = @_;
332              
333 553         1195 my $local_relname;
334             # for single-column case, set the remote relname to the column
335             # name, to make filter accessors work, but strip trailing _id
336 553 100       1110 if(scalar keys %{$cond} == 1) {
  553         2920  
337 504         1136 my ($col) = values %{$cond};
  504         1591  
338 504         2067 $col = $self->_strip_id_postfix($self->_normalize_name($col));
339 504         2396 ($local_relname) = $self->_inflect_singular($col);
340             }
341             else {
342 49         207 ($local_relname) = $self->_inflect_singular($self->_normalize_name($remote_table));
343             }
344              
345 553         8872 return $local_relname;
346             }
347              
348             sub _resolve_relname_collision {
349 1300     1300   3354 my ($self, $moniker, $cols, $relname) = @_;
350              
351 1300 100       3503 return $relname if $relname eq 'id'; # this shouldn't happen, but just in case
352              
353 1286         5620 my $table = $self->loader->moniker_to_table->{$moniker};
354              
355 1286 100       5659 if ($self->loader->_is_result_class_method($relname, $table)) {
356 14 100       78 if (my $map = $self->rel_collision_map) {
357 12         270 for my $re (keys %$map) {
358 12 100       107 if (my @matches = $relname =~ /$re/) {
359 6         55 return sprintf $map->{$re}, @matches;
360             }
361             }
362             }
363              
364 8         28 my $new_relname = $relname;
365 8         46 while ($self->loader->_is_result_class_method($new_relname, $table)) {
366 8         47 $new_relname .= '_rel'
367             }
368              
369 8         53 warn <<"EOF";
370 8         140 Relationship '$relname' in source '$moniker' for columns '@{[ join ',', @$cols ]}' collides with an inherited method. Renaming to '$new_relname'.
371             See "RELATIONSHIP NAME COLLISIONS" in perldoc DBIx::Class::Schema::Loader::Base .
372             EOF
373              
374 8         51 return $new_relname;
375             }
376              
377 1272         3507 return $relname;
378             }
379              
380             sub generate_code {
381 116     116 1 588 my ($self, $tables) = @_;
382              
383             # make a copy to destroy
384 116         655 my @tables = @$tables;
385              
386 116         401 my $all_code = {};
387              
388 116 100       540 while (my ($local_moniker, $rels, $uniqs) = @{ shift @tables || [] }) {
  885         6685  
389 770         4720 my $local_class = $self->schema->class($local_moniker);
390              
391 770         72903 my %counters;
392 770         2838 foreach my $rel (@$rels) {
393 611 50       2674 next if !$rel->{remote_source};
394 611         2363 $counters{$rel->{remote_source}}++;
395             }
396              
397 770         2149 foreach my $rel (@$rels) {
398             my $remote_moniker = $rel->{remote_source}
399 611 50       2298 or next;
400              
401 611         2736 my $remote_class = $self->schema->class($remote_moniker);
402 611         51872 my $remote_obj = $self->schema->source($remote_moniker);
403 611   100     26004 my $remote_cols = $rel->{remote_columns} || [ $remote_obj->primary_columns ];
404              
405 611         2175 my $local_cols = $rel->{local_columns};
406              
407 611 50       2569 if($#$local_cols != $#$remote_cols) {
408 0         0 croak "Column count mismatch: $local_moniker (@$local_cols) "
409             . "$remote_moniker (@$remote_cols)";
410             }
411              
412 611         1383 my %cond;
413 611         3169 @cond{@$remote_cols} = @$local_cols;
414              
415 611         3120 my ( $local_relname, $remote_relname, $remote_method ) =
416             $self->_relnames_and_method( $local_moniker, $rel, \%cond, $uniqs, \%counters );
417 611         1834 my $local_method = 'belongs_to';
418              
419 611         2776 ($local_relname) = $self->_rel_name_map(
420             $local_relname, $local_method,
421             $local_class, $local_moniker, $local_cols,
422             $remote_class, $remote_moniker, $remote_cols,
423             );
424 610         1892 ($remote_relname) = $self->_rel_name_map(
425             $remote_relname, $remote_method,
426             $remote_class, $remote_moniker, $remote_cols,
427             $local_class, $local_moniker, $local_cols,
428             );
429              
430 610         2521 $local_relname = $self->_resolve_relname_collision(
431             $local_moniker, $local_cols, $local_relname,
432             );
433 610         1873 $remote_relname = $self->_resolve_relname_collision(
434             $remote_moniker, $remote_cols, $remote_relname,
435             );
436              
437             my $rel_attrs_params = {
438             rel_name => $local_relname,
439             rel_type => $local_method,
440             local_source => $self->schema->source($local_moniker),
441             remote_source => $self->schema->source($remote_moniker),
442             local_table => $rel->{local_table},
443             local_cols => $local_cols,
444             remote_table => $rel->{remote_table},
445 610         3489 remote_cols => $remote_cols,
446             };
447              
448 610         4308 push @{$all_code->{$local_class}}, {
449             method => $local_method,
450             args => [
451             $local_relname,
452             $remote_class,
453             \%cond,
454 610         62908 $self->_remote_attrs($local_moniker, $local_cols, $rel->{attrs}, $rel_attrs_params),
455             ],
456             extra => {
457             local_class => $local_class,
458             local_moniker => $local_moniker,
459             remote_moniker => $remote_moniker,
460             },
461             };
462              
463 610         2875 my %rev_cond = reverse %cond;
464 610         2387 for (keys %rev_cond) {
465 659         3181 $rev_cond{"foreign.$_"} = "self.".$rev_cond{$_};
466 659         2072 delete $rev_cond{$_};
467             }
468              
469             $rel_attrs_params = {
470             rel_name => $remote_relname,
471             rel_type => $remote_method,
472             local_source => $self->schema->source($remote_moniker),
473             remote_source => $self->schema->source($local_moniker),
474             local_table => $rel->{remote_table},
475             local_cols => $remote_cols,
476             remote_table => $rel->{local_table},
477 610         3058 remote_cols => $local_cols,
478             };
479              
480 610         55089 push @{$all_code->{$remote_class}}, {
  610         4000  
481             method => $remote_method,
482             args => [
483             $remote_relname,
484             $local_class,
485             \%rev_cond,
486             $self->_relationship_attrs($remote_method, {}, $rel_attrs_params),
487             ],
488             extra => {
489             local_class => $remote_class,
490             local_moniker => $remote_moniker,
491             remote_moniker => $local_moniker,
492             },
493             };
494             }
495             }
496              
497 115         1225 $self->_generate_m2ms($all_code);
498              
499             # disambiguate rels with the same name
500 115         901 foreach my $class (keys %$all_code) {
501 667         2097 my $dups = $self->_duplicates($all_code->{$class});
502              
503 667 100       1970 $self->_disambiguate($all_code, $class, $dups) if $dups;
504             }
505              
506 115         1070 $self->_cleanup;
507              
508 115         612 return $all_code;
509             }
510              
511             # Find classes with only 2 FKs which are the PK and make many_to_many bridges for them.
512             sub _generate_m2ms {
513 115     115   572 my ($self, $all_code) = @_;
514              
515             LINK_CLASS:
516 115         1488 foreach my $link_class (sort keys %$all_code) {
517 667         1399 my @rels = grep $_->{method} eq 'belongs_to', @{$all_code->{$link_class}};
  667         3766  
518 667 100       2248 next unless @rels == 2;
519              
520 116         290 my @class;
521 116         308 foreach my $this (0, 1) {
522 225 100       605 my $that = $this ? 0 : 1;
523 225         409 my %class;
524 225         502 $class[$this] = \%class;
525 225         839 $class{local_moniker} = $rels[$this]{extra}{remote_moniker};
526 225         705 $class{remote_moniker} = $rels[$that]{extra}{remote_moniker};
527              
528 225         756 $class{class} = $rels[$this]{args}[1];
529              
530 225     267   874 my %link_cols = map { $_ => 1 } apply { s/^self\.//i } values %{ $rels[$this]{args}[2] };
  267         1001  
  267         839  
  225         1515  
531              
532             $class{link_table_rel} = first {
533             $_->{method} eq 'has_many'
534             and
535             $_->{args}[1] eq $link_class
536             and
537 486 100 100 486   3556 all { $link_cols{$_} } apply { s/^foreign\.//i } keys %{$_->{args}[2]}
  346         1316  
  351         1532  
  295         1469  
538 225         1263 } @{ $all_code->{$class{class}} };
  225         989  
539              
540 225 100       1478 next LINK_CLASS unless $class{link_table_rel};
541              
542 218         760 $class{link_table_rel_name} = $class{link_table_rel}{args}[0];
543              
544 218         868 $class{link_rel} = $rels[$that]{args}[0];
545              
546 260     260   1110 $class{from_cols} = [ apply { s/^self\.//i } values %{
547 218         766 $class{link_table_rel}->{args}[2]
  218         961  
548             } ];
549              
550 218     260   946 $class{to_cols} = [ apply { s/^foreign\.//i } keys %{ $rels[$that]{args}[2] } ];
  260         713  
  218         1012  
551              
552 218     260   867 $class{from_link_cols} = [ apply { s/^self\.//i } values %{ $rels[$this]{args}[2] } ];
  260         796  
  218         854  
553             }
554              
555 109         528 my $link_moniker = $rels[0]{extra}{local_moniker};
556              
557             my @link_table_cols =
558 109         223 @{[ $self->schema->source($link_moniker)->columns ]};
  109         653  
559              
560             my @link_table_primary_cols =
561 109         7329 @{[ $self->schema->source($link_moniker)->primary_columns ]};
  109         523  
562              
563             next unless array_eq(
564 109 100 33     5613 [ sort +uniq @{$class[0]{from_link_cols}}, @{$class[1]{from_link_cols}} ],
  109   66     362  
  109         465  
565             [ sort @link_table_primary_cols ],
566             ) && ($self->allow_extra_m2m_cols || @link_table_cols == @link_table_primary_cols);
567              
568 32         790 foreach my $this (0, 1) {
569 64 100       212 my $that = $this ? 0 : 1;
570             ($class[$this]{m2m_relname}) = $self->_rel_name_map(
571             ($self->_inflect_plural($class[$this]{link_rel}))[0],
572             'many_to_many',
573 64         272 @{$class[$this]}{qw(class local_moniker from_cols)},
574             $class[$that]{class},
575 64         446 @{$class[$this]}{qw(remote_moniker to_cols)},
576             {
577             link_class => $link_class,
578             link_moniker => $link_moniker,
579             link_rel_name => $class[$this]{link_table_rel_name},
580             },
581 64         255 );
582              
583             $class[$this]{m2m_relname} = $self->_resolve_relname_collision(
584 64         241 @{$class[$this]}{qw(local_moniker from_cols m2m_relname)},
  64         230  
585             );
586             }
587              
588 32         121 for my $this (0, 1) {
589 64 100       193 my $that = $this ? 0 : 1;
590              
591 64         198 push @{$all_code->{$class[$this]{class}}}, {
592             method => 'many_to_many',
593             args => [
594 64         421 @{$class[$this]}{qw(m2m_relname link_table_rel_name link_rel)},
595             $self->_relationship_attrs('many_to_many', {}, {
596             rel_type => 'many_to_many',
597             rel_name => $class[$this]{class2_relname},
598             local_source => $self->schema->source($class[$this]{local_moniker}),
599             remote_source => $self->schema->source($class[$this]{remote_moniker}),
600             local_table => $self->loader->class_to_table->{$class[$this]{class}},
601             local_cols => $class[$this]{from_cols},
602             remote_table => $self->loader->class_to_table->{$class[$that]{class}},
603             remote_cols => $class[$that]{from_cols},
604             }) || (),
605             ],
606             extra => {
607             local_class => $class[$this]{class},
608             link_class => $link_class,
609             local_moniker => $class[$this]{local_moniker},
610             remote_moniker => $class[$this]{remote_moniker},
611             },
612 64   66     116 };
613             }
614             }
615             }
616              
617             sub _duplicates {
618 683     683   1585 my ($self, $rels) = @_;
619              
620 683         3963 my @rels = map [ $_->{args}[0] => $_ ], @$rels;
621 683         1351 my %rel_names;
622 683         3511 $rel_names{$_}++ foreach map $_->[0], @rels;
623              
624 683         2274 my @dups = grep $rel_names{$_} > 1, keys %rel_names;
625              
626 683         1366 my %dups;
627              
628 683         1642 foreach my $dup (@dups) {
629 18         74 $dups{$dup} = [ map $_->[1], grep { $_->[0] eq $dup } @rels ];
  65         210  
630             }
631              
632 683 100       2607 return if not %dups;
633              
634 18         96 return \%dups;
635             }
636              
637             sub _tagger {
638 14     14   41 my $self = shift;
639              
640 14 100       96 $self->__tagger(Lingua::EN::Tagger->new) unless $self->__tagger;
641              
642 14         391300 return $self->__tagger;
643             }
644              
645             sub _adjectives {
646 14     14   48 my ($self, @cols) = @_;
647              
648 14         33 my @adjectives;
649              
650 14         37 foreach my $col (@cols) {
651 14         63 my @words = split_name $col;
652              
653 14         350 my $tagged = $self->_tagger->get_readable(join ' ', @words);
654              
655 14         20634 push @adjectives, $tagged =~ m{\G(\w+)/JJ\s+}g;
656             }
657              
658 14         65 return @adjectives;
659             }
660              
661             sub _name_to_identifier {
662 0     0   0 my ($self, $name) = @_;
663              
664             my $to_identifier = $self->loader->naming->{force_ascii} ?
665 0 0       0 \&String::ToIdentifier::EN::to_identifier
666             : \&String::ToIdentifier::EN::Unicode::to_identifier;
667              
668 0         0 return join '_', map lc, split_name $to_identifier->($name, '_');
669             }
670              
671             sub _disambiguate {
672 16     16   58 my ($self, $all_code, $in_class, $dups) = @_;
673              
674 16         73 DUP: foreach my $dup (keys %$dups) {
675 16         50 my @rels = @{ $dups->{$dup} };
  16         60  
676              
677             # Check if there are rels to the same table name in different
678             # schemas/databases, if so qualify them.
679             my @tables = map $self->loader->moniker_to_table->{$_->{extra}{remote_moniker}},
680 16         193 @rels;
681              
682             # databases are different, prepend database
683 16 50 0     280 if ($tables[0]->can('database') && (uniq map $_->database||'', @tables) > 1) {
    50 33        
      50        
684             # If any rels are in the same database, we have to distinguish by
685             # both schema and database.
686 0         0 my %db_counts;
687 0         0 $db_counts{$_}++ for map $_->database, @tables;
688 0     0   0 my $use_schema = any { $_ > 1 } values %db_counts;
  0         0  
689              
690 0         0 foreach my $i (0..$#rels) {
691 0         0 my $rel = $rels[$i];
692 0         0 my $table = $tables[$i];
693              
694             $rel->{args}[0] = $self->_name_to_identifier($table->database)
695             . ($use_schema ? ('_' . $self->name_to_identifier($table->schema)) : '')
696 0 0       0 . '_' . $rel->{args}[0];
697             }
698 0         0 next DUP;
699             }
700             # schemas are different, prepend schema
701             elsif ((uniq map $_->schema||'', @tables) > 1) {
702 0         0 foreach my $i (0..$#rels) {
703 0         0 my $rel = $rels[$i];
704 0         0 my $table = $tables[$i];
705              
706             $rel->{args}[0] = $self->_name_to_identifier($table->schema)
707 0         0 . '_' . $rel->{args}[0];
708             }
709 0         0 next DUP;
710             }
711              
712 16         60 foreach my $rel (@rels) {
713 32 100       189 next if $rel->{method} =~ /^(?:belongs_to|many_to_many)\z/;
714              
715 14     14   104 my @to_cols = apply { s/^foreign\.//i }
716 14         89 keys %{ $rel->{args}[2] };
  14         104  
717              
718 14         106 my @adjectives = $self->_adjectives(@to_cols);
719              
720             # If there are no adjectives, and there is only one might_have
721             # rel to that class, we hardcode 'active'.
722              
723 14         66 my $to_class = $rel->{args}[1];
724              
725 14 100 66     84 if ((not @adjectives)
726             && (grep { $_->{method} eq 'might_have'
727 21 100       140 && $_->{args}[1] eq $to_class } @{ $all_code->{$in_class} }) == 1) {
  7         37  
728              
729 7         32 @adjectives = 'active';
730             }
731              
732 14 50       63 if (@adjectives) {
733 14         68 my $rel_name = join '_', sort(@adjectives), $rel->{args}[0];
734              
735 14 50       94 ($rel_name) = $rel->{method} eq 'might_have' ?
736             $self->_inflect_singular($rel_name)
737             :
738             $self->_inflect_plural($rel_name);
739              
740             my ($local_class, $local_moniker, $remote_moniker)
741 14         81 = @{ $rel->{extra} }
742 14         57 {qw/local_class local_moniker remote_moniker/};
743              
744 14     14   84 my @from_cols = apply { s/^self\.//i }
745 14         89 values %{ $rel->{args}[2] };
  14         90  
746              
747 14         119 ($rel_name) = $self->_rel_name_map($rel_name, $rel->{method}, $local_class, $local_moniker, \@from_cols, $to_class, $remote_moniker, \@to_cols);
748              
749 14         78 $rel_name = $self->_resolve_relname_collision($local_moniker, \@from_cols, $rel_name);
750              
751 14         104 $rel->{args}[0] = $rel_name;
752             }
753             }
754             }
755              
756             # Check again for duplicates, since the heuristics above may not have resolved them all.
757              
758 16 100       86 if ($dups = $self->_duplicates($all_code->{$in_class})) {
759 2         10 foreach my $dup (keys %$dups) {
760             # sort by method
761 2         12 my @rels = map $_->[1], sort { $a->[0] <=> $b->[0] } map [
762             {
763             belongs_to => 3,
764             has_many => 2,
765             might_have => 1,
766             many_to_many => 0,
767             }->{$_->{method}}, $_
768 2         7 ], @{ $dups->{$dup} };
  2         27  
769              
770 2         6 my $rel_num = 2;
771              
772 2         9 foreach my $rel (@rels[1 .. $#rels]) {
773 2 50       13 my $inflect_type = $rel->{method} =~ /^(?:many_to_many|has_many)\z/ ?
774             'inflect_plural'
775             :
776             'inflect_singular';
777              
778 2         6 my $inflect_method = "_$inflect_type";
779              
780 2         8 my $relname_new_uninflected = $rel->{args}[0] . "_$rel_num";
781              
782 2         7 $rel_num++;
783              
784             my ($local_class, $local_moniker, $remote_moniker)
785 2         10 = @{ $rel->{extra} }
786 2         5 {qw/local_class local_moniker remote_moniker/};
787              
788 2         6 my (@from_cols, @to_cols, $to_class);
789              
790 2 50       8 if ($rel->{method} eq 'many_to_many') {
791 2     2   14 @from_cols = apply { s/^self\.//i } values %{
792 2     4   10 (first { $_->{args}[0] eq $rel->{args}[1] } @{ $all_code->{$local_class} })
  4         20  
  2         9  
793 2         10 ->{args}[2]
794             };
795 2     2   12 @to_cols = apply { s/^foreign\.//i } keys %{
796 2     3   16 (first { $_->{args}[0] eq $rel->{args}[2] }
  3         14  
797 2         9 @{ $all_code->{ $rel->{extra}{link_class} } })
798 2         9 ->{args}[2]
799             };
800 2         15 $to_class = $self->schema->source($remote_moniker)->result_class;
801             }
802             else {
803 0     0   0 @from_cols = apply { s/^self\.//i } values %{ $rel->{args}[2] };
  0         0  
  0         0  
804 0     0   0 @to_cols = apply { s/^foreign\.//i } keys %{ $rel->{args}[2] };
  0         0  
  0         0  
805 0         0 $to_class = $rel->{args}[1];
806             }
807              
808 2         192 my ($relname_new, $inflect_mapped) =
809             $self->$inflect_method($relname_new_uninflected);
810              
811 2         13 my $rel_name_mapped;
812              
813 2         15 ($relname_new, $rel_name_mapped) = $self->_rel_name_map($relname_new, $rel->{method}, $local_class, $local_moniker, \@from_cols, $to_class, $remote_moniker, \@to_cols);
814              
815 2   33     25 my $mapped = $inflect_mapped || $rel_name_mapped;
816              
817 2 50       10 warn <<"EOF" unless $mapped;
818             Could not find a proper name for relationship '$relname_new' in source
819 0         0 '$local_moniker' for columns '@{[ join ',', @from_cols ]}'. Supply a value in
820             '$inflect_type' for '$relname_new_uninflected' or 'rel_name_map' for
821             '$relname_new' to name this relationship.
822             EOF
823              
824 2         11 $relname_new = $self->_resolve_relname_collision($local_moniker, \@from_cols, $relname_new);
825              
826 2         16 $rel->{args}[0] = $relname_new;
827             }
828             }
829             }
830             }
831              
832             sub _relnames_and_method {
833 546     546   2009 my ( $self, $local_moniker, $rel, $cond, $uniqs, $counters ) = @_;
834              
835 546         1686 my $remote_moniker = $rel->{remote_source};
836 546         2320 my $remote_obj = $self->schema->source( $remote_moniker );
837 546         23766 my $remote_class = $self->schema->class( $remote_moniker );
838 546         43109 my $local_relname = $self->_local_relname( $rel->{remote_table}, $cond);
839              
840 546         1632 my $local_cols = $rel->{local_columns};
841 546         1594 my $local_table = $rel->{local_table};
842 546         3726 my $local_class = $self->schema->class($local_moniker);
843 546         54185 my $local_source = $self->schema->source($local_moniker);
844              
845 546         23866 my $remote_relname_uninflected = $self->_normalize_name($local_table);
846 546         2224 my ($remote_relname) = $self->_inflect_plural($self->_normalize_name($local_table));
847              
848 546         1705 my $remote_method = 'has_many';
849              
850             # If the local columns have a UNIQUE constraint, this is a one-to-one rel
851 546 100 100     3053 if (array_eq([ $local_source->primary_columns ], $local_cols) ||
852 181     181   913 first { array_eq($_->[1], $local_cols) } @$uniqs) {
853 68         261 $remote_method = 'might_have';
854 68         304 ($remote_relname) = $self->_inflect_singular($remote_relname_uninflected);
855             }
856              
857             # If more than one rel between this pair of tables, use the local
858             # col names to distinguish, unless the rel was created previously.
859 546 100       4922 if ($counters->{$remote_moniker} > 1) {
860 184         511 my $relationship_exists = 0;
861              
862 184 100       1273 if (-f (my $existing_remote_file = $self->loader->get_dump_filename($remote_class))) {
863 111         645 my $class = "${remote_class}Temporary";
864              
865 111 100       955 if (not Class::Inspector->loaded($class)) {
866 48         5273 my $code = slurp_file $existing_remote_file;
867              
868 48         21361 $code =~ s/(?<=package $remote_class)/Temporary/g;
869              
870 48         1090 $code =~ s/__PACKAGE__->meta->make_immutable[^;]*;//g;
871              
872 48     2   5955 eval $code;
  2     2   22  
  2     2   5  
  2     2   22  
  2     2   163  
  2     2   7  
  2     2   63  
  2     2   11  
  2     2   4  
  2     2   106  
  2     2   14  
  2     2   6  
  2     2   461  
  1     2   8  
  1     2   3  
  1     2   30  
  1     1   8  
  1     1   2  
  1     1   219  
  1     1   8  
  1     1   8  
  1     1   239  
  2     1   33  
  2     1   6  
  2     1   18  
  2     1   165  
  2     1   5  
  2     1   61  
  2     1   15  
  2     1   6  
  2     1   107  
  2     1   16  
  2     1   9  
  2     1   380  
  1     1   9  
  1     1   4  
  1     1   47  
  1     1   7  
  1     1   3  
  1     1   211  
  1     1   7  
  1     1   3  
  1     1   356  
  2     1   26  
  2     1   9  
  2     1   28  
  2     1   153  
  2     1   7  
  2     1   59  
  2     1   12  
  2     1   9  
  2     1   90  
  2     1   14  
  2     1   6  
  2     1   352  
  1     1   9  
  1     1   4  
  1     1   49  
  1     1   13  
  1     1   10  
  1     1   207  
  1     1   8  
  1     1   4  
  1     1   399  
  2     1   20  
  2     1   7  
  2     1   15  
  2     1   173  
  2     1   16  
  2     1   55  
  2     1   11  
  2     1   5  
  2     1   498  
  2     1   13  
  2     1   8  
  2     1   399  
  1     1   10  
  1     1   4  
  1     1   26  
  1     1   10  
  1         3  
  1         181  
  1         10  
  1         4  
  1         240  
  2         22  
  2         7  
  2         19  
  2         162  
  2         6  
  2         56  
  2         12  
  2         11  
  2         92  
  2         14  
  2         5  
  2         423  
  1         8  
  1         6  
  1         39  
  1         10  
  1         4  
  1         185  
  1         10  
  1         5  
  1         228  
  2         19  
  2         7  
  2         16  
  2         157  
  2         6  
  2         47  
  2         12  
  2         7  
  2         79  
  2         49  
  2         7  
  2         362  
  1         7  
  1         2  
  1         49  
  1         8  
  1         2  
  1         179  
  1         10  
  1         4  
  1         220  
  2         46  
  2         8  
  2         19  
  2         172  
  2         6  
  2         72  
  2         15  
  2         6  
  2         98  
  2         14  
  2         6  
  2         380  
  1         9  
  1         2  
  1         33  
  1         5  
  1         9  
  1         194  
  1         7  
  1         3  
  1         234  
  2         28  
  2         7  
  2         19  
  2         156  
  2         5  
  2         54  
  2         12  
  2         7  
  2         88  
  2         15  
  2         8  
  2         370  
  1         9  
  1         3  
  1         30  
  1         6  
  1         7  
  1         245  
  1         8  
  1         2  
  1         270  
  1         12  
  1         3  
  1         8  
  1         78  
  1         3  
  1         28  
  1         5  
  1         3  
  1         68  
  1         9  
  1         3  
  1         198  
  1         10  
  1         2  
  1         27  
  1         6  
  1         3  
  1         224  
  1         8  
  1         2  
  1         299  
  1         12  
  1         5  
  1         7  
  1         74  
  1         3  
  1         25  
  1         6  
  1         2  
  1         48  
  1         10  
  1         2  
  1         154  
  1         8  
  1         2  
  1         25  
  1         5  
  1         3  
  1         197  
  1         8  
  1         2  
  1         382  
  1         12  
  1         3  
  1         9  
  1         77  
  1         3  
  1         27  
  1         5  
  1         3  
  1         45  
  1         5  
  1         3  
  1         207  
  1         9  
  1         3  
  1         30  
  1         5  
  1         4  
  1         229  
  1         9  
  1         4  
  1         319  
  1         12  
  1         4  
  1         9  
  1         79  
  1         3  
  1         26  
  1         392  
  1         2  
  1         66  
  1         8  
  1         3  
  1         196  
  1         7  
  1         3  
  1         27  
  1         5  
  1         2  
  1         247  
  1         8  
  1         14  
  1         292  
  1         10  
  1         4  
  1         7  
  1         74  
  1         4  
  1         30  
  1         5  
  1         3  
  1         50  
  1         8  
  1         2  
  1         175  
  1         8  
  1         2  
  1         34  
  1         5  
  1         4  
  1         216  
  1         10  
  1         3  
  1         251  
  1         10  
  1         3  
  1         8  
  1         80  
  1         4  
  1         28  
  1         6  
  1         2  
  1         45  
  1         6  
  1         4  
  1         201  
  1         8  
  1         2  
  1         44  
  1         6  
  1         2  
  1         223  
  1         8  
  1         2  
  1         256  
  1         10  
  1         3  
  1         7  
  1         72  
  1         4  
  1         24  
  1         8  
  1         6  
  1         53  
  1         9  
  1         2  
  1         173  
  1         9  
  1         3  
  1         28  
  1         6  
  1         3  
  1         217  
  1         8  
  1         11  
  1         245  
  1         15  
  1         2  
  1         9  
  1         81  
  1         3  
  1         31  
  1         8  
  1         3  
  1         45  
  1         7  
  1         6  
  1         195  
  1         8  
  1         3  
  1         26  
  1         6  
  1         4  
  1         249  
  1         9  
  1         2  
  1         314  
  1         11  
  1         3  
  1         9  
  1         87  
  1         4  
  1         30  
  1         1747  
  1         4  
  1         58  
  1         6  
  1         3  
  1         205  
  1         8  
  1         3  
  1         30  
  1         6  
  1         3  
  1         234  
  1         10  
  1         4  
  1         283  
  1         1776  
  1         7  
  1         11  
  1         99  
  1         4  
  1         53  
  1         7  
  1         3  
  1         55  
  1         6  
  1         3  
  1         214  
  1         10  
  1         4  
  1         31  
  1         6  
  1         2  
  1         239  
  1         8  
  1         3  
  1         377  
  1         14  
  1         3  
  1         9  
  1         119  
  1         6  
  1         41  
  1         6  
  1         3  
  1         53  
  1         7  
  1         3  
  1         225  
  1         9  
  1         3  
  1         32  
  1         5  
  1         4  
  1         249  
  1         9  
  1         3  
  1         316  
  1         11  
  1         3  
  1         9  
  1         82  
  1         9  
  1         36  
  1         11  
  1         2  
  1         44  
  1         6  
  1         3  
  1         204  
  1         9  
  1         4  
  1         27  
  1         6  
  1         5  
  1         234  
  1         8  
  1         3  
  1         278  
  1         16  
  1         3  
  1         10  
  1         85  
  1         5  
  1         30  
  1         8  
  1         3  
  1         52  
  1         6  
  1         3  
  1         213  
  1         9  
  1         3  
  1         44  
  1         7  
  1         3  
  1         219  
  1         8  
  1         3  
  1         259  
  1         13  
  1         3  
  1         10  
  1         80  
  1         3  
  1         28  
  1         7  
  1         2  
  1         45  
  1         6  
  1         4  
  1         227  
  1         10  
  1         4  
  1         31  
  1         6  
  1         3  
  1         249  
  1         7  
  1         4  
  1         260  
  1         10  
  1         2  
  1         9  
  1         86  
  1         2  
  1         27  
  1         7  
  1         2  
  1         41  
  1         7  
  1         3  
  1         181  
  1         9  
  1         3  
  1         29  
  1         5  
  1         4  
  1         313  
  1         12  
  1         8  
  1         274  
  1         15  
  1         2  
  1         11  
  1         82  
  1         5  
  1         27  
  1         7  
  1         3  
  1         53  
  1         10  
  1         3  
  1         165  
  1         10  
  1         3  
  1         26  
  1         8  
  1         5  
  1         225  
  1         8  
  1         4  
  1         347  
  1         12  
  1         3  
  1         13  
  1         84  
  1         4  
  1         29  
  1         6  
  1         7  
  1         75  
  1         14  
  1         3  
  1         218  
  1         8  
  1         3  
  1         28  
  1         5  
  1         2  
  1         287  
  1         8  
  1         2  
  1         291  
  1         10  
  1         2  
  1         11  
  1         77  
  1         3  
  1         27  
  1         7  
  1         2  
  1         62  
  1         8  
  1         4  
  1         171  
  1         9  
  1         3  
  1         27  
  1         5  
  1         4  
  1         214  
  1         8  
  1         3  
  1         402  
  1         11  
  1         4  
  1         8  
  1         81  
  1         3  
  1         28  
  1         8  
  1         3  
  1         46  
  1         6  
  1         2  
  1         206  
  1         9  
  1         2  
  1         28  
  1         6  
  1         2  
  1         242  
  1         7  
  1         3  
  1         333  
  1         10  
  1         3  
  1         7  
  1         127  
  1         3  
  1         34  
  1         6  
  1         2  
  1         37  
  1         18  
  1         4  
  1         175  
  1         7  
  1         4  
  1         44  
  1         7  
  1         3  
  1         210  
  1         10  
  1         3  
  1         313  
  1         13  
  1         12  
  1         9  
  1         77  
  1         5  
  1         29  
  1         5  
  1         4  
  1         69  
  1         8  
  1         6  
  1         172  
  1         9  
  1         4  
  1         30  
  1         5  
  1         3  
  1         219  
  1         12  
  1         4  
  1         286  
  1         11  
  1         3  
  1         8  
  1         82  
  1         3  
  1         28  
  1         6  
  1         2  
  1         42  
  1         6  
  1         3  
  1         210  
  1         9  
  1         2  
  1         45  
  1         7  
  1         2  
  1         249  
  1         9  
  1         3  
  1         251  
  1         10  
  1         3  
  1         8  
  1         119  
  1         3  
  1         28  
  1         7  
  1         2  
  1         45  
  1         6  
  1         3  
  1         265  
  1         8  
  1         2  
  1         43  
  1         6  
  1         4  
  1         220  
  1         9  
  1         3  
  1         274  
  1         12  
  1         5  
  1         8  
  1         143  
  1         3  
  1         31  
  1         6  
  1         3  
  1         62  
  1         8  
  1         2  
  1         280  
  1         9  
  1         3  
  1         43  
  1         7  
  1         6  
  1         233  
  1         8  
  1         3  
  1         301  
  1         11  
  1         3  
  1         10  
  1         85  
  1         12  
  1         35  
  1         12  
  1         19  
  1         48  
  1         10  
  1         3  
  1         242  
  1         10  
  1         3  
  1         53  
  1         13  
  1         5  
  1         259  
  1         10  
  1         9  
  1         327  
  1         18  
  1         4  
  1         14  
  1         85  
  1         6  
  1         34  
  1         6  
  1         2  
  1         49  
  1         8  
  1         4  
  1         166  
  1         12  
  1         5  
  1         30  
  1         7  
  1         8  
  1         223  
  1         8  
  1         5  
  1         445  
  1         11  
  1         3  
  1         10  
  1         90  
  1         4  
  1         28  
  1         7  
  1         4  
  1         48  
  1         8  
  1         3  
  1         194  
  1         10  
  1         4  
  1         32  
  1         7  
  1         6  
  1         269  
  1         11  
  1         3  
  1         442  
  1         12  
  1         4  
  1         10  
  1         76  
  1         4  
  1         27  
  1         7  
  1         3  
  1         32  
  1         6  
  1         4  
  1         162  
  1         10  
  1         8  
  1         49  
  1         8  
  1         2  
  1         217  
  1         10  
  1         2  
  1         363  
  1         11  
  1         4  
  1         6  
  1         92  
  1         3  
  1         26  
  1         5  
  1         3  
  1         32  
  1         8  
  1         3  
  1         162  
  1         8  
  1         2  
  1         25  
  1         4  
  1         3  
  1         213  
  1         9  
  1         3  
  1         267  
  1         11  
  1         5  
  1         8  
  1         90  
  1         3  
  1         26  
  1         7  
  1         5  
  1         47  
  1         6  
  1         4  
  1         196  
  1         9  
  1         4  
  1         33  
  1         5  
  1         3  
  1         234  
  1         11  
  1         3  
  1         266  
  1         9  
  1         3  
  1         6  
  1         73  
  1         3  
  1         24  
  1         6  
  1         3  
  1         31  
  1         7  
  1         2  
  1         146  
  1         9  
  1         4  
  1         31  
  1         5  
  1         3  
  1         208  
  1         10  
  1         2  
  1         239  
  1         13  
  1         4  
  1         7  
  1         83  
  1         4  
  1         28  
  1         6  
  1         3  
  1         56  
  1         8  
  1         2  
  1         243  
  1         8  
  1         2  
  1         55  
  1         7  
  1         6  
  1         239  
  1         8  
  1         3  
  1         325  
873 48 50       382 die $@ if $@;
874              
875 48         159 push @{ $self->_temp_classes }, $class;
  48         352  
876             }
877              
878 111 100       7108 if ($class->has_relationship($remote_relname)) {
879 0     5   0 my $rel_cols = [ sort { $a cmp $b } apply { s/^foreign\.//i }
  5         38  
880 5         354 (keys %{ $class->relationship_info($remote_relname)->{cond} }) ];
  5         269  
881              
882 5 50       44 $relationship_exists = 1 if array_eq([ sort @$local_cols ], $rel_cols);
883             }
884             }
885              
886 184 100       7236 if (not $relationship_exists) {
887 179         1280 my $colnames = q{_} . $self->_normalize_name(join '_', @$local_cols);
888 179 100       913 $local_relname .= $colnames if keys %$cond > 1;
889              
890 179         927 $remote_relname = $self->_strip_id_postfix($self->_normalize_name($local_table . $colnames));
891              
892 179         556 $remote_relname_uninflected = $remote_relname;
893 179         705 ($remote_relname) = $self->_inflect_plural($remote_relname);
894              
895             # if colnames were added and this is a might_have, re-inflect
896 179 100       901 if ($remote_method eq 'might_have') {
897 2         20 ($remote_relname) = $self->_inflect_singular($remote_relname_uninflected);
898             }
899             }
900             }
901              
902 546         3145 return ($local_relname, $remote_relname, $remote_method);
903             }
904              
905             sub _rel_name_map {
906 1301     1301   4388 my ($self, $relname, $method, $local_class, $local_moniker, $local_cols,
907             $remote_class, $remote_moniker, $remote_cols, $extra) = @_;
908              
909             my $info = {
910 1301 100       2457 %{$extra || {}},
  1301         13593  
911             name => $relname,
912             type => $method,
913             local_class => $local_class,
914             local_moniker => $local_moniker,
915             local_columns => $local_cols,
916             remote_class => $remote_class,
917             remote_moniker => $remote_moniker,
918             remote_columns => $remote_cols,
919             };
920              
921 1301         6316 $self->_run_user_map($self->rel_name_map, $info);
922             }
923              
924             sub _run_user_map {
925 1303     1303   6915 my ($self, $map, $info) = @_;
926              
927 1303         2800 my $new_name = $info->{name};
928 1303         2230 my $mapped = 0;
929              
930 1303 100       4732 if ('HASH' eq ref($map)) {
    100          
931 18         37 my $name = $info->{name};
932 18         38 my $moniker = $info->{local_moniker};
933 18 100 66     151 if ($map->{$moniker} and 'HASH' eq ref($map->{$moniker})
    100 66        
      66        
934             and $map->{$moniker}{$name}
935             ) {
936 3         9 $new_name = $map->{$moniker}{$name};
937 3         9 $mapped = 1;
938             }
939             elsif ($map->{$name} and not 'HASH' eq ref($map->{$name})) {
940 3         13 $new_name = $map->{$name};
941 3         7 $mapped = 1;
942             }
943             }
944             elsif ('CODE' eq ref($map)) {
945             my $cb = sub {
946 3     3   2517 my ($cb_map) = @_;
947 3 100       20 croak "reentered rel_name_map must be a hashref"
948             unless 'HASH' eq ref($cb_map);
949 2         9 my ($cb_name, $cb_mapped) = $self->_run_user_map($cb_map, $info);
950 2   33     10 return $cb_mapped && $cb_name;
951 15         72 };
952 15         61 my $name = $map->($info, $cb);
953 14 100       8257 if ($name) {
954 6         13 $new_name = $name;
955 6         37 $mapped = 1;
956             }
957             }
958              
959 1302         6078 return ($new_name, $mapped);
960             }
961              
962             sub _cleanup {
963 115     115   362 my $self = shift;
964              
965 115         354 for my $class (@{ $self->_temp_classes }) {
  115         944  
966 48         23409 Class::Unload->unload($class);
967             }
968              
969 115         11251 $self->_temp_classes([]);
970             }
971              
972             =head1 AUTHORS
973              
974             See L.
975              
976             =head1 LICENSE
977              
978             This library is free software; you can redistribute it and/or modify it under
979             the same terms as Perl itself.
980              
981             =cut
982              
983             1;
984             # vim:et sts=4 sw=4 tw=0: