Merge 'trunk' into 'DBIx-Class-current'
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Relationship / Base.pm
CommitLineData
55e2d745 1package DBIx::Class::Relationship::Base;
2
3use strict;
4use warnings;
5
1edd1722 6use base qw/DBIx::Class/;
55e2d745 7
75d07914 8=head1 NAME
55e2d745 9
8918977e 10DBIx::Class::Relationship::Base - Inter-table relationships
55e2d745 11
12=head1 SYNOPSIS
13
14=head1 DESCRIPTION
15
30236e47 16This class provides methods to describe the relationships between the
17tables in your database model. These are the "bare bones" relationships
75d07914 18methods, for predefined ones, look in L<DBIx::Class::Relationship>.
55e2d745 19
20=head1 METHODS
21
8091aa91 22=head2 add_relationship
503536d5 23
27f01d1f 24=over 4
25
ebc77b53 26=item Arguments: 'relname', 'Foreign::Class', $cond, $attrs
27f01d1f 27
28=back
30236e47 29
503536d5 30 __PACKAGE__->add_relationship('relname', 'Foreign::Class', $cond, $attrs);
31
5271499d 32The condition needs to be an L<SQL::Abstract>-style representation of the
33join between the tables. When resolving the condition for use in a C<JOIN>,
34keys using the pseudo-table C<foreign> are resolved to mean "the Table on the
35other side of the relationship", and values using the pseudo-table C<self>
30236e47 36are resolved to mean "the Table this class is representing". Other
37restrictions, such as by value, sub-select and other tables, may also be
5271499d 38used. Please check your database for C<JOIN> parameter support.
30236e47 39
5271499d 40For example, if you're creating a relationship from C<Author> to C<Book>, where
41the C<Book> table has a column C<author_id> containing the ID of the C<Author>
42row:
503536d5 43
30236e47 44 { 'foreign.author_id' => 'self.id' }
503536d5 45
5271499d 46will result in the C<JOIN> clause
503536d5 47
5271499d 48 author me JOIN book book ON book.author_id = me.id
503536d5 49
5271499d 50For multi-column foreign keys, you will need to specify a C<foreign>-to-C<self>
51mapping for each column in the key. For example, if you're creating a
52relationship from C<Book> to C<Edition>, where the C<Edition> table refers to a
53publisher and a type (e.g. "paperback"):
54
55 {
781102cd 56 'foreign.publisher_id' => 'self.publisher_id',
5271499d 57 'foreign.type_id' => 'self.type_id',
58 }
59
60This will result in the C<JOIN> clause:
61
62 book me JOIN edition edition ON edition.publisher_id = me.publisher_id
63 AND edition.type_id = me.type_id
64
65Each key-value pair provided in a hashref will be used as C<AND>ed conditions.
66To add an C<OR>ed condition, use an arrayref of hashrefs. See the
67L<SQL::Abstract> documentation for more details.
8091aa91 68
69Valid attributes are as follows:
70
71=over 4
72
73=item join_type
74
75Explicitly specifies the type of join to use in the relationship. Any SQL
76join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in the SQL
77command immediately before C<JOIN>.
78
79=item proxy
80
30236e47 81An arrayref containing a list of accessors in the foreign class to create in
8091aa91 82the main class. If, for example, you do the following:
83
27f01d1f 84 MyDB::Schema::CD->might_have(liner_notes => 'MyDB::Schema::LinerNotes',
85 undef, {
86 proxy => [ qw/notes/ ],
87 });
8091aa91 88
30236e47 89Then, assuming MyDB::Schema::LinerNotes has an accessor named notes, you can do:
8091aa91 90
30236e47 91 my $cd = MyDB::Schema::CD->find(1);
92 $cd->notes('Notes go here'); # set notes -- LinerNotes object is
93 # created if it doesn't exist
8091aa91 94
95=item accessor
96
97Specifies the type of accessor that should be created for the relationship.
98Valid values are C<single> (for when there is only a single related object),
99C<multi> (when there can be many), and C<filter> (for when there is a single
100related object, but you also want the relationship accessor to double as
101a column accessor). For C<multi> accessors, an add_to_* method is also
102created, which calls C<create_related> for the relationship.
103
104=back
105
87c4e602 106=head2 register_relationship
107
27f01d1f 108=over 4
109
ebc77b53 110=item Arguments: $relname, $rel_info
27f01d1f 111
112=back
71e65b39 113
30236e47 114Registers a relationship on the class. This is called internally by
71f9df37 115DBIx::Class::ResultSourceProxy to set up Accessors and Proxies.
71e65b39 116
55e2d745 117=cut
118
71e65b39 119sub register_relationship { }
120
27f01d1f 121=head2 related_resultset
122
123=over 4
124
ebc77b53 125=item Arguments: $relationship_name
27f01d1f 126
d601dc88 127=item Return Value: $related_resultset
27f01d1f 128
129=back
30236e47 130
27f01d1f 131 $rs = $cd->related_resultset('artist');
30236e47 132
27f01d1f 133Returns a L<DBIx::Class::ResultSet> for the relationship named
134$relationship_name.
30236e47 135
136=cut
137
138sub related_resultset {
139 my $self = shift;
bc0c9800 140 $self->throw_exception("Can't call *_related as class methods")
141 unless ref $self;
30236e47 142 my $rel = shift;
143 my $rel_obj = $self->relationship_info($rel);
bc0c9800 144 $self->throw_exception( "No such relationship ${rel}" )
145 unless $rel_obj;
30236e47 146
147 return $self->{related_resultsets}{$rel} ||= do {
148 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
149 $attrs = { %{$rel_obj->{attrs} || {}}, %$attrs };
150
bc0c9800 151 $self->throw_exception( "Invalid query: @_" )
152 if (@_ > 1 && (@_ % 2 == 1));
30236e47 153 my $query = ((@_ > 1) ? {@_} : shift);
154
bc0c9800 155 my $cond = $self->result_source->resolve_condition(
156 $rel_obj->{cond}, $rel, $self
157 );
30236e47 158 if (ref $cond eq 'ARRAY') {
159 $cond = [ map { my $hash;
160 foreach my $key (keys %$_) {
161 my $newkey = $key =~ /\./ ? "me.$key" : $key;
162 $hash->{$newkey} = $_->{$key};
163 }; $hash } @$cond ];
164 } else {
165 foreach my $key (grep { ! /\./ } keys %$cond) {
166 $cond->{"me.$key"} = delete $cond->{$key};
167 }
168 }
169 $query = ($query ? { '-and' => [ $cond, $query ] } : $cond);
bc0c9800 170 $self->result_source->related_source($rel)->resultset->search(
171 $query, $attrs
172 );
30236e47 173 };
174}
175
8091aa91 176=head2 search_related
503536d5 177
30236e47 178 $rs->search_related('relname', $cond, $attrs);
179
180Run a search on a related resultset. The search will be restricted to the
181item or items represented by the L<DBIx::Class::ResultSet> it was called
182upon. This method can be called on a ResultSet, a Row or a ResultSource class.
503536d5 183
184=cut
185
55e2d745 186sub search_related {
ff7bb7a1 187 return shift->related_resultset(shift)->search(@_);
b52e9bf8 188}
189
190=head2 count_related
191
7be93b07 192 $obj->count_related('relname', $cond, $attrs);
b52e9bf8 193
bc0c9800 194Returns the count of all the items in the related resultset, restricted by the
195current item or where conditions. Can be called on a
27f01d1f 196L<DBIx::Class::Manual::Glossary/"ResultSet"> or a
bc0c9800 197L<DBIx::Class::Manual::Glossary/"Row"> object.
30236e47 198
b52e9bf8 199=cut
200
201sub count_related {
202 my $self = shift;
203 return $self->search_related(@_)->count;
55e2d745 204}
205
30236e47 206=head2 new_related
207
208 my $new_obj = $obj->new_related('relname', \%col_data);
209
210Create a new item of the related foreign class. If called on a
27f01d1f 211L<DBIx::Class::Manual::Glossary/"Row"> object, it will magically set any
212primary key values into foreign key columns for you. The newly created item
213will not be saved into your storage until you call L<DBIx::Class::Row/insert>
30236e47 214on it.
215
216=cut
217
218sub new_related {
219 my ($self, $rel, $values, $attrs) = @_;
220 return $self->search_related($rel)->new($values, $attrs);
221}
222
8091aa91 223=head2 create_related
503536d5 224
30236e47 225 my $new_obj = $obj->create_related('relname', \%col_data);
226
227Creates a new item, similarly to new_related, and also inserts the item's data
228into your storage medium. See the distinction between C<create> and C<new>
229in L<DBIx::Class::ResultSet> for details.
503536d5 230
231=cut
232
55e2d745 233sub create_related {
3842b955 234 my $self = shift;
fea3d045 235 my $rel = shift;
64acc2bc 236 my $obj = $self->search_related($rel)->create(@_);
237 delete $self->{related_resultsets}->{$rel};
238 return $obj;
55e2d745 239}
240
8091aa91 241=head2 find_related
503536d5 242
30236e47 243 my $found_item = $obj->find_related('relname', @pri_vals | \%pri_vals);
244
245Attempt to find a related object using its primary key or unique constraints.
27f01d1f 246See L<DBIx::Class::ResultSet/find> for details.
503536d5 247
248=cut
249
1a14aa3f 250sub find_related {
251 my $self = shift;
252 my $rel = shift;
716b3d29 253 return $self->search_related($rel)->find(@_);
1a14aa3f 254}
255
b3e1f1f5 256=head2 find_or_new_related
257
258 my $new_obj = $obj->find_or_new_related('relname', \%col_data);
259
260Find an item of a related class. If none exists, instantiate a new item of the
261related class. The object will not be saved into your storage until you call
262L<DBIx::Class::Row/insert> on it.
263
264=cut
265
266sub find_or_new_related {
267 my $self = shift;
268 return $self->find_related(@_) || $self->new_related(@_);
269}
270
8091aa91 271=head2 find_or_create_related
503536d5 272
30236e47 273 my $new_obj = $obj->find_or_create_related('relname', \%col_data);
274
27f01d1f 275Find or create an item of a related class. See
b3e1f1f5 276L<DBIx::Class::ResultSet/find_or_create> for details.
503536d5 277
278=cut
279
55e2d745 280sub find_or_create_related {
281 my $self = shift;
1a14aa3f 282 return $self->find_related(@_) || $self->create_related(@_);
55e2d745 283}
284
045120e6 285=head2 update_or_create_related
286
287 my $updated_item = $obj->update_or_create_related('relname', \%col_data, \%attrs?);
288
289Update or create an item of a related class. See
f7e1846f 290L<DBIx::Class::ResultSet/update_or_create> for details.
045120e6 291
292=cut
293
294sub update_or_create_related {
295 my $self = shift;
296 my $rel = shift;
297 return $self->related_resultset($rel)->update_or_create(@_);
298}
299
8091aa91 300=head2 set_from_related
503536d5 301
30236e47 302 $book->set_from_related('author', $author_obj);
303
304Set column values on the current object, using related values from the given
305related object. This is used to associate previously separate objects, for
306example, to set the correct author for a book, find the Author object, then
307call set_from_related on the book.
308
27f01d1f 309The columns are only set in the local copy of the object, call L</update> to
310set them in the storage.
503536d5 311
312=cut
313
55e2d745 314sub set_from_related {
315 my ($self, $rel, $f_obj) = @_;
4685e006 316 my $rel_obj = $self->relationship_info($rel);
701da8c4 317 $self->throw_exception( "No such relationship ${rel}" ) unless $rel_obj;
55e2d745 318 my $cond = $rel_obj->{cond};
bc0c9800 319 $self->throw_exception(
320 "set_from_related can only handle a hash condition; the ".
321 "condition for $rel is of type ".
322 (ref $cond ? ref $cond : 'plain scalar')
323 ) unless ref $cond eq 'HASH';
2c037e6b 324 if (defined $f_obj) {
325 my $f_class = $self->result_source->schema->class($rel_obj->{class});
326 $self->throw_exception( "Object $f_obj isn't a ".$f_class )
327 unless $f_obj->isa($f_class);
328 }
fde6e28e 329 $self->set_columns(
330 $self->result_source->resolve_condition(
331 $rel_obj->{cond}, $f_obj, $rel));
55e2d745 332 return 1;
333}
334
8091aa91 335=head2 update_from_related
503536d5 336
30236e47 337 $book->update_from_related('author', $author_obj);
338
27f01d1f 339The same as L</"set_from_related">, but the changes are immediately updated
340in storage.
503536d5 341
342=cut
343
55e2d745 344sub update_from_related {
345 my $self = shift;
346 $self->set_from_related(@_);
347 $self->update;
348}
349
8091aa91 350=head2 delete_related
503536d5 351
30236e47 352 $obj->delete_related('relname', $cond, $attrs);
353
354Delete any related item subject to the given conditions.
503536d5 355
356=cut
357
55e2d745 358sub delete_related {
359 my $self = shift;
64acc2bc 360 my $obj = $self->search_related(@_)->delete;
361 delete $self->{related_resultsets}->{$_[0]};
362 return $obj;
55e2d745 363}
364
3651;
366
55e2d745 367=head1 AUTHORS
368
daec44b8 369Matt S. Trout <mst@shadowcatsystems.co.uk>
55e2d745 370
371=head1 LICENSE
372
373You may distribute this code under the same terms as Perl itself.
374
375=cut
376