line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Fey::Meta::Role::Relationship::ViaFK; |
2
|
|
|
|
|
|
|
|
3
|
10
|
|
|
10
|
|
7569
|
use strict; |
|
10
|
|
|
|
|
18
|
|
|
10
|
|
|
|
|
368
|
|
4
|
10
|
|
|
10
|
|
55
|
use warnings; |
|
10
|
|
|
|
|
19
|
|
|
10
|
|
|
|
|
357
|
|
5
|
10
|
|
|
10
|
|
54
|
use namespace::autoclean; |
|
10
|
|
|
|
|
19
|
|
|
10
|
|
|
|
|
107
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = '0.47'; |
8
|
|
|
|
|
|
|
|
9
|
10
|
|
|
10
|
|
1029
|
use Fey::Exceptions qw( param_error ); |
|
10
|
|
|
|
|
19
|
|
|
10
|
|
|
|
|
710
|
|
10
|
10
|
|
|
10
|
|
57
|
use Fey::ORM::Types qw( Bool ); |
|
10
|
|
|
|
|
28
|
|
|
10
|
|
|
|
|
107
|
|
11
|
|
|
|
|
|
|
|
12
|
10
|
|
|
10
|
|
51626
|
use Moose::Role; |
|
10
|
|
|
|
|
22
|
|
|
10
|
|
|
|
|
104
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
has fk => ( |
15
|
|
|
|
|
|
|
is => 'ro', |
16
|
|
|
|
|
|
|
isa => 'Fey::FK', |
17
|
|
|
|
|
|
|
lazy => 1, |
18
|
|
|
|
|
|
|
builder => '_build_fk', |
19
|
|
|
|
|
|
|
predicate => '_has_fk', |
20
|
|
|
|
|
|
|
writer => '_set_fk', |
21
|
|
|
|
|
|
|
); |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
has _is_has_many => ( |
24
|
|
|
|
|
|
|
is => 'ro', |
25
|
|
|
|
|
|
|
isa => Bool, |
26
|
|
|
|
|
|
|
lazy => 1, |
27
|
|
|
|
|
|
|
default => sub { ( ref $_[0] ) =~ /HasMany/ ? 1 : 0 }, |
28
|
|
|
|
|
|
|
); |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
16
|
0
|
|
sub BUILD { } |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
after BUILD => sub { |
33
|
|
|
|
|
|
|
my $self = shift; |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
return unless $self->_has_fk(); |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
$self->_set_fk( $self->_invert_fk_if_necessary( $self->fk() ) ); |
38
|
|
|
|
|
|
|
}; |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub _build_fk { |
41
|
14
|
|
|
14
|
|
30
|
my $self = shift; |
42
|
|
|
|
|
|
|
|
43
|
14
|
|
|
|
|
497
|
$self->_find_one_fk_between_tables( |
44
|
|
|
|
|
|
|
$self->table(), |
45
|
|
|
|
|
|
|
$self->foreign_table(), |
46
|
|
|
|
|
|
|
); |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
sub _find_one_fk_between_tables { |
50
|
14
|
|
|
14
|
|
34
|
my $self = shift; |
51
|
14
|
|
|
|
|
25
|
my $source_table = shift; |
52
|
14
|
|
|
|
|
21
|
my $target_table = shift; |
53
|
|
|
|
|
|
|
|
54
|
14
|
|
|
|
|
406
|
my @fk = $source_table->schema() |
55
|
|
|
|
|
|
|
->foreign_keys_between_tables( $source_table, $target_table ); |
56
|
|
|
|
|
|
|
|
57
|
14
|
100
|
|
|
|
70348
|
my $desc = $self->_is_has_many() ? 'has_many' : 'has_one'; |
58
|
|
|
|
|
|
|
|
59
|
14
|
100
|
|
|
|
72
|
if ( @fk == 0 ) { |
|
|
100
|
|
|
|
|
|
60
|
2
|
|
|
|
|
60
|
param_error |
61
|
|
|
|
|
|
|
'There are no foreign keys between the table for this class, ' |
62
|
|
|
|
|
|
|
. $source_table->name() |
63
|
|
|
|
|
|
|
. " and the table you passed to $desc(), " |
64
|
|
|
|
|
|
|
. $target_table->name() . '.'; |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
elsif ( @fk > 1 ) { |
67
|
2
|
|
|
|
|
73
|
param_error |
68
|
|
|
|
|
|
|
'There is more than one foreign key between the table for this class, ' |
69
|
|
|
|
|
|
|
. $source_table->name() |
70
|
|
|
|
|
|
|
. " and the table you passed to $desc(), " |
71
|
|
|
|
|
|
|
. $target_table->name() |
72
|
|
|
|
|
|
|
. '. You must specify one explicitly.'; |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
10
|
|
|
|
|
49
|
return $self->_invert_fk_if_necessary( $fk[0] ); |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# We may need to invert the meaning of source & target since source & |
79
|
|
|
|
|
|
|
# target for an FK object are sort of arbitrary. The source should be |
80
|
|
|
|
|
|
|
# "our" table, and the target the foreign table. |
81
|
|
|
|
|
|
|
sub _invert_fk_if_necessary { |
82
|
12
|
|
|
12
|
|
26
|
my $self = shift; |
83
|
12
|
|
|
|
|
21
|
my $fk = shift; |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
# Self-referential keys are a special case, and that case differs |
86
|
|
|
|
|
|
|
# for has_one vs has_many. |
87
|
12
|
100
|
|
|
|
339
|
if ( $fk->is_self_referential() ) { |
88
|
2
|
100
|
|
|
|
464
|
if ( $self->_is_has_many() ) { |
89
|
|
|
|
|
|
|
return $fk |
90
|
|
|
|
|
|
|
unless $fk->target_table() |
91
|
1
|
50
|
|
|
|
42
|
->has_candidate_key( @{ $fk->target_columns() } ); |
|
1
|
|
|
|
|
50
|
|
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
else { |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# A self-referential key is a special case. If the target |
96
|
|
|
|
|
|
|
# columns are _not_ a key, then we need to invert source & |
97
|
|
|
|
|
|
|
# target so we do our select by a key. This doesn't |
98
|
|
|
|
|
|
|
# address a pathological case where neither source nor |
99
|
|
|
|
|
|
|
# target column sets make up a key. That shouldn't happen, |
100
|
|
|
|
|
|
|
# though ;) |
101
|
|
|
|
|
|
|
return $fk |
102
|
|
|
|
|
|
|
if $fk->target_table() |
103
|
1
|
50
|
|
|
|
19
|
->has_candidate_key( @{ $fk->target_columns() } ); |
|
1
|
|
|
|
|
25
|
|
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
else { |
107
|
10
|
100
|
|
|
|
821
|
return $fk |
108
|
|
|
|
|
|
|
if $fk->target_table()->name() eq $self->foreign_table->name(); |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
5
|
|
|
|
|
3234
|
return Fey::FK->new( |
112
|
|
|
|
|
|
|
source_columns => $fk->target_columns(), |
113
|
|
|
|
|
|
|
target_columns => $fk->source_columns(), |
114
|
|
|
|
|
|
|
); |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
1; |