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