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 52     52   348 use strict;
  52         148  
  52         2270  
4 52     52   258 use warnings;
  52         103  
  52         2773  
5 52     52   305 use base 'Class::Accessor::Grouped';
  52         121  
  52         7465  
6 52     52   365 use mro 'c3';
  52         107  
  52         359  
7 52     52   2208 use Carp::Clan qw/^DBIx::Class/;
  52         161  
  52         362  
8 52     52   5842 use Scalar::Util 'weaken';
  52         172  
  52         4328  
9 52     52   1011 use DBIx::Class::Schema::Loader::Utils qw/split_name slurp_file array_eq apply uniq/;
  52         244  
  52         4174  
10 52     52   846 use Try::Tiny;
  52         328  
  52         4325  
11 52     52   573 use List::Util qw/all any first/;
  52         197  
  52         4206  
12 52     52   366 use namespace::clean;
  52         126  
  52         530  
13 52     52   60862 use Lingua::EN::Inflect::Phrase ();
  52         4219899  
  52         1841  
14 52     52   503 use Lingua::EN::Tagger ();
  52         162  
  52         941  
15 52     52   30428 use String::ToIdentifier::EN ();
  52         2398879  
  52         2222  
16 52     52   33959 use String::ToIdentifier::EN::Unicode ();
  52         29433  
  52         1608  
17 52     52   24623 use Class::Unload ();
  52         243215  
  52         1596  
18 52     52   403 use Class::Inspector ();
  52         113  
  52         399971  
19              
20             our $VERSION = '0.07053';
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 144     144 1 719 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 144         676 (map { $_ => $loader->$_ } qw(
  1008         42819  
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 144         11133 weaken $self->{loader}; #< don't leak
148              
149 144         680 bless $self => $class;
150              
151             # validate the relationship_attrs arg
152 144 100       1440 if( defined $self->relationship_attrs ) {
153 5 100 100     396 (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 142         14535 return $self;
158             }
159              
160              
161             # pluralize a relationship name
162             sub _inflect_plural {
163 902     902   2881 my ($self, $relname) = @_;
164              
165 902 50 33     5891 return '' if !defined $relname || $relname eq '';
166              
167 902         2243 my $result;
168 902         2091 my $mapped = 0;
169              
170 902 100       5992 if( ref $self->inflect_plural eq 'HASH' ) {
    50          
171 404 100       2363 if (exists $self->inflect_plural->{$relname}) {
172 6         27 $result = $self->inflect_plural->{$relname};
173 6         16 $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 902 100       14073 return ($result, $mapped) if $mapped;
185              
186 896         4297 return ($self->_to_PL($relname), 0);
187             }
188              
189             # Singularize a relationship name
190             sub _inflect_singular {
191 740     740   2615 my ($self, $relname) = @_;
192              
193 740 50 33     6029 return '' if !defined $relname || $relname eq '';
194              
195 740         1997 my $result;
196 740         2007 my $mapped = 0;
197              
198 740 100       5486 if( ref $self->inflect_singular eq 'HASH' ) {
    50          
199 297 100       1716 if (exists $self->inflect_singular->{$relname}) {
200 6         28 $result = $self->inflect_singular->{$relname};
201 6         21 $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 740 100       13940 return ($result, $mapped) if $mapped;
213              
214 734         3451 return ($self->_to_S($relname), 0);
215             }
216              
217             sub _to_PL {
218 831     831   5924 my ($self, $name) = @_;
219              
220 831         4205 $name =~ s/_/ /g;
221 831         4092 my $plural = Lingua::EN::Inflect::Phrase::to_PL($name);
222 831         3276887 $plural =~ s/ /_/g;
223              
224 831         4628 return $plural;
225             }
226              
227             sub _to_S {
228 668     668   2348 my ($self, $name) = @_;
229              
230 668         3109 $name =~ s/_/ /g;
231 668         3568 my $singular = Lingua::EN::Inflect::Phrase::to_S($name);
232 668         2607097 $singular =~ s/ /_/g;
233              
234 668         3963 return $singular;
235             }
236              
237             sub _default_relationship_attrs { +{
238 1238     1238   68900 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 1310     1310   12087 my ( $self, $reltype, $db_attrs, $params ) = @_;
262 1310         5088 my $r = $self->relationship_attrs;
263              
264             my %composite = (
265 1310 100       5025 %{ $self->_default_relationship_attrs->{$reltype} || {} },
266 1310 50       11200 %{ $db_attrs || {} },
267             (
268             ref $r eq 'HASH' ? (
269 546 100       3148 %{ $r->{all} || {} },
270 1310 100       2689 %{ $r->{$reltype} || {} },
  546 100       3860  
271             )
272             :
273             ()
274             ),
275             );
276              
277 1310 100       6438 if (ref $r eq 'CODE') {
278 2         9 $params->{attrs} = \%composite;
279              
280 2 50       5 my %ret = %{ $r->(%$params) || {} };
  2         17  
281              
282 2 50       4243 %composite = %ret if %ret;
283             }
284              
285 1310 100       28028 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 594     594   2548 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 594   50     3371 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 594     643   7019 my $nullable = first { $self->schema->source($local_moniker)->column_info($_)->{is_nullable} } @$local_cols;
  643         7593  
305 594 100 66     52682 $attrs->{join_type} = 'LEFT' if $nullable && !defined $attrs->{join_type};
306              
307 594         7404 return $attrs;
308             }
309              
310             sub _sanitize_name {
311 2137     2137   5522 my ($self, $name) = @_;
312              
313 2137         13308 $name = $self->loader->_to_identifier('relationships', $name, '_');
314              
315 2137         10065 $name =~ s/\W+/_/g; # if naming >= 8 to_identifier takes care of it
316              
317 2137         5846 return $name;
318             }
319              
320             sub _normalize_name {
321 2105     2105   6326 my ($self, $name) = @_;
322              
323 2105         7993 $name = $self->_sanitize_name($name);
324              
325 2105         8340 my @words = split_name $name, $self->loader->_get_naming_v('relationships');
326              
327 2105         20251 return join '_', map lc, @words;
328             }
329              
330             sub _local_relname {
331 595     595   2446 my ($self, $remote_table, $cond) = @_;
332              
333 595         1871 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 595 100       1646 if(scalar keys %{$cond} == 1) {
  595         4013  
337 546         1797 my ($col) = values %{$cond};
  546         2207  
338 546         2909 $col = $self->_strip_id_postfix($self->_normalize_name($col));
339 546         3632 ($local_relname) = $self->_inflect_singular($col);
340             }
341             else {
342 49         218 ($local_relname) = $self->_inflect_singular($self->_normalize_name($remote_table));
343             }
344              
345 595         15316 return $local_relname;
346             }
347              
348             sub _resolve_relname_collision {
349 1384     1384   4535 my ($self, $moniker, $cols, $relname) = @_;
350              
351 1384 100       4537 return $relname if $relname eq 'id'; # this shouldn't happen, but just in case
352              
353 1370         8722 my $table = $self->loader->moniker_to_table->{$moniker};
354              
355 1370 100       7643 if ($self->loader->_is_result_class_method($relname, $table)) {
356 14 100       99 if (my $map = $self->rel_collision_map) {
357 12         368 for my $re (keys %$map) {
358 12 100       132 if (my @matches = $relname =~ /$re/) {
359 6         52 return sprintf $map->{$re}, @matches;
360             }
361             }
362             }
363              
364 8         29 my $new_relname = $relname;
365 8         44 while ($self->loader->_is_result_class_method($new_relname, $table)) {
366 8         62 $new_relname .= '_rel'
367             }
368              
369 8         26 warn <<"EOF";
370 8         165 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         55 return $new_relname;
375             }
376              
377 1356         4745 return $relname;
378             }
379              
380             sub generate_code {
381 147     147 1 908 my ($self, $tables) = @_;
382              
383             # make a copy to destroy
384 147         974 my @tables = @$tables;
385              
386 147         577 my $all_code = {};
387              
388 147 100       717 while (my ($local_moniker, $rels, $uniqs) = @{ shift @tables || [] }) {
  987         8561  
389 841         6595 my $local_class = $self->schema->class($local_moniker);
390              
391 841         116368 my %counters;
392 841         3443 foreach my $rel (@$rels) {
393 653 50       3279 next if !$rel->{remote_source};
394 653         2831 $counters{$rel->{remote_source}}++;
395             }
396              
397 841         2842 foreach my $rel (@$rels) {
398             my $remote_moniker = $rel->{remote_source}
399 653 50       3114 or next;
400              
401 653         3664 my $remote_class = $self->schema->class($remote_moniker);
402 653         62732 my $remote_obj = $self->schema->source($remote_moniker);
403 653   100     32061 my $remote_cols = $rel->{remote_columns} || [ $remote_obj->primary_columns ];
404              
405 653         2775 my $local_cols = $rel->{local_columns};
406              
407 653 50       3081 if($#$local_cols != $#$remote_cols) {
408 0         0 croak "Column count mismatch: $local_moniker (@$local_cols) "
409             . "$remote_moniker (@$remote_cols)";
410             }
411              
412 653         1818 my %cond;
413 653         3743 @cond{@$remote_cols} = @$local_cols;
414              
415 653         4719 my ( $local_relname, $remote_relname, $remote_method ) =
416             $self->_relnames_and_method( $local_moniker, $rel, \%cond, $uniqs, \%counters );
417 653         2454 my $local_method = 'belongs_to';
418              
419 653         4482 ($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 652         2633 ($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 652         3949 $local_relname = $self->_resolve_relname_collision(
431             $local_moniker, $local_cols, $local_relname,
432             );
433 652         2538 $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 652         13973 remote_cols => $remote_cols,
446             };
447              
448 652         6972 push @{$all_code->{$local_class}}, {
449             method => $local_method,
450             args => [
451             $local_relname,
452             $remote_class,
453             \%cond,
454 652         84693 $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 652         3720 my %rev_cond = reverse %cond;
464 652         2573 for (keys %rev_cond) {
465 701         3647 $rev_cond{"foreign.$_"} = "self.".$rev_cond{$_};
466 701         2449 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 652         4286 remote_cols => $local_cols,
478             };
479              
480 652         68442 push @{$all_code->{$remote_class}}, {
  652         4579  
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 146         1709 $self->_generate_m2ms($all_code);
498              
499             # disambiguate rels with the same name
500 146         788 foreach my $class (keys %$all_code) {
501 737         3105 my $dups = $self->_duplicates($all_code->{$class});
502              
503 737 100       2603 $self->_disambiguate($all_code, $class, $dups) if $dups;
504             }
505              
506 146         1513 $self->_cleanup;
507              
508 146         881 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 146     146   595 my ($self, $all_code) = @_;
514              
515             LINK_CLASS:
516 146         1440 foreach my $link_class (sort keys %$all_code) {
517 737         1440 my @rels = grep $_->{method} eq 'belongs_to', @{$all_code->{$link_class}};
  737         4505  
518 737 100       2713 next unless @rels == 2;
519              
520 118         252 my @class;
521 118         341 foreach my $this (0, 1) {
522 229 100       721 my $that = $this ? 0 : 1;
523 229         459 my %class;
524 229         567 $class[$this] = \%class;
525 229         1029 $class{local_moniker} = $rels[$this]{extra}{remote_moniker};
526 229         793 $class{remote_moniker} = $rels[$that]{extra}{remote_moniker};
527              
528 229         852 $class{class} = $rels[$this]{args}[1];
529              
530 229     271   1059 my %link_cols = map { $_ => 1 } apply { s/^self\.//i } values %{ $rels[$this]{args}[2] };
  271         1097  
  271         782  
  229         1344  
531              
532             $class{link_table_rel} = first {
533             $_->{method} eq 'has_many'
534             and
535             $_->{args}[1] eq $link_class
536             and
537 496 100 100 496   3831 all { $link_cols{$_} } apply { s/^foreign\.//i } keys %{$_->{args}[2]}
  351         1485  
  357         1956  
  301         1374  
538 229         1475 } @{ $all_code->{$class{class}} };
  229         1174  
539              
540 229 100       1746 next LINK_CLASS unless $class{link_table_rel};
541              
542 222         853 $class{link_table_rel_name} = $class{link_table_rel}{args}[0];
543              
544 222         759 $class{link_rel} = $rels[$that]{args}[0];
545              
546 264     264   1247 $class{from_cols} = [ apply { s/^self\.//i } values %{
547 222         780 $class{link_table_rel}->{args}[2]
  222         928  
548             } ];
549              
550 222     264   925 $class{to_cols} = [ apply { s/^foreign\.//i } keys %{ $rels[$that]{args}[2] } ];
  264         620  
  222         1030  
551              
552 222     264   925 $class{from_link_cols} = [ apply { s/^self\.//i } values %{ $rels[$this]{args}[2] } ];
  264         691  
  222         930  
553             }
554              
555 111         440 my $link_moniker = $rels[0]{extra}{local_moniker};
556              
557             my @link_table_cols =
558 111         268 @{[ $self->schema->source($link_moniker)->columns ]};
  111         850  
559              
560             my @link_table_primary_cols =
561 111         9982 @{[ $self->schema->source($link_moniker)->primary_columns ]};
  111         577  
562              
563             next unless array_eq(
564 111 100 33     6662 [ sort +uniq @{$class[0]{from_link_cols}}, @{$class[1]{from_link_cols}} ],
  111   66     382  
  111         629  
565             [ sort @link_table_primary_cols ],
566             ) && ($self->allow_extra_m2m_cols || @link_table_cols == @link_table_primary_cols);
567              
568 32         961 foreach my $this (0, 1) {
569 64 100       222 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         451 @{$class[$this]}{qw(class local_moniker from_cols)},
574             $class[$that]{class},
575 64         703 @{$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         331 );
582              
583             $class[$this]{m2m_relname} = $self->_resolve_relname_collision(
584 64         300 @{$class[$this]}{qw(local_moniker from_cols m2m_relname)},
  64         351  
585             );
586             }
587              
588 32         115 for my $this (0, 1) {
589 64 100       236 my $that = $this ? 0 : 1;
590              
591 64         256 push @{$all_code->{$class[$this]{class}}}, {
592             method => 'many_to_many',
593             args => [
594 64         557 @{$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     150 };
613             }
614             }
615             }
616              
617             sub _duplicates {
618 753     753   1745 my ($self, $rels) = @_;
619              
620 753         5246 my @rels = map [ $_->{args}[0] => $_ ], @$rels;
621 753         1425 my %rel_names;
622 753         4135 $rel_names{$_}++ foreach map $_->[0], @rels;
623              
624 753         2676 my @dups = grep $rel_names{$_} > 1, keys %rel_names;
625              
626 753         1626 my %dups;
627              
628 753         1720 foreach my $dup (@dups) {
629 18         50 $dups{$dup} = [ map $_->[1], grep { $_->[0] eq $dup } @rels ];
  65         224  
630             }
631              
632 753 100       3469 return if not %dups;
633              
634 18         102 return \%dups;
635             }
636              
637             sub _tagger {
638 14     14   33 my $self = shift;
639              
640 14 100       119 $self->__tagger(Lingua::EN::Tagger->new) unless $self->__tagger;
641              
642 14         575949 return $self->__tagger;
643             }
644              
645             sub _adjectives {
646 14     14   51 my ($self, @cols) = @_;
647              
648 14         36 my @adjectives;
649              
650 14         40 foreach my $col (@cols) {
651 14         77 my @words = split_name $col;
652              
653 14         393 my $tagged = $self->_tagger->get_readable(join ' ', @words);
654              
655 14         26359 push @adjectives, $tagged =~ m{\G(\w+)/JJ\s+}g;
656             }
657              
658 14         68 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   75 my ($self, $all_code, $in_class, $dups) = @_;
673              
674 16         62 DUP: foreach my $dup (keys %$dups) {
675 16         39 my @rels = @{ $dups->{$dup} };
  16         61  
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         219 @rels;
681              
682             # databases are different, prepend database
683 16 50 0     345 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       239 next if $rel->{method} =~ /^(?:belongs_to|many_to_many)\z/;
714              
715 14     14   103 my @to_cols = apply { s/^foreign\.//i }
716 14         86 keys %{ $rel->{args}[2] };
  14         94  
717              
718 14         128 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         68 my $to_class = $rel->{args}[1];
724              
725 14 100 66     100 if ((not @adjectives)
726             && (grep { $_->{method} eq 'might_have'
727 21 100       180 && $_->{args}[1] eq $to_class } @{ $all_code->{$in_class} }) == 1) {
  7         35  
728              
729 7         32 @adjectives = 'active';
730             }
731              
732 14 50       67 if (@adjectives) {
733 14         75 my $rel_name = join '_', sort(@adjectives), $rel->{args}[0];
734              
735 14 50       143 ($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         110 = @{ $rel->{extra} }
742 14         48 {qw/local_class local_moniker remote_moniker/};
743              
744 14     14   109 my @from_cols = apply { s/^self\.//i }
745 14         138 values %{ $rel->{args}[2] };
  14         153  
746              
747 14         137 ($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         79 $rel_name = $self->_resolve_relname_collision($local_moniker, \@from_cols, $rel_name);
750              
751 14         127 $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       106 if ($dups = $self->_duplicates($all_code->{$in_class})) {
759 2         8 foreach my $dup (keys %$dups) {
760             # sort by method
761 2         17 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         6 ], @{ $dups->{$dup} };
  2         38  
769              
770 2         8 my $rel_num = 2;
771              
772 2         11 foreach my $rel (@rels[1 .. $#rels]) {
773 2 50       21 my $inflect_type = $rel->{method} =~ /^(?:many_to_many|has_many)\z/ ?
774             'inflect_plural'
775             :
776             'inflect_singular';
777              
778 2         8 my $inflect_method = "_$inflect_type";
779              
780 2         9 my $relname_new_uninflected = $rel->{args}[0] . "_$rel_num";
781              
782 2         8 $rel_num++;
783              
784             my ($local_class, $local_moniker, $remote_moniker)
785 2         14 = @{ $rel->{extra} }
786 2         6 {qw/local_class local_moniker remote_moniker/};
787              
788 2         5 my (@from_cols, @to_cols, $to_class);
789              
790 2 50       12 if ($rel->{method} eq 'many_to_many') {
791 2     2   21 @from_cols = apply { s/^self\.//i } values %{
792 2     4   15 (first { $_->{args}[0] eq $rel->{args}[1] } @{ $all_code->{$local_class} })
  4         27  
  2         16  
793 2         13 ->{args}[2]
794             };
795 2     2   6 @to_cols = apply { s/^foreign\.//i } keys %{
796 2     3   18 (first { $_->{args}[0] eq $rel->{args}[2] }
  3         22  
797 2         15 @{ $all_code->{ $rel->{extra}{link_class} } })
798 2         10 ->{args}[2]
799             };
800 2         27 $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         358 my ($relname_new, $inflect_mapped) =
809             $self->$inflect_method($relname_new_uninflected);
810              
811 2         8 my $rel_name_mapped;
812              
813 2         21 ($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     15 my $mapped = $inflect_mapped || $rel_name_mapped;
816              
817 2 50       9 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         16 $relname_new = $self->_resolve_relname_collision($local_moniker, \@from_cols, $relname_new);
825              
826 2         36 $rel->{args}[0] = $relname_new;
827             }
828             }
829             }
830             }
831              
832             sub _relnames_and_method {
833 588     588   3361 my ( $self, $local_moniker, $rel, $cond, $uniqs, $counters ) = @_;
834              
835 588         2389 my $remote_moniker = $rel->{remote_source};
836 588         9937 my $remote_obj = $self->schema->source( $remote_moniker );
837 588         28959 my $remote_class = $self->schema->class( $remote_moniker );
838 588         72542 my $local_relname = $self->_local_relname( $rel->{remote_table}, $cond);
839              
840 588         2689 my $local_cols = $rel->{local_columns};
841 588         2064 my $local_table = $rel->{local_table};
842 588         6168 my $local_class = $self->schema->class($local_moniker);
843 588         73711 my $local_source = $self->schema->source($local_moniker);
844              
845 588         31500 my $remote_relname_uninflected = $self->_normalize_name($local_table);
846 588         2565 my ($remote_relname) = $self->_inflect_plural($self->_normalize_name($local_table));
847              
848 588         2392 my $remote_method = 'has_many';
849              
850             # If the local columns have a UNIQUE constraint, this is a one-to-one rel
851 588 100 100     6173 if (array_eq([ $local_source->primary_columns ], $local_cols) ||
852 187     187   928 first { array_eq($_->[1], $local_cols) } @$uniqs) {
853 70         248 $remote_method = 'might_have';
854 70         439 ($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 588 100       7598 if ($counters->{$remote_moniker} > 1) {
860 188         614 my $relationship_exists = 0;
861              
862 188 100       1994 if (-f (my $existing_remote_file = $self->loader->get_dump_filename($remote_class))) {
863 115         602 my $class = "${remote_class}Temporary";
864              
865 115 100       1495 if (not Class::Inspector->loaded($class)) {
866 50         6167 my $code = slurp_file $existing_remote_file;
867              
868 50         27573 $code =~ s/(?<=package $remote_class)/Temporary/g;
869              
870 50         519 $code =~ s/__PACKAGE__->meta->make_immutable[^;]*;//g;
871              
872 50     4   6748 eval $code;
  4     4   50  
  4     2   10  
  4     2   35  
  4     2   317  
  4     2   13  
  4     2   108  
  4     2   19  
  4     2   9  
  4     2   315  
  4     2   26  
  4     2   11  
  4     2   1047  
  1     2   10  
  1     2   4  
  1     2   73  
  1     1   9  
  1     1   6  
  1     1   288  
  1     1   10  
  1     1   3  
  1     1   304  
  2     1   23  
  2     1   6  
  2     1   18  
  2     1   172  
  2     1   5  
  2     1   69  
  2     1   10  
  2     1   5  
  2     1   183  
  2     1   14  
  2     1   5  
  2     1   569  
  1     1   10  
  1     1   3  
  1     1   43  
  1     1   7  
  1     1   3  
  1     1   276  
  1     1   11  
  1     1   3  
  1     1   453  
  2     1   26  
  2     1   7  
  2     1   19  
  2     1   179  
  2     1   6  
  2     1   66  
  2     1   10  
  2     1   25  
  2     1   215  
  2     1   16  
  2     1   5  
  2     1   398  
  1     1   10  
  1     1   3  
  1     1   60  
  1     1   8  
  1     1   3  
  1     1   286  
  1     1   10  
  1     1   3  
  1     1   454  
  2     1   21  
  2     1   5  
  2     1   19  
  2     1   173  
  2     1   7  
  2     1   69  
  2     1   11  
  2     1   5  
  2     1   186  
  2     1   16  
  2     1   5  
  2     1   646  
  1     1   10  
  1     1   3  
  1     1   45  
  1     1   10  
  1         2  
  1         319  
  1         10  
  1         3  
  1         383  
  2         25  
  2         7  
  2         21  
  2         222  
  2         6  
  2         86  
  2         12  
  2         6  
  2         225  
  2         19  
  2         6  
  2         639  
  1         10  
  1         4  
  1         45  
  1         9  
  1         3  
  1         307  
  1         10  
  1         3  
  1         356  
  2         27  
  2         7  
  2         18  
  2         236  
  2         8  
  2         97  
  2         15  
  2         6  
  2         187  
  2         18  
  2         6  
  2         624  
  1         11  
  1         4  
  1         45  
  1         7  
  1         4  
  1         338  
  1         12  
  1         3  
  1         300  
  2         23  
  2         7  
  2         18  
  2         178  
  2         6  
  2         94  
  2         12  
  2         6  
  2         175  
  2         27  
  2         7  
  2         433  
  1         12  
  1         3  
  1         81  
  1         9  
  1         4  
  1         320  
  1         10  
  1         2  
  1         355  
  2         27  
  2         7  
  2         19  
  2         174  
  2         6  
  2         107  
  2         14  
  2         6  
  2         190  
  2         16  
  2         6  
  2         481  
  1         10  
  1         3  
  1         45  
  1         8  
  1         3  
  1         286  
  1         10  
  1         3  
  1         400  
  1         12  
  1         3  
  1         9  
  1         114  
  1         3  
  1         46  
  1         7  
  1         3  
  1         84  
  1         9  
  1         3  
  1         274  
  1         10  
  1         3  
  1         36  
  1         5  
  1         2  
  1         253  
  1         6  
  1         2  
  1         367  
  1         9  
  1         2  
  1         7  
  1         61  
  1         2  
  1         27  
  1         4  
  1         3  
  1         79  
  1         6  
  1         2  
  1         174  
  1         6  
  1         2  
  1         22  
  1         3  
  1         1  
  1         238  
  1         7  
  1         1  
  1         314  
  1         13  
  1         3  
  1         9  
  1         108  
  1         3  
  1         42  
  1         7  
  1         3  
  1         91  
  1         8  
  1         4  
  1         260  
  1         10  
  1         2  
  1         91  
  1         9  
  1         3  
  1         314  
  1         12  
  1         3  
  1         451  
  1         8  
  1         3  
  1         7  
  1         60  
  1         22  
  1         30  
  1         4  
  1         2  
  1         61  
  1         6  
  1         1  
  1         190  
  1         6  
  1         2  
  1         22  
  1         4  
  1         2  
  1         217  
  1         6  
  1         2  
  1         242  
  1         11  
  1         3  
  1         10  
  1         148  
  1         4  
  1         46  
  1         7  
  1         3  
  1         84  
  1         8  
  1         3  
  1         238  
  1         10  
  1         3  
  1         41  
  1         6  
  1         3  
  1         325  
  1         9  
  1         4  
  1         375  
  1         13  
  1         4  
  1         11  
  1         134  
  1         4  
  1         54  
  1         7  
  1         2  
  1         96  
  1         10  
  1         4  
  1         285  
  1         11  
  1         3  
  1         43  
  1         8  
  1         3  
  1         348  
  1         10  
  1         3  
  1         412  
  1         13  
  1         3  
  1         9  
  1         114  
  1         3  
  1         78  
  1         9  
  1         3  
  1         95  
  1         9  
  1         3  
  1         256  
  1         10  
  1         5  
  1         65  
  1         7  
  1         3  
  1         368  
  1         10  
  1         4  
  1         347  
  1         14  
  1         4  
  1         8  
  1         104  
  1         4  
  1         42  
  1         6  
  1         3  
  1         123  
  1         10  
  1         2  
  1         279  
  1         9  
  1         3  
  1         37  
  1         7  
  1         3  
  1         349  
  1         10  
  1         3  
  1         425  
  1         11  
  1         2  
  1         8  
  1         60  
  1         3  
  1         26  
  1         4  
  1         2  
  1         113  
  1         7  
  1         2  
  1         228  
  1         10  
  1         3  
  1         32  
  1         5  
  1         2  
  1         218  
  1         6  
  1         2  
  1         230  
  1         11  
  1         4  
  1         11  
  1         107  
  1         3  
  1         44  
  1         7  
  1         2  
  1         86  
  1         10  
  1         3  
  1         254  
  1         10  
  1         4  
  1         43  
  1         8  
  1         2  
  1         366  
  1         9  
  1         3  
  1         476  
  1         9  
  1         3  
  1         7  
  1         58  
  1         1  
  1         26  
  1         3  
  1         2  
  1         58  
  1         4  
  1         3  
  1         175  
  1         6  
  1         2  
  1         23  
  1         3  
  1         3  
  1         233  
  1         7  
  1         2  
  1         271  
  1         8  
  1         4  
  1         7  
  1         70  
  1         3  
  1         25  
  1         4  
  1         3  
  1         58  
  1         5  
  1         1  
  1         175  
  1         5  
  1         3  
  1         43  
  1         4  
  1         2  
  1         216  
  1         5  
  1         2  
  1         245  
  1         8  
  1         2  
  1         6  
  1         59  
  1         2  
  1         23  
  1         3  
  1         2  
  1         103  
  1         7  
  1         2  
  1         162  
  1         6  
  1         1  
  1         32  
  1         4  
  1         3  
  1         177  
  1         5  
  1         2  
  1         203  
  1         12  
  1         4  
  1         11  
  1         108  
  1         3  
  1         42  
  1         7  
  1         3  
  1         84  
  1         9  
  1         3  
  1         287  
  1         12  
  1         3  
  1         46  
  1         8  
  1         4  
  1         379  
  1         10  
  1         3  
  1         335  
  1         13  
  1         4  
  1         10  
  1         149  
  1         4  
  1         56  
  1         7  
  1         3  
  1         95  
  1         8  
  1         2  
  1         235  
  1         11  
  1         3  
  1         53  
  1         7  
  1         2  
  1         319  
  1         9  
  1         3  
  1         370  
  1         15  
  1         4  
  1         10  
  1         105  
  1         4  
  1         43  
  1         7  
  1         2  
  1         122  
  1         11  
  1         3  
  1         297  
  1         10  
  1         4  
  1         41  
  1         6  
  1         3  
  1         375  
  1         10  
  1         2  
  1         457  
  1         14  
  1         4  
  1         8  
  1         104  
  1         3  
  1         44  
  1         7  
  1         2  
  1         96  
  1         9  
  1         3  
  1         254  
  1         9  
  1         1  
  1         27  
  1         4  
  1         3  
  1         256  
  1         10  
  1         3  
  1         275  
  1         10  
  1         3  
  1         8  
  1         63  
  1         3  
  1         29  
  1         4  
  1         2  
  1         64  
  1         7  
  1         1  
  1         194  
  1         6  
  1         2  
  1         24  
  1         3  
  1         3  
  1         303  
  1         7  
  1         2  
  1         294  
  1         11  
  1         3  
  1         7  
  1         65  
  1         2  
  1         28  
  1         4  
  1         2  
  1         93  
  1         6  
  1         2  
  1         234  
  1         7  
  1         3  
  1         47  
  1         6  
  1         2  
  1         236  
  1         7  
  1         2  
  1         290  
  1         10  
  1         3  
  1         9  
  1         65  
  1         2  
  1         28  
  1         3  
  1         2  
  1         62  
  1         6  
  1         3  
  1         309  
  1         11  
  1         3  
  1         32  
  1         5  
  1         2  
  1         278  
  1         7  
  1         2  
  1         258  
  1         14  
  1         3  
  1         9  
  1         115  
  1         4  
  1         50  
  1         7  
  1         3  
  1         98  
  1         10  
  1         3  
  1         351  
  1         12  
  1         2  
  1         52  
  1         7  
  1         4  
  1         374  
  1         10  
  1         3  
  1         401  
  1         13  
  1         4  
  1         10  
  1         107  
  1         3  
  1         50  
  1         7  
  1         3  
  1         98  
  1         10  
  1         2  
  1         267  
  1         10  
  1         3  
  1         89  
  1         10  
  1         3  
  1         329  
  1         9  
  1         3  
  1         386  
  1         10  
  1         2  
  1         7  
  1         109  
  1         3  
  1         33  
  1         4  
  1         2  
  1         97  
  1         5  
  1         2  
  1         180  
  1         8  
  1         2  
  1         57  
  1         8  
  1         5  
  1         241  
  1         7  
  1         3  
  1         220  
  1         13  
  1         4  
  1         9  
  1         142  
  1         5  
  1         51  
  1         7  
  1         3  
  1         109  
  1         10  
  1         3  
  1         246  
  1         10  
  1         3  
  1         42  
  1         7  
  1         3  
  1         352  
  1         10  
  1         3  
  1         468  
  1         12  
  1         4  
  1         9  
  1         106  
  1         4  
  1         42  
  1         6  
  1         3  
  1         85  
  1         9  
  1         3  
  1         278  
  1         10  
  1         3  
  1         42  
  1         6  
  1         3  
  1         361  
  1         9  
  1         2  
  1         370  
  1         15  
  1         4  
  1         11  
  1         109  
  1         4  
  1         45  
  1         6  
  1         3  
  1         125  
  1         10  
  1         4  
  1         245  
  1         10  
  1         2  
  1         40  
  1         7  
  1         2  
  1         340  
  1         9  
  1         3  
  1         508  
  1         9  
  1         2  
  1         6  
  1         59  
  1         2  
  1         47  
  1         4  
  1         2  
  1         63  
  1         6  
  1         2  
  1         181  
  1         6  
  1         2  
  1         30  
  1         4  
  1         2  
  1         226  
  1         9  
  1         2  
  1         281  
  1         10  
  1         2  
  1         7  
  1         86  
  1         2  
  1         37  
  1         3  
  1         2  
  1         60  
  1         5  
  1         1  
  1         185  
  1         6  
  1         1  
  1         24  
  1         4  
  1         2  
  1         208  
  1         6  
  1         1  
  1         239  
  1         9  
  1         2  
  1         8  
  1         75  
  1         2  
  1         38  
  1         4  
  1         3  
  1         56  
  1         5  
  1         2  
  1         195  
  1         7  
  1         2  
  1         25  
  1         3  
  1         2  
  1         200  
  1         5  
  1         2  
  1         206  
  1         9  
  1         2  
  1         7  
  1         58  
  1         3  
  1         24  
  1         4  
  1         3  
  1         70  
  1         5  
  1         2  
  1         160  
  1         6  
  1         3  
  1         33  
  1         4  
  1         2  
  1         211  
  1         7  
  1         2  
  1         227  
  1         7  
  1         3  
  1         6  
  1         57  
  1         1  
  1         34  
  1         4  
  1         2  
  1         59  
  1         4  
  1         2  
  1         163  
  1         7  
  1         1  
  1         24  
  1         4  
  1         4  
  1         215  
  1         6  
  1         2  
  1         222  
  1         9  
  1         3  
  1         8  
  1         77  
  1         3  
  1         29  
  1         4  
  1         2  
  1         78  
  1         7  
  1         2  
  1         216  
  1         7  
  1         3  
  1         25  
  1         5  
  1         2  
  1         276  
  1         6  
  1         2  
  1         310  
873 50 50       433 die $@ if $@;
874              
875 50         157 push @{ $self->_temp_classes }, $class;
  50         508  
876             }
877              
878 115 100       9745 if ($class->has_relationship($remote_relname)) {
879 0     5   0 my $rel_cols = [ sort { $a cmp $b } apply { s/^foreign\.//i }
  5         40  
880 5         461 (keys %{ $class->relationship_info($remote_relname)->{cond} }) ];
  5         366  
881              
882 5 50       44 $relationship_exists = 1 if array_eq([ sort @$local_cols ], $rel_cols);
883             }
884             }
885              
886 188 100       9958 if (not $relationship_exists) {
887 183         1824 my $colnames = q{_} . $self->_normalize_name(join '_', @$local_cols);
888 183 100       1172 $local_relname .= $colnames if keys %$cond > 1;
889              
890 183         1439 $remote_relname = $self->_strip_id_postfix($self->_normalize_name($local_table . $colnames));
891              
892 183         715 $remote_relname_uninflected = $remote_relname;
893 183         1017 ($remote_relname) = $self->_inflect_plural($remote_relname);
894              
895             # if colnames were added and this is a might_have, re-inflect
896 183 100       1268 if ($remote_method eq 'might_have') {
897 2         14 ($remote_relname) = $self->_inflect_singular($remote_relname_uninflected);
898             }
899             }
900             }
901              
902 588         4956 return ($local_relname, $remote_relname, $remote_method);
903             }
904              
905             sub _rel_name_map {
906 1385     1385   5979 my ($self, $relname, $method, $local_class, $local_moniker, $local_cols,
907             $remote_class, $remote_moniker, $remote_cols, $extra) = @_;
908              
909             my $info = {
910 1385 100       2764 %{$extra || {}},
  1385         17490  
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 1385         8426 $self->_run_user_map($self->rel_name_map, $info);
922             }
923              
924             sub _run_user_map {
925 1387     1387   14922 my ($self, $map, $info) = @_;
926              
927 1387         3563 my $new_name = $info->{name};
928 1387         2915 my $mapped = 0;
929              
930 1387 100       6216 if ('HASH' eq ref($map)) {
    100          
931 18         54 my $name = $info->{name};
932 18         73 my $moniker = $info->{local_moniker};
933 18 100 66     223 if ($map->{$moniker} and 'HASH' eq ref($map->{$moniker})
    100 66        
      66        
934             and $map->{$moniker}{$name}
935             ) {
936 3         13 $new_name = $map->{$moniker}{$name};
937 3         8 $mapped = 1;
938             }
939             elsif ($map->{$name} and not 'HASH' eq ref($map->{$name})) {
940 3         38 $new_name = $map->{$name};
941 3         13 $mapped = 1;
942             }
943             }
944             elsif ('CODE' eq ref($map)) {
945             my $cb = sub {
946 3     3   3126 my ($cb_map) = @_;
947 3 100       42 croak "reentered rel_name_map must be a hashref"
948             unless 'HASH' eq ref($cb_map);
949 2         15 my ($cb_name, $cb_mapped) = $self->_run_user_map($cb_map, $info);
950 2   33     17 return $cb_mapped && $cb_name;
951 15         68 };
952 15         65 my $name = $map->($info, $cb);
953 14 100       8486 if ($name) {
954 6         16 $new_name = $name;
955 6         78 $mapped = 1;
956             }
957             }
958              
959 1386         8444 return ($new_name, $mapped);
960             }
961              
962             sub _cleanup {
963 146     146   524 my $self = shift;
964              
965 146         508 for my $class (@{ $self->_temp_classes }) {
  146         1158  
966 50         26850 Class::Unload->unload($class);
967             }
968              
969 146         21723 $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: