File Coverage

blib/lib/DBR/Config/Relation.pm
Criterion Covered Total %
statement 81 83 97.5
branch 20 34 58.8
condition 4 9 44.4
subroutine 18 19 94.7
pod 0 13 0.0
total 123 158 77.8


line stmt bran cond sub pod time code
1             # the contents of this file are Copyright (c) 2009 Daniel Norman
2             # This program is free software; you can redistribute it and/or
3             # modify it under the terms of the GNU General Public License as
4             # published by the Free Software Foundation.
5              
6             package DBR::Config::Relation;
7              
8 18     18   124 use strict;
  18         41  
  18         794  
9 18     18   109 use base 'DBR::Common';
  18         44  
  18         2056  
10 18     18   155 use DBR::Config::Table;
  18         40  
  18         386  
11 18     18   100 use DBR::Config::Field;
  18         37  
  18         609  
12 18     18   96 use Carp;
  18         48  
  18         1663  
13 18     18   112 use Clone 'clone';
  18         47  
  18         38748  
14              
15             my %TYPES = (
16             1 => { name => 'parentof', mode => '1toM', opposite => 2 }, #reciprocal
17             2 => { name => 'childof', mode => 'Mto1', opposite => 1 },
18             3 => { name => 'assoc', mode => 'MtoM' },
19             4 => { name => 'other', mode => 'MtoM' },
20             );
21              
22             map { $TYPES{$_}{type_id} = $_ } keys %TYPES;
23              
24             sub list_types{
25 18     18 0 159 return clone( [ sort {$a->{type_id} <=> $b->{type_id} } values %TYPES ] );
  84         1393  
26             }
27              
28              
29             my %RELATIONS_BY_ID;
30             sub load{
31 34     34 0 100 my( $package ) = shift;
32 34         161 my %params = @_;
33              
34 34         221 my $self = { session => $params{session} };
35 34         220 bless( $self, $package ); # Dummy object
36              
37 34   50     159 my $instance = $params{instance} || return $self->_error('instance is required');
38              
39 34   50     152 my $table_ids = $params{table_id} || return $self->_error('table_id is required');
40 34 50       211 $table_ids = [$table_ids] unless ref($table_ids) eq 'ARRAY';
41              
42 34 50       171 return 1 unless @$table_ids;
43              
44 34   50     1961 my $dbrh = $instance->connect || return $self->_error("Failed to connect to ${\$instance->name}");
45              
46 34 50       474 return $self->_error('Failed to select from dbr_relationships') unless
47             my $relations = $dbrh->select(
48             -table => 'dbr_relationships',
49             -fields => 'relationship_id from_name from_table_id from_field_id to_name to_table_id to_field_id type',
50             -where => { from_table_id => ['d in',@$table_ids] },
51             );
52              
53 34         183 my @rel_ids;
54 34         125 foreach my $relation (@$relations){
55              
56 24 50       193 my $table1 = DBR::Config::Table->_register_relation(
57             table_id => $relation->{to_table_id},
58             name => $relation->{from_name}, #yes, this is kinda confusing
59             relation_id => $relation->{relationship_id},
60             ) or return $self->_error('failed to register to relationship');
61              
62 24 50       142 my $table2 = DBR::Config::Table->_register_relation(
63             table_id => $relation->{from_table_id},
64             name => $relation->{to_name}, #yes, this is kinda confusing
65             relation_id => $relation->{relationship_id},
66             ) or return $self->_error('failed to register from relationship');
67              
68              
69 24         103 $relation->{same_schema} = ( $table1->{schema_id} == $table2->{schema_id} );
70              
71 24         106 $RELATIONS_BY_ID{ $relation->{relationship_id} } = $relation;
72 24         140 push @rel_ids, $relation->{relationship_id};
73              
74             }
75              
76 34         214 return 1;
77             }
78              
79              
80             sub new {
81 44     44 0 185 my $package = shift;
82 44         207 my %params = @_;
83 44         268 my $self = {
84             session => $params{session},
85             relation_id => $params{relation_id},
86             table_id => $params{table_id},
87             };
88              
89 44         156 bless( $self, $package );
90              
91 44 50       210 return $self->_error('relation_id is required') unless $self->{relation_id};
92 44 50       148 return $self->_error('table_id is required') unless $self->{table_id};
93              
94              
95 44 50       266 my $ref = $RELATIONS_BY_ID{ $self->{relation_id} } or return $self->_error('invalid relation_id');
96 44 50       194 return $self->_error("Invalid type_id $ref->{type}") unless $TYPES{ $ref->{type} };
97              
98 44 100       232 if($ref->{from_table_id} == $self->{table_id}){
    50          
99              
100 25         85 $self->{forward} = 'from';
101 25         77 $self->{reverse} = 'to';
102 25         85 $self->{type_id} = $ref->{type};
103             }elsif($ref->{to_table_id} == $self->{table_id}){
104              
105 19         86 $self->{forward} = 'to';
106 19         55 $self->{reverse} = 'from';
107 19   33     105 $self->{type_id} = $TYPES{ $ref->{type} }->{opposite} || $ref->{type};
108              
109             }else{
110 0         0 return $self->_error("table_id $self->{table_id} is invalid for this relationship");
111             }
112              
113 44         241 return( $self );
114             }
115              
116 0     0 0 0 sub relation_id { $_[0]->{relation_id} }
117 35     35 0 229 sub name { $RELATIONS_BY_ID{ $_[0]->{relation_id} }->{ $_[0]->{reverse} . '_name' } } # Name is always the opposite of everything else
118              
119             sub field_id {
120 35     35 0 62 my $self = shift;
121              
122 35         301 return $RELATIONS_BY_ID{ $self->{relation_id} }->{ $self->{forward} . '_field_id' };
123             }
124              
125             sub field {
126 9     9 0 18 my $self = shift;
127 9         36 my $field_id = $RELATIONS_BY_ID{ $self->{relation_id} }->{ $self->{forward} . '_field_id' };
128              
129 9 50       48 my $field = DBR::Config::Field->new(
130             session => $self->{session},
131             field_id => $field_id,
132             ) or return $self->_error('failed to create field object');
133              
134 9         39 return $field;
135             }
136              
137             sub mapfield {
138 21     21 0 57 my $self = shift;
139 21         283 my $mapfield_id = $RELATIONS_BY_ID{ $self->{relation_id} }->{ $self->{reverse} . '_field_id' };
140              
141 21 50       135 my $field = DBR::Config::Field->new(
142             session => $self->{session},
143             field_id => $mapfield_id,
144             ) or return $self->_error('failed to create field object');
145              
146 21         95 return $field;
147             }
148              
149             sub table {
150 12     12 0 35 my $self = shift;
151              
152 12         144 return DBR::Config::Table->new(
153             session => $self->{session},
154             table_id => $RELATIONS_BY_ID{ $self->{relation_id} }->{$self->{forward} . '_table_id'}
155             );
156             }
157              
158             sub maptable {
159 21     21 0 49 my $self = shift;
160              
161 21         176 return DBR::Config::Table->new(
162             session => $self->{session},
163             table_id => $RELATIONS_BY_ID{ $self->{relation_id} }->{$self->{reverse} . '_table_id'}
164             );
165             }
166              
167             sub is_to_one{
168 30     30 0 137 my $mode = $TYPES{ $_[0]->{type_id} }->{mode};
169              
170 30 100       365 return 1 if $mode eq 'Mto1';
171 4 50       14 return 1 if $mode eq '1to1';
172              
173 4         12 return 0;
174             }
175              
176 28     28 0 219 sub is_same_schema{ $RELATIONS_BY_ID{ shift->{relation_id} }->{same_schema} }
177              
178              
179             sub index{
180 66     66 0 117 my $self = shift;
181 66         108 my $set = shift;
182              
183 66 100       186 if(defined($set)){
184 8 50       36 croak "Cannot set the index on a relation object twice" if defined($self->{index}); # I want this to fail obnoxiously
185 8         25 $self->{index} = $set;
186 8         28 return 1;
187             }
188              
189 58         195 return $self->{index};
190             }
191              
192             1;