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   118 use strict;
  18         36  
  18         523  
4 18     18   112 use warnings;
  18         53  
  18         464  
5 18     18   118 use base 'Class::Accessor::Grouped';
  18         37  
  18         1815  
6 18     18   119 use mro 'c3';
  18         39  
  18         201  
7 18     18   575 use Carp::Clan qw/^DBIx::Class/;
  18         65  
  18         115  
8 18     18   2057 use Scalar::Util 'weaken';
  18         102  
  18         1143  
9 18     18   762 use DBIx::Class::Schema::Loader::Utils qw/split_name slurp_file array_eq apply uniq/;
  18         62  
  18         1346  
10 18     18   236 use Try::Tiny;
  18         71  
  18         1130  
11 18     18   116 use List::Util qw/all any first/;
  18         50  
  18         1294  
12 18     18   117 use namespace::clean;
  18         43  
  18         143  
13 18     18   16664 use Lingua::EN::Inflect::Phrase ();
  18         1618730  
  18         570  
14 18     18   203 use Lingua::EN::Tagger ();
  18         46  
  18         318  
15 18     18   9284 use String::ToIdentifier::EN ();
  18         627331  
  18         558  
16 18     18   7974 use String::ToIdentifier::EN::Unicode ();
  18         6136  
  18         409  
17 18     18   6297 use Class::Unload ();
  18         57733  
  18         389  
18 18     18   135 use Class::Inspector ();
  18         48  
  18         111046  
19              
20             our $VERSION = '0.07051';
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 469 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         538 (map { $_ => $loader->$_ } qw(
  791         18808  
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         4652 weaken $self->{loader}; #< don't leak
148              
149 113         436 bless $self => $class;
150              
151             # validate the relationship_attrs arg
152 113 100       1157 if( defined $self->relationship_attrs ) {
153 5 100 100     295 (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         5977 return $self;
158             }
159              
160              
161             # pluralize a relationship name
162             sub _inflect_plural {
163 856     856   2329 my ($self, $relname) = @_;
164              
165 856 50 33     4409 return '' if !defined $relname || $relname eq '';
166              
167 856         1771 my $result;
168 856         1684 my $mapped = 0;
169              
170 856 100       4270 if( ref $self->inflect_plural eq 'HASH' ) {
    50          
171 404 100       1564 if (exists $self->inflect_plural->{$relname}) {
172 6         42 $result = $self->inflect_plural->{$relname};
173 6         19 $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       6713 return ($result, $mapped) if $mapped;
185              
186 850         2899 return ($self->_to_PL($relname), 0);
187             }
188              
189             # Singularize a relationship name
190             sub _inflect_singular {
191 696     696   2023 my ($self, $relname) = @_;
192              
193 696 50 33     3879 return '' if !defined $relname || $relname eq '';
194              
195 696         1346 my $result;
196 696         1533 my $mapped = 0;
197              
198 696 100       3668 if( ref $self->inflect_singular eq 'HASH' ) {
    50          
199 297 100       1331 if (exists $self->inflect_singular->{$relname}) {
200 6         29 $result = $self->inflect_singular->{$relname};
201 6         15 $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       5806 return ($result, $mapped) if $mapped;
213              
214 690         2281 return ($self->_to_S($relname), 0);
215             }
216              
217             sub _to_PL {
218 785     785   1909 my ($self, $name) = @_;
219              
220 785         2967 $name =~ s/_/ /g;
221 785         3125 my $plural = Lingua::EN::Inflect::Phrase::to_PL($name);
222 785         2343563 $plural =~ s/ /_/g;
223              
224 785         3376 return $plural;
225             }
226              
227             sub _to_S {
228 624     624   1608 my ($self, $name) = @_;
229              
230 624         2177 $name =~ s/_/ /g;
231 624         2719 my $singular = Lingua::EN::Inflect::Phrase::to_S($name);
232 624         1615721 $singular =~ s/ /_/g;
233              
234 624         2648 return $singular;
235             }
236              
237             sub _default_relationship_attrs { +{
238 1154     1154   14962 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   9436 my ( $self, $reltype, $db_attrs, $params ) = @_;
262 1226         3358 my $r = $self->relationship_attrs;
263              
264             my %composite = (
265 1226 100       3368 %{ $self->_default_relationship_attrs->{$reltype} || {} },
266 1226 50       7731 %{ $db_attrs || {} },
267             (
268             ref $r eq 'HASH' ? (
269 546 100       2734 %{ $r->{all} || {} },
270 1226 100       2264 %{ $r->{$reltype} || {} },
  546 100       3282  
271             )
272             :
273             ()
274             ),
275             );
276              
277 1226 100       5477 if (ref $r eq 'CODE') {
278 2         8 $params->{attrs} = \%composite;
279              
280 2 50       6 my %ret = %{ $r->(%$params) || {} };
  2         14  
281              
282 2 50       2903 %composite = %ret if %ret;
283             }
284              
285 1226 100       10688 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   1926 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     2137 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   4177 my $nullable = first { $self->schema->source($local_moniker)->column_info($_)->{is_nullable} } @$local_cols;
  601         5578  
305 552 100 66     37205 $attrs->{join_type} = 'LEFT' if $nullable && !defined $attrs->{join_type};
306              
307 552         4742 return $attrs;
308             }
309              
310             sub _sanitize_name {
311 2003     2003   4205 my ($self, $name) = @_;
312              
313 2003         8721 $name = $self->loader->_to_identifier('relationships', $name, '_');
314              
315 2003         6748 $name =~ s/\W+/_/g; # if naming >= 8 to_identifier takes care of it
316              
317 2003         4780 return $name;
318             }
319              
320             sub _normalize_name {
321 1971     1971   4725 my ($self, $name) = @_;
322              
323 1971         5839 $name = $self->_sanitize_name($name);
324              
325 1971         6682 my @words = split_name $name, $self->loader->_get_naming_v('relationships');
326              
327 1971         15235 return join '_', map lc, @words;
328             }
329              
330             sub _local_relname {
331 553     553   1699 my ($self, $remote_table, $cond) = @_;
332              
333 553         1248 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       1078 if(scalar keys %{$cond} == 1) {
  553         2417  
337 504         1106 my ($col) = values %{$cond};
  504         1694  
338 504         2015 $col = $self->_strip_id_postfix($self->_normalize_name($col));
339 504         2452 ($local_relname) = $self->_inflect_singular($col);
340             }
341             else {
342 49         202 ($local_relname) = $self->_inflect_singular($self->_normalize_name($remote_table));
343             }
344              
345 553         8755 return $local_relname;
346             }
347              
348             sub _resolve_relname_collision {
349 1300     1300   3552 my ($self, $moniker, $cols, $relname) = @_;
350              
351 1300 100       3293 return $relname if $relname eq 'id'; # this shouldn't happen, but just in case
352              
353 1286         5597 my $table = $self->loader->moniker_to_table->{$moniker};
354              
355 1286 100       5080 if ($self->loader->_is_result_class_method($relname, $table)) {
356 14 100       68 if (my $map = $self->rel_collision_map) {
357 12         282 for my $re (keys %$map) {
358 12 100       117 if (my @matches = $relname =~ /$re/) {
359 6         52 return sprintf $map->{$re}, @matches;
360             }
361             }
362             }
363              
364 8         30 my $new_relname = $relname;
365 8         62 while ($self->loader->_is_result_class_method($new_relname, $table)) {
366 8         50 $new_relname .= '_rel'
367             }
368              
369 8         45 warn <<"EOF";
370 8         128 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         48 return $new_relname;
375             }
376              
377 1272         3626 return $relname;
378             }
379              
380             sub generate_code {
381 116     116 1 574 my ($self, $tables) = @_;
382              
383             # make a copy to destroy
384 116         656 my @tables = @$tables;
385              
386 116         478 my $all_code = {};
387              
388 116 100       452 while (my ($local_moniker, $rels, $uniqs) = @{ shift @tables || [] }) {
  885         6232  
389 770         4511 my $local_class = $self->schema->class($local_moniker);
390              
391 770         71442 my %counters;
392 770         2565 foreach my $rel (@$rels) {
393 611 50       2833 next if !$rel->{remote_source};
394 611         2177 $counters{$rel->{remote_source}}++;
395             }
396              
397 770         2212 foreach my $rel (@$rels) {
398             my $remote_moniker = $rel->{remote_source}
399 611 50       2396 or next;
400              
401 611         2642 my $remote_class = $self->schema->class($remote_moniker);
402 611         49822 my $remote_obj = $self->schema->source($remote_moniker);
403 611   100     25444 my $remote_cols = $rel->{remote_columns} || [ $remote_obj->primary_columns ];
404              
405 611         1986 my $local_cols = $rel->{local_columns};
406              
407 611 50       2412 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         1296 my %cond;
413 611         2959 @cond{@$remote_cols} = @$local_cols;
414              
415 611         2969 my ( $local_relname, $remote_relname, $remote_method ) =
416             $self->_relnames_and_method( $local_moniker, $rel, \%cond, $uniqs, \%counters );
417 611         1708 my $local_method = 'belongs_to';
418              
419 611         2719 ($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         2046 ($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         2520 $local_relname = $self->_resolve_relname_collision(
431             $local_moniker, $local_cols, $local_relname,
432             );
433 610         1794 $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         3341 remote_cols => $remote_cols,
446             };
447              
448 610         4041 push @{$all_code->{$local_class}}, {
449             method => $local_method,
450             args => [
451             $local_relname,
452             $remote_class,
453             \%cond,
454 610         61480 $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         2760 my %rev_cond = reverse %cond;
464 610         2480 for (keys %rev_cond) {
465 659         3086 $rev_cond{"foreign.$_"} = "self.".$rev_cond{$_};
466 659         2017 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         2931 remote_cols => $local_cols,
478             };
479              
480 610         54461 push @{$all_code->{$remote_class}}, {
  610         3660  
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         1292 $self->_generate_m2ms($all_code);
498              
499             # disambiguate rels with the same name
500 115         727 foreach my $class (keys %$all_code) {
501 667         2130 my $dups = $self->_duplicates($all_code->{$class});
502              
503 667 100       1906 $self->_disambiguate($all_code, $class, $dups) if $dups;
504             }
505              
506 115         1000 $self->_cleanup;
507              
508 115         606 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   579 my ($self, $all_code) = @_;
514              
515             LINK_CLASS:
516 115         1371 foreach my $link_class (sort keys %$all_code) {
517 667         1727 my @rels = grep $_->{method} eq 'belongs_to', @{$all_code->{$link_class}};
  667         3384  
518 667 100       2064 next unless @rels == 2;
519              
520 116         302 my @class;
521 116         303 foreach my $this (0, 1) {
522 225 100       585 my $that = $this ? 0 : 1;
523 225         407 my %class;
524 225         496 $class[$this] = \%class;
525 225         867 $class{local_moniker} = $rels[$this]{extra}{remote_moniker};
526 225         677 $class{remote_moniker} = $rels[$that]{extra}{remote_moniker};
527              
528 225         598 $class{class} = $rels[$this]{args}[1];
529              
530 225     267   849 my %link_cols = map { $_ => 1 } apply { s/^self\.//i } values %{ $rels[$this]{args}[2] };
  267         934  
  267         823  
  225         1141  
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   3301 all { $link_cols{$_} } apply { s/^foreign\.//i } keys %{$_->{args}[2]}
  343         1206  
  351         1477  
  295         1384  
538 225         1232 } @{ $all_code->{$class{class}} };
  225         964  
539              
540 225 100       1488 next LINK_CLASS unless $class{link_table_rel};
541              
542 218         670 $class{link_table_rel_name} = $class{link_table_rel}{args}[0];
543              
544 218         811 $class{link_rel} = $rels[$that]{args}[0];
545              
546 260     260   1105 $class{from_cols} = [ apply { s/^self\.//i } values %{
547 218         1093 $class{link_table_rel}->{args}[2]
  218         873  
548             } ];
549              
550 218     260   881 $class{to_cols} = [ apply { s/^foreign\.//i } keys %{ $rels[$that]{args}[2] } ];
  260         629  
  218         950  
551              
552 218     260   886 $class{from_link_cols} = [ apply { s/^self\.//i } values %{ $rels[$this]{args}[2] } ];
  260         753  
  218         800  
553             }
554              
555 109         517 my $link_moniker = $rels[0]{extra}{local_moniker};
556              
557             my @link_table_cols =
558 109         218 @{[ $self->schema->source($link_moniker)->columns ]};
  109         608  
559              
560             my @link_table_primary_cols =
561 109         6988 @{[ $self->schema->source($link_moniker)->primary_columns ]};
  109         434  
562              
563             next unless array_eq(
564 109 100 33     5728 [ sort +uniq @{$class[0]{from_link_cols}}, @{$class[1]{from_link_cols}} ],
  109   66     341  
  109         454  
565             [ sort @link_table_primary_cols ],
566             ) && ($self->allow_extra_m2m_cols || @link_table_cols == @link_table_primary_cols);
567              
568 32         766 foreach my $this (0, 1) {
569 64 100       179 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         274 @{$class[$this]}{qw(class local_moniker from_cols)},
574             $class[$that]{class},
575 64         443 @{$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         240 );
582              
583             $class[$this]{m2m_relname} = $self->_resolve_relname_collision(
584 64         235 @{$class[$this]}{qw(local_moniker from_cols m2m_relname)},
  64         226  
585             );
586             }
587              
588 32         126 for my $this (0, 1) {
589 64 100       168 my $that = $this ? 0 : 1;
590              
591 64         186 push @{$all_code->{$class[$this]{class}}}, {
592             method => 'many_to_many',
593             args => [
594 64         376 @{$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     121 };
613             }
614             }
615             }
616              
617             sub _duplicates {
618 683     683   1467 my ($self, $rels) = @_;
619              
620 683         3648 my @rels = map [ $_->{args}[0] => $_ ], @$rels;
621 683         1254 my %rel_names;
622 683         3536 $rel_names{$_}++ foreach map $_->[0], @rels;
623              
624 683         2253 my @dups = grep $rel_names{$_} > 1, keys %rel_names;
625              
626 683         1373 my %dups;
627              
628 683         1523 foreach my $dup (@dups) {
629 18         53 $dups{$dup} = [ map $_->[1], grep { $_->[0] eq $dup } @rels ];
  65         184  
630             }
631              
632 683 100       2716 return if not %dups;
633              
634 18         76 return \%dups;
635             }
636              
637             sub _tagger {
638 14     14   36 my $self = shift;
639              
640 14 100       83 $self->__tagger(Lingua::EN::Tagger->new) unless $self->__tagger;
641              
642 14         389615 return $self->__tagger;
643             }
644              
645             sub _adjectives {
646 14     14   51 my ($self, @cols) = @_;
647              
648 14         33 my @adjectives;
649              
650 14         44 foreach my $col (@cols) {
651 14         53 my @words = split_name $col;
652              
653 14         341 my $tagged = $self->_tagger->get_readable(join ' ', @words);
654              
655 14         20343 push @adjectives, $tagged =~ m{\G(\w+)/JJ\s+}g;
656             }
657              
658 14         54 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   59 my ($self, $all_code, $in_class, $dups) = @_;
673              
674 16         72 DUP: foreach my $dup (keys %$dups) {
675 16         47 my @rels = @{ $dups->{$dup} };
  16         51  
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         194 @rels;
681              
682             # databases are different, prepend database
683 16 50 0     267 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         66 foreach my $rel (@rels) {
713 32 100       184 next if $rel->{method} =~ /^(?:belongs_to|many_to_many)\z/;
714              
715 14     14   103 my @to_cols = apply { s/^foreign\.//i }
716 14         81 keys %{ $rel->{args}[2] };
  14         88  
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         60 my $to_class = $rel->{args}[1];
724              
725 14 100 66     82 if ((not @adjectives)
726             && (grep { $_->{method} eq 'might_have'
727 21 100       123 && $_->{args}[1] eq $to_class } @{ $all_code->{$in_class} }) == 1) {
  7         35  
728              
729 7         30 @adjectives = 'active';
730             }
731              
732 14 50       61 if (@adjectives) {
733 14         66 my $rel_name = join '_', sort(@adjectives), $rel->{args}[0];
734              
735 14 50       91 ($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         92 = @{ $rel->{extra} }
742 14         52 {qw/local_class local_moniker remote_moniker/};
743              
744 14     14   83 my @from_cols = apply { s/^self\.//i }
745 14         95 values %{ $rel->{args}[2] };
  14         96  
746              
747 14         131 ($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         86 $rel_name = $self->_resolve_relname_collision($local_moniker, \@from_cols, $rel_name);
750              
751 14         101 $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       80 if ($dups = $self->_duplicates($all_code->{$in_class})) {
759 2         8 foreach my $dup (keys %$dups) {
760             # sort by method
761 2         11 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         5 ], @{ $dups->{$dup} };
  2         25  
769              
770 2         6 my $rel_num = 2;
771              
772 2         7 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         5 my $inflect_method = "_$inflect_type";
779              
780 2         8 my $relname_new_uninflected = $rel->{args}[0] . "_$rel_num";
781              
782 2         5 $rel_num++;
783              
784             my ($local_class, $local_moniker, $remote_moniker)
785 2         13 = @{ $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       6 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         10  
793 2         9 ->{args}[2]
794             };
795 2     2   6 @to_cols = apply { s/^foreign\.//i } keys %{
796 2     3   19 (first { $_->{args}[0] eq $rel->{args}[2] }
  3         13  
797 2         8 @{ $all_code->{ $rel->{extra}{link_class} } })
798 2         8 ->{args}[2]
799             };
800 2         19 $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         194 my ($relname_new, $inflect_mapped) =
809             $self->$inflect_method($relname_new_uninflected);
810              
811 2         7 my $rel_name_mapped;
812              
813 2         10 ($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     17 my $mapped = $inflect_mapped || $rel_name_mapped;
816              
817 2 50       8 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         7 $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   1975 my ( $self, $local_moniker, $rel, $cond, $uniqs, $counters ) = @_;
834              
835 546         1453 my $remote_moniker = $rel->{remote_source};
836 546         2087 my $remote_obj = $self->schema->source( $remote_moniker );
837 546         22744 my $remote_class = $self->schema->class( $remote_moniker );
838 546         42246 my $local_relname = $self->_local_relname( $rel->{remote_table}, $cond);
839              
840 546         1653 my $local_cols = $rel->{local_columns};
841 546         1533 my $local_table = $rel->{local_table};
842 546         3265 my $local_class = $self->schema->class($local_moniker);
843 546         52257 my $local_source = $self->schema->source($local_moniker);
844              
845 546         23045 my $remote_relname_uninflected = $self->_normalize_name($local_table);
846 546         1882 my ($remote_relname) = $self->_inflect_plural($self->_normalize_name($local_table));
847              
848 546         1474 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     3249 if (array_eq([ $local_source->primary_columns ], $local_cols) ||
852 181     181   814 first { array_eq($_->[1], $local_cols) } @$uniqs) {
853 68         241 $remote_method = 'might_have';
854 68         344 ($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       4778 if ($counters->{$remote_moniker} > 1) {
860 184         555 my $relationship_exists = 0;
861              
862 184 100       1223 if (-f (my $existing_remote_file = $self->loader->get_dump_filename($remote_class))) {
863 111         639 my $class = "${remote_class}Temporary";
864              
865 111 100       899 if (not Class::Inspector->loaded($class)) {
866 48         5264 my $code = slurp_file $existing_remote_file;
867              
868 48         21154 $code =~ s/(?<=package $remote_class)/Temporary/g;
869              
870 48         1090 $code =~ s/__PACKAGE__->meta->make_immutable[^;]*;//g;
871              
872 48     2   5832 eval $code;
  2     2   19  
  2     2   5  
  2     2   17  
  2     2   149  
  2     2   5  
  2     2   84  
  2     2   12  
  2     2   5  
  2     2   86  
  2     2   12  
  2     2   5  
  2     2   384  
  1     2   7  
  1     2   5  
  1     2   44  
  1     1   6  
  1     1   3  
  1     1   205  
  1     1   7  
  1     1   2  
  1     1   221  
  2     1   30  
  2     1   4  
  2     1   31  
  2     1   168  
  2     1   8  
  2     1   55  
  2     1   11  
  2     1   5  
  2     1   155  
  2     1   19  
  2     1   5  
  2     1   347  
  1     1   8  
  1     1   3  
  1     1   28  
  1     1   6  
  1     1   3  
  1     1   199  
  1     1   8  
  1     1   2  
  1     1   316  
  2     1   21  
  2     1   5  
  2     1   20  
  2     1   166  
  2     1   5  
  2     1   55  
  2     1   12  
  2     1   7  
  2     1   107  
  2     1   13  
  2     1   7  
  2     1   350  
  1     1   7  
  1     1   3  
  1     1   28  
  1     1   6  
  1     1   2  
  1     1   199  
  1     1   9  
  1     1   2  
  1     1   281  
  2     1   20  
  2     1   6  
  2     1   23  
  2     1   226  
  2     1   6  
  2     1   66  
  2     1   12  
  2     1   7  
  2     1   439  
  2     1   16  
  2     1   5  
  2     1   477  
  1     1   7  
  1     1   3  
  1     1   28  
  1     1   6  
  1         2  
  1         189  
  1         8  
  1         4  
  1         234  
  2         16  
  2         6  
  2         16  
  2         146  
  2         5  
  2         53  
  2         10  
  2         4  
  2         77  
  2         13  
  2         4  
  2         410  
  1         7  
  1         3  
  1         26  
  1         5  
  1         2  
  1         164  
  1         7  
  1         3  
  1         199  
  2         23  
  2         6  
  2         18  
  2         154  
  2         9  
  2         61  
  2         12  
  2         4  
  2         98  
  2         12  
  2         7  
  2         468  
  1         8  
  1         2  
  1         33  
  1         7  
  1         3  
  1         217  
  1         11  
  1         3  
  1         201  
  2         23  
  2         8  
  2         19  
  2         157  
  2         6  
  2         73  
  2         12  
  2         5  
  2         106  
  2         14  
  2         5  
  2         386  
  1         7  
  1         2  
  1         39  
  1         6  
  1         3  
  1         174  
  1         7  
  1         3  
  1         210  
  2         18  
  2         5  
  2         16  
  2         151  
  2         8  
  2         56  
  2         12  
  2         6  
  2         84  
  2         15  
  2         4  
  2         371  
  1         10  
  1         3  
  1         27  
  1         5  
  1         3  
  1         169  
  1         8  
  1         3  
  1         272  
  1         19  
  1         3  
  1         10  
  1         80  
  1         4  
  1         27  
  1         6  
  1         6  
  1         47  
  1         6  
  1         4  
  1         210  
  1         7  
  1         3  
  1         56  
  1         8  
  1         3  
  1         245  
  1         8  
  1         5  
  1         309  
  1         22  
  1         4  
  1         14  
  1         80  
  1         5  
  1         32  
  1         6  
  1         6  
  1         52  
  1         7  
  1         8  
  1         216  
  1         13  
  1         2  
  1         34  
  1         6  
  1         3  
  1         210  
  1         8  
  1         3  
  1         396  
  1         14  
  1         3  
  1         8  
  1         95  
  1         4  
  1         29  
  1         8  
  1         5  
  1         43  
  1         7  
  1         4  
  1         192  
  1         9  
  1         7  
  1         28  
  1         6  
  1         3  
  1         219  
  1         9  
  1         5  
  1         328  
  1         9  
  1         3  
  1         9  
  1         72  
  1         3  
  1         27  
  1         5  
  1         3  
  1         36  
  1         6  
  1         2  
  1         190  
  1         9  
  1         2  
  1         29  
  1         5  
  1         3  
  1         219  
  1         8  
  1         3  
  1         274  
  1         11  
  1         3  
  1         10  
  1         77  
  1         4  
  1         28  
  1         5  
  1         3  
  1         44  
  1         6  
  1         3  
  1         222  
  1         9  
  1         3  
  1         29  
  1         6  
  1         3  
  1         241  
  1         7  
  1         3  
  1         257  
  1         10  
  1         2  
  1         11  
  1         76  
  1         3  
  1         27  
  1         6  
  1         4  
  1         44  
  1         6  
  1         2  
  1         199  
  1         8  
  1         2  
  1         58  
  1         7  
  1         3  
  1         213  
  1         7  
  1         2  
  1         233  
  1         11  
  1         4  
  1         8  
  1         76  
  1         4  
  1         27  
  1         6  
  1         2  
  1         48  
  1         10  
  1         4  
  1         170  
  1         8  
  1         3  
  1         26  
  1         7  
  1         3  
  1         214  
  1         8  
  1         2  
  1         252  
  1         9  
  1         3  
  1         6  
  1         73  
  1         3  
  1         26  
  1         5  
  1         4  
  1         36  
  1         6  
  1         3  
  1         161  
  1         8  
  1         2  
  1         24  
  1         5  
  1         4  
  1         225  
  1         9  
  1         3  
  1         309  
  1         11  
  1         2  
  1         11  
  1         81  
  1         3  
  1         29  
  1         1864  
  1         4  
  1         60  
  1         7  
  1         3  
  1         218  
  1         10  
  1         5  
  1         32  
  1         9  
  1         4  
  1         250  
  1         8  
  1         4  
  1         280  
  1         1322  
  1         7  
  1         12  
  1         99  
  1         2  
  1         28  
  1         5  
  1         2  
  1         34  
  1         5  
  1         7  
  1         156  
  1         9  
  1         5  
  1         26  
  1         8  
  1         3  
  1         218  
  1         8  
  1         4  
  1         359  
  1         9  
  1         3  
  1         10  
  1         83  
  1         5  
  1         31  
  1         7  
  1         4  
  1         42  
  1         10  
  1         2  
  1         191  
  1         9  
  1         3  
  1         29  
  1         6  
  1         4  
  1         227  
  1         9  
  1         3  
  1         283  
  1         12  
  1         4  
  1         8  
  1         82  
  1         3  
  1         28  
  1         5  
  1         3  
  1         46  
  1         7  
  1         4  
  1         188  
  1         12  
  1         3  
  1         31  
  1         5  
  1         3  
  1         228  
  1         8  
  1         4  
  1         263  
  1         8  
  1         4  
  1         10  
  1         75  
  1         3  
  1         25  
  1         6  
  1         2  
  1         34  
  1         7  
  1         2  
  1         152  
  1         8  
  1         2  
  1         43  
  1         7  
  1         2  
  1         207  
  1         8  
  1         3  
  1         289  
  1         8  
  1         2  
  1         8  
  1         70  
  1         2  
  1         25  
  1         5  
  1         3  
  1         35  
  1         6  
  1         3  
  1         155  
  1         8  
  1         3  
  1         27  
  1         5  
  1         3  
  1         207  
  1         8  
  1         2  
  1         222  
  1         8  
  1         3  
  1         7  
  1         67  
  1         3  
  1         23  
  1         6  
  1         2  
  1         45  
  1         7  
  1         2  
  1         126  
  1         8  
  1         3  
  1         24  
  1         5  
  1         3  
  1         194  
  1         8  
  1         5  
  1         229  
  1         10  
  1         3  
  1         8  
  1         74  
  1         3  
  1         26  
  1         6  
  1         3  
  1         56  
  1         7  
  1         3  
  1         195  
  1         8  
  1         7  
  1         35  
  1         5  
  1         4  
  1         271  
  1         9  
  1         4  
  1         320  
  1         10  
  1         3  
  1         10  
  1         78  
  1         3  
  1         29  
  1         6  
  1         3  
  1         42  
  1         6  
  1         3  
  1         209  
  1         8  
  1         3  
  1         61  
  1         9  
  1         2  
  1         243  
  1         9  
  1         2  
  1         300  
  1         12  
  1         3  
  1         11  
  1         140  
  1         3  
  1         31  
  1         6  
  1         2  
  1         57  
  1         7  
  1         3  
  1         204  
  1         8  
  1         3  
  1         29  
  1         7  
  1         3  
  1         226  
  1         8  
  1         2  
  1         357  
  1         10  
  1         3  
  1         10  
  1         98  
  1         7  
  1         29  
  1         6  
  1         3  
  1         60  
  1         21  
  1         2  
  1         248  
  1         9  
  1         3  
  1         35  
  1         6  
  1         2  
  1         280  
  1         8  
  1         13  
  1         327  
  1         24  
  1         2  
  1         47  
  1         103  
  1         3  
  1         29  
  1         7  
  1         4  
  1         46  
  1         6  
  1         5  
  1         227  
  1         15  
  1         2  
  1         60  
  1         11  
  1         7  
  1         244  
  1         10  
  1         3  
  1         386  
  1         8  
  1         4  
  1         6  
  1         71  
  1         3  
  1         25  
  1         7  
  1         3  
  1         63  
  1         8  
  1         4  
  1         150  
  1         8  
  1         2  
  1         26  
  1         5  
  1         3  
  1         207  
  1         8  
  1         3  
  1         252  
  1         10  
  1         3  
  1         10  
  1         90  
  1         2  
  1         32  
  1         8  
  1         4  
  1         47  
  1         7  
  1         3  
  1         217  
  1         8  
  1         2  
  1         45  
  1         7  
  1         3  
  1         245  
  1         8  
  1         3  
  1         273  
  1         9  
  1         3  
  1         11  
  1         80  
  1         8  
  1         27  
  1         6  
  1         4  
  1         52  
  1         7  
  1         4  
  1         266  
  1         8  
  1         3  
  1         57  
  1         7  
  1         4  
  1         615  
  1         8  
  1         2  
  1         274  
  1         11  
  1         4  
  1         10  
  1         90  
  1         3  
  1         26  
  1         5  
  1         3  
  1         59  
  1         7  
  1         2  
  1         312  
  1         9  
  1         6  
  1         45  
  1         7  
  1         3  
  1         302  
  1         8  
  1         3  
  1         341  
  1         10  
  1         3  
  1         10  
  1         81  
  1         2  
  1         30  
  1         6  
  1         2  
  1         42  
  1         7  
  1         2  
  1         196  
  1         10  
  1         6  
  1         30  
  1         8  
  1         3  
  1         230  
  1         7  
  1         4  
  1         289  
  1         10  
  1         3  
  1         10  
  1         81  
  1         3  
  1         27  
  1         6  
  1         2  
  1         58  
  1         6  
  1         4  
  1         193  
  1         8  
  1         2  
  1         27  
  1         6  
  1         2  
  1         222  
  1         8  
  1         2  
  1         362  
  1         13  
  1         4  
  1         10  
  1         85  
  1         4  
  1         28  
  1         6  
  1         3  
  1         48  
  1         10  
  1         6  
  1         206  
  1         9  
  1         3  
  1         29  
  1         9  
  1         8  
  1         245  
  1         7  
  1         3  
  1         310  
  1         8  
  1         3  
  1         8  
  1         68  
  1         4  
  1         23  
  1         7  
  1         2  
  1         29  
  1         6  
  1         2  
  1         120  
  1         7  
  1         3  
  1         38  
  1         6  
  1         2  
  1         273  
  1         8  
  1         3  
  1         275  
  1         12  
  1         7  
  1         7  
  1         80  
  1         5  
  1         24  
  1         5  
  1         3  
  1         33  
  1         6  
  1         5  
  1         145  
  1         8  
  1         4  
  1         40  
  1         9  
  1         2  
  1         192  
  1         8  
  1         3  
  1         259  
  1         14  
  1         4  
  1         8  
  1         69  
  1         3  
  1         24  
  1         6  
  1         2  
  1         30  
  1         7  
  1         6  
  1         513  
  1         8  
  1         3  
  1         27  
  1         7  
  1         3  
  1         206  
  1         8  
  1         3  
  1         222  
  1         8  
  1         2  
  1         9  
  1         67  
  1         3  
  1         22  
  1         7  
  1         3  
  1         31  
  1         6  
  1         5  
  1         150  
  1         10  
  1         3  
  1         27  
  1         5  
  1         3  
  1         255  
  1         11  
  1         3  
  1         242  
  1         8  
  1         3  
  1         8  
  1         71  
  1         2  
  1         23  
  1         6  
  1         2  
  1         44  
  1         7  
  1         3  
  1         138  
  1         7  
  1         2  
  1         25  
  1         6  
  1         2  
  1         202  
  1         8  
  1         3  
  1         284  
873 48 50       333 die $@ if $@;
874              
875 48         159 push @{ $self->_temp_classes }, $class;
  48         363  
876             }
877              
878 111 100       6620 if ($class->has_relationship($remote_relname)) {
879 0     5   0 my $rel_cols = [ sort { $a cmp $b } apply { s/^foreign\.//i }
  5         32  
880 5         308 (keys %{ $class->relationship_info($remote_relname)->{cond} }) ];
  5         243  
881              
882 5 50       44 $relationship_exists = 1 if array_eq([ sort @$local_cols ], $rel_cols);
883             }
884             }
885              
886 184 100       6792 if (not $relationship_exists) {
887 179         1193 my $colnames = q{_} . $self->_normalize_name(join '_', @$local_cols);
888 179 100       888 $local_relname .= $colnames if keys %$cond > 1;
889              
890 179         858 $remote_relname = $self->_strip_id_postfix($self->_normalize_name($local_table . $colnames));
891              
892 179         910 $remote_relname_uninflected = $remote_relname;
893 179         816 ($remote_relname) = $self->_inflect_plural($remote_relname);
894              
895             # if colnames were added and this is a might_have, re-inflect
896 179 100       828 if ($remote_method eq 'might_have') {
897 2         11 ($remote_relname) = $self->_inflect_singular($remote_relname_uninflected);
898             }
899             }
900             }
901              
902 546         3065 return ($local_relname, $remote_relname, $remote_method);
903             }
904              
905             sub _rel_name_map {
906 1301     1301   4303 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       2456 %{$extra || {}},
  1301         13411  
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         6296 $self->_run_user_map($self->rel_name_map, $info);
922             }
923              
924             sub _run_user_map {
925 1303     1303   7341 my ($self, $map, $info) = @_;
926              
927 1303         2922 my $new_name = $info->{name};
928 1303         2437 my $mapped = 0;
929              
930 1303 100       4691 if ('HASH' eq ref($map)) {
    100          
931 18         37 my $name = $info->{name};
932 18         37 my $moniker = $info->{local_moniker};
933 18 100 66     150 if ($map->{$moniker} and 'HASH' eq ref($map->{$moniker})
    100 66        
      66        
934             and $map->{$moniker}{$name}
935             ) {
936 3         10 $new_name = $map->{$moniker}{$name};
937 3         8 $mapped = 1;
938             }
939             elsif ($map->{$name} and not 'HASH' eq ref($map->{$name})) {
940 3         9 $new_name = $map->{$name};
941 3         8 $mapped = 1;
942             }
943             }
944             elsif ('CODE' eq ref($map)) {
945             my $cb = sub {
946 3     3   2125 my ($cb_map) = @_;
947 3 100       19 croak "reentered rel_name_map must be a hashref"
948             unless 'HASH' eq ref($cb_map);
949 2         12 my ($cb_name, $cb_mapped) = $self->_run_user_map($cb_map, $info);
950 2   33     12 return $cb_mapped && $cb_name;
951 15         72 };
952 15         50 my $name = $map->($info, $cb);
953 14 100       8164 if ($name) {
954 6         15 $new_name = $name;
955 6         35 $mapped = 1;
956             }
957             }
958              
959 1302         6076 return ($new_name, $mapped);
960             }
961              
962             sub _cleanup {
963 115     115   334 my $self = shift;
964              
965 115         365 for my $class (@{ $self->_temp_classes }) {
  115         946  
966 48         22784 Class::Unload->unload($class);
967             }
968              
969 115         11096 $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: