File Coverage

blib/lib/SQL/Entity/Relationship.pm
Criterion Covered Total %
statement 58 58 100.0
branch 16 20 80.0
condition 5 9 55.5
subroutine 15 15 100.0
pod 8 8 100.0
total 102 110 92.7


line stmt bran cond sub pod time code
1             package SQL::Entity::Relationship;
2              
3 5     5   966 use warnings;
  5         11  
  5         172  
4 5     5   26 use strict;
  5         10  
  5         172  
5 5     5   25 use Carp 'confess';
  5         11  
  5         278  
6 5     5   27 use vars qw(@EXPORT_OK %EXPORT_TAGS $VERSION);
  5         16  
  5         342  
7 5     5   616 use SQL::Entity::Condition;
  5         10  
  5         269  
8              
9             $VERSION = '0.01';
10 5     5   36 use base 'Exporter';
  5         9  
  5         709  
11              
12             @EXPORT_OK = qw(sql_relationship);
13             %EXPORT_TAGS = (all => \@EXPORT_OK);
14              
15 5     5   31 use Abstract::Meta::Class ':all';
  5         8  
  5         6648  
16              
17             =head1 NAME
18              
19             SQL::Entity::Relationship - Entities Relationship abstraction layer.
20              
21             =head1 SYNOPSIS
22              
23             use SQL::Entity::Relationship ':all';
24             use SQL::Entity::Column ':all';
25             use SQL::Entity::Table;
26             use SQL::Entity::Condition ':all';
27              
28             my $dept = SQL::Entity::Table->new(
29             name => 'dept',
30             alias => 'd',
31             columns => [
32             sql_column(name => 'deptno'),
33             sql_column(name => 'dname')
34             ],
35             );
36             my $emp = SQL::Entity->new(
37             name => 'emp',
38             primary_key => ['empno'],
39             unique_expression => 'rowid',
40             columns => [
41             sql_column(name => 'ename'),
42             sql_column(name => 'empno'),
43             sql_column(name => 'deptno')
44             ],
45             );
46             $emp->add_to_one_relationships(sql_relationship(
47             target_entity => $dept,
48             condition => sql_cond($dept->column('deptno'), '=', $entity->column('deptno'))
49             ));
50              
51             =head1 DESCRIPTION
52              
53             Represents relationship between entities.
54              
55             =head2 EXPORT
56              
57             sql_relationship by all tag.
58              
59             =head2 ATTRIBUTES
60              
61             =over
62              
63             =item name
64              
65             Name of the relationship
66              
67             =cut
68              
69             has '$.name';
70              
71              
72             =item target_entity
73              
74             =cut
75              
76             has '$.target_entity' => (associated_class => 'SQL::Entity');
77              
78              
79             =item condition
80              
81             =cut
82              
83             has '$.condition' => (associated_class => 'SQL::Entity::Condition');
84              
85              
86             =item join_columns
87              
88             =cut
89              
90             has '@.join_columns';
91              
92              
93             =item order_by
94              
95             =cut
96              
97             has '$.order_by';
98              
99              
100             =back
101              
102             =head2 METHODS
103              
104             =over
105              
106             =item initialise
107              
108             =cut
109              
110             sub initialise {
111 7     7 1 1790 my ($self) = @_;
112 7 100       21 $self->name($self->target_entity->id)
113             unless $self->name;
114             }
115              
116              
117             =item join_condition
118              
119             Return join condition.
120              
121             =cut
122              
123             sub join_condition {
124 3     3 1 13 my ($self, $entity, $bind_variables, $entity_condition) = @_;
125 3         17 my $join_condition = $self->join_columns_condition($entity);
126 3         12 my $condition = $self->condition;
127 3 50 66     50 $condition = $condition && $join_condition
      66        
128             ? $join_condition->and($condition)
129             : $condition || $join_condition;
130 3 100       11 $condition = $entity_condition ? $condition->and($entity_condition) : $condition;
131 3         17 $condition;
132             }
133              
134              
135              
136             =item join_condition_as_string
137              
138             Return SQL condition fragment.
139              
140             =cut
141              
142             sub join_condition_as_string {
143 2     2 1 55 my ($self, $entity, $bind_variables, $entity_condition) = @_;
144 2         9 my $condition = $self->join_condition($entity, $bind_variables, $entity_condition);
145 2         7 my $target_entity = $self->target_entity;
146 2         20 my %query_columns = $entity->query_columns;
147 2         32 $condition->as_string(\%query_columns, $bind_variables, $entity);
148             }
149              
150              
151             =item join_columns_values
152              
153             Returns join columns values.
154              
155             =cut
156              
157             sub join_columns_values {
158 5     5 1 2101 my ($self, $entity) = @_;
159 5         16 my $target_entity = $self->target_entity;
160 5 100       44 if($entity->to_one_relationship($self->name)) {
161 3         68 $target_entity = $entity;
162 3         11 $entity = $self->target_entity;
163             }
164 5 100       68 my @join_columns = $self->join_columns or return;
165 3 50       31 my @primary_key = $entity->primary_key or confess "primary key must be defined for entity " . $entity->name;
166            
167 3         25 my @result;
168 3         7 for my $i (0 .. $#primary_key) {
169 3 100       12 my $column = $entity->column($primary_key[$i])
170             or confess "unknown primary key column: " . $primary_key[$i] . " on " . $entity->name;
171 2         31 push @result, $column;
172              
173 2 100       5 my $join_column = $target_entity->column($join_columns[$i])
174             or confess "unknown foreign key column: " . $join_columns[$i] . " on " . $target_entity->name;
175 1         12 push @result, $join_column;
176             }
177 1         3 @result;
178            
179             }
180              
181             =item join_columns_condition
182              
183             Returns condition for join columns.
184              
185             =cut
186              
187             sub join_columns_condition {
188 3     3 1 6 my ($self, $entity) = @_;
189 3         11 my @condition = $self->join_columns_values($entity);
190 3         44 SQL::Entity::Condition->struct_to_condition(@condition);
191             }
192              
193              
194             =item order_by_clause
195              
196             Returns order by sql fragment.
197              
198             =cut
199              
200             sub order_by_clause {
201 1     1 1 2 my ($self) = @_;
202 1         4 my $order_by = $self->order_by;
203 1 50       8 $order_by ? " ORDER BY ${order_by}" : "";
204             }
205              
206              
207             =item associate_the_other_end
208              
209             Associated the other end.
210              
211             =cut
212              
213             sub associate_the_other_end {
214 3     3 1 4 my ($self, $entity) = @_;
215 3         7 my $target_entity = $self->target_entity;
216 3 50 33     23 $target_entity->add_to_one_relationships(sql_relationship(
217             name => ($entity->id || $entity->name),
218             target_entity => $entity,
219             condition => $self->condition,
220             ($self->join_columns ? (join_columns => [$self->join_columns ]) : ())
221             ));
222             }
223              
224              
225             =item sql_relationship
226              
227             Creates a new relation object.
228              
229             =cut
230              
231             sub sql_relationship {
232 5     5 1 104 __PACKAGE__->new(@_);
233             }
234              
235              
236              
237             1;
238              
239             __END__