Better linking in Relatiomship POD
[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
684af876 70In addition to the
71L<standard ResultSet attributes|DBIx::Class::ResultSet/ATTRIBUTES>,
72the following attributes are also valid:
8091aa91 73
74=over 4
75
76=item join_type
77
78Explicitly specifies the type of join to use in the relationship. Any SQL
79join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in the SQL
80command immediately before C<JOIN>.
81
82=item proxy
83
30236e47 84An arrayref containing a list of accessors in the foreign class to create in
8091aa91 85the main class. If, for example, you do the following:
86
27f01d1f 87 MyDB::Schema::CD->might_have(liner_notes => 'MyDB::Schema::LinerNotes',
88 undef, {
89 proxy => [ qw/notes/ ],
90 });
8091aa91 91
30236e47 92Then, assuming MyDB::Schema::LinerNotes has an accessor named notes, you can do:
8091aa91 93
30236e47 94 my $cd = MyDB::Schema::CD->find(1);
95 $cd->notes('Notes go here'); # set notes -- LinerNotes object is
96 # created if it doesn't exist
8091aa91 97
98=item accessor
99
100Specifies the type of accessor that should be created for the relationship.
101Valid values are C<single> (for when there is only a single related object),
102C<multi> (when there can be many), and C<filter> (for when there is a single
103related object, but you also want the relationship accessor to double as
104a column accessor). For C<multi> accessors, an add_to_* method is also
105created, which calls C<create_related> for the relationship.
106
3d618782 107=item is_foreign_key_constraint
108
109If you are using L<SQL::Translator> to create SQL for you and you find that it
110is creating constraints where it shouldn't, or not creating them where it
111should, set this attribute to a true or false value to override the detection
112of when to create constraints.
113
e377d723 114=item on_delete / on_update
115
116If you are using L<SQL::Translator> to create SQL for you, you can use these
117attributes to explicitly set the desired C<ON DELETE> or C<ON UPDATE> constraint
118type. If not supplied the SQLT parser will attempt to infer the constraint type by
119interrogating the attributes of the B<opposite> relationship. For any 'multi'
120relationship with C<< cascade_delete => 1 >>, the corresponding belongs_to
121relationship will be created with an C<ON DELETE CASCADE> constraint. For any
122relationship bearing C<< cascade_copy => 1 >> the resulting belongs_to constraint
123will be C<ON UPDATE CASCADE>. If you wish to disable this autodetection, and just
124use the RDBMS' default constraint type, pass C<< on_delete => undef >> or
125C<< on_delete => '' >>, and the same for C<on_update> respectively.
126
13de943d 127=item is_deferrable
128
129Tells L<SQL::Translator> that the foreign key constraint it creates should be
130deferrable. In other words, the user may request that the constraint be ignored
131until the end of the transaction. Currently, only the PostgreSQL producer
132actually supports this.
133
2581038c 134=item add_fk_index
135
136Tells L<SQL::Translator> to add an index for this constraint. Can also be
137specified globally in the args to L<DBIx::Class::Schema/deploy> or
138L<DBIx::Class::Schema/create_ddl_dir>. Default is on, set to 0 to disable.
139
8091aa91 140=back
141
87c4e602 142=head2 register_relationship
143
27f01d1f 144=over 4
145
ebc77b53 146=item Arguments: $relname, $rel_info
27f01d1f 147
148=back
71e65b39 149
30236e47 150Registers a relationship on the class. This is called internally by
71f9df37 151DBIx::Class::ResultSourceProxy to set up Accessors and Proxies.
71e65b39 152
55e2d745 153=cut
154
71e65b39 155sub register_relationship { }
156
27f01d1f 157=head2 related_resultset
158
159=over 4
160
ebc77b53 161=item Arguments: $relationship_name
27f01d1f 162
d601dc88 163=item Return Value: $related_resultset
27f01d1f 164
165=back
30236e47 166
27f01d1f 167 $rs = $cd->related_resultset('artist');
30236e47 168
27f01d1f 169Returns a L<DBIx::Class::ResultSet> for the relationship named
170$relationship_name.
30236e47 171
172=cut
173
174sub related_resultset {
175 my $self = shift;
bc0c9800 176 $self->throw_exception("Can't call *_related as class methods")
177 unless ref $self;
30236e47 178 my $rel = shift;
179 my $rel_obj = $self->relationship_info($rel);
bc0c9800 180 $self->throw_exception( "No such relationship ${rel}" )
181 unless $rel_obj;
30236e47 182
183 return $self->{related_resultsets}{$rel} ||= do {
184 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
185 $attrs = { %{$rel_obj->{attrs} || {}}, %$attrs };
186
bc0c9800 187 $self->throw_exception( "Invalid query: @_" )
188 if (@_ > 1 && (@_ % 2 == 1));
30236e47 189 my $query = ((@_ > 1) ? {@_} : shift);
190
68f3b0dd 191 my $source = $self->result_source;
192 my $cond = $source->resolve_condition(
bc0c9800 193 $rel_obj->{cond}, $rel, $self
194 );
68f3b0dd 195 if ($cond eq $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION) {
196 my $reverse = $source->reverse_relationship_info($rel);
197 foreach my $rev_rel (keys %$reverse) {
2c5c07ec 198 if ($reverse->{$rev_rel}{attrs}{accessor} eq 'multi') {
199 $attrs->{related_objects}{$rev_rel} = [ $self ];
200 Scalar::Util::weaken($attrs->{related_object}{$rev_rel}[0]);
201 } else {
202 $attrs->{related_objects}{$rev_rel} = $self;
203 Scalar::Util::weaken($attrs->{related_object}{$rev_rel});
204 }
68f3b0dd 205 }
206 }
30236e47 207 if (ref $cond eq 'ARRAY') {
370f2ba2 208 $cond = [ map {
209 if (ref $_ eq 'HASH') {
210 my $hash;
211 foreach my $key (keys %$_) {
212 my $newkey = $key =~ /\./ ? "me.$key" : $key;
213 $hash->{$newkey} = $_->{$key};
214 }
215 $hash;
216 } else {
217 $_;
218 }
219 } @$cond ];
68f3b0dd 220 } elsif (ref $cond eq 'HASH') {
30236e47 221 foreach my $key (grep { ! /\./ } keys %$cond) {
222 $cond->{"me.$key"} = delete $cond->{$key};
223 }
224 }
225 $query = ($query ? { '-and' => [ $cond, $query ] } : $cond);
bc0c9800 226 $self->result_source->related_source($rel)->resultset->search(
227 $query, $attrs
228 );
30236e47 229 };
230}
231
8091aa91 232=head2 search_related
503536d5 233
5b89a768 234 @objects = $rs->search_related('relname', $cond, $attrs);
235 $objects_rs = $rs->search_related('relname', $cond, $attrs);
30236e47 236
237Run a search on a related resultset. The search will be restricted to the
238item or items represented by the L<DBIx::Class::ResultSet> it was called
239upon. This method can be called on a ResultSet, a Row or a ResultSource class.
503536d5 240
241=cut
242
55e2d745 243sub search_related {
ff7bb7a1 244 return shift->related_resultset(shift)->search(@_);
b52e9bf8 245}
246
5b89a768 247=head2 search_related_rs
248
249 ( $objects_rs ) = $rs->search_related_rs('relname', $cond, $attrs);
250
60a8fb95 251This method works exactly the same as search_related, except that
6264db97 252it guarantees a restultset, even in list context.
5b89a768 253
254=cut
255
256sub search_related_rs {
257 return shift->related_resultset(shift)->search_rs(@_);
258}
259
b52e9bf8 260=head2 count_related
261
7be93b07 262 $obj->count_related('relname', $cond, $attrs);
b52e9bf8 263
bc0c9800 264Returns the count of all the items in the related resultset, restricted by the
265current item or where conditions. Can be called on a
27f01d1f 266L<DBIx::Class::Manual::Glossary/"ResultSet"> or a
bc0c9800 267L<DBIx::Class::Manual::Glossary/"Row"> object.
30236e47 268
b52e9bf8 269=cut
270
271sub count_related {
272 my $self = shift;
273 return $self->search_related(@_)->count;
55e2d745 274}
275
30236e47 276=head2 new_related
277
278 my $new_obj = $obj->new_related('relname', \%col_data);
279
280Create a new item of the related foreign class. If called on a
aaaa048e 281L<Row|DBIx::Class::Manual::Glossary/"Row"> object, it will magically
479b2a6a 282set any foreign key columns of the new object to the related primary
283key columns of the source object for you. The newly created item will
284not be saved into your storage until you call L<DBIx::Class::Row/insert>
30236e47 285on it.
286
287=cut
288
289sub new_related {
290 my ($self, $rel, $values, $attrs) = @_;
291 return $self->search_related($rel)->new($values, $attrs);
292}
293
8091aa91 294=head2 create_related
503536d5 295
30236e47 296 my $new_obj = $obj->create_related('relname', \%col_data);
297
298Creates a new item, similarly to new_related, and also inserts the item's data
299into your storage medium. See the distinction between C<create> and C<new>
300in L<DBIx::Class::ResultSet> for details.
503536d5 301
302=cut
303
55e2d745 304sub create_related {
3842b955 305 my $self = shift;
fea3d045 306 my $rel = shift;
64acc2bc 307 my $obj = $self->search_related($rel)->create(@_);
308 delete $self->{related_resultsets}->{$rel};
309 return $obj;
55e2d745 310}
311
8091aa91 312=head2 find_related
503536d5 313
30236e47 314 my $found_item = $obj->find_related('relname', @pri_vals | \%pri_vals);
315
316Attempt to find a related object using its primary key or unique constraints.
27f01d1f 317See L<DBIx::Class::ResultSet/find> for details.
503536d5 318
319=cut
320
1a14aa3f 321sub find_related {
322 my $self = shift;
323 my $rel = shift;
716b3d29 324 return $self->search_related($rel)->find(@_);
1a14aa3f 325}
326
b3e1f1f5 327=head2 find_or_new_related
328
329 my $new_obj = $obj->find_or_new_related('relname', \%col_data);
330
331Find an item of a related class. If none exists, instantiate a new item of the
332related class. The object will not be saved into your storage until you call
333L<DBIx::Class::Row/insert> on it.
334
335=cut
336
337sub find_or_new_related {
338 my $self = shift;
e60dc79f 339 my $obj = $self->find_related(@_);
340 return defined $obj ? $obj : $self->new_related(@_);
b3e1f1f5 341}
342
8091aa91 343=head2 find_or_create_related
503536d5 344
30236e47 345 my $new_obj = $obj->find_or_create_related('relname', \%col_data);
346
27f01d1f 347Find or create an item of a related class. See
b3e1f1f5 348L<DBIx::Class::ResultSet/find_or_create> for details.
503536d5 349
350=cut
351
55e2d745 352sub find_or_create_related {
353 my $self = shift;
9c2c91ea 354 my $obj = $self->find_related(@_);
355 return (defined($obj) ? $obj : $self->create_related(@_));
55e2d745 356}
357
045120e6 358=head2 update_or_create_related
359
360 my $updated_item = $obj->update_or_create_related('relname', \%col_data, \%attrs?);
361
362Update or create an item of a related class. See
f7e1846f 363L<DBIx::Class::ResultSet/update_or_create> for details.
045120e6 364
365=cut
366
367sub update_or_create_related {
368 my $self = shift;
369 my $rel = shift;
370 return $self->related_resultset($rel)->update_or_create(@_);
371}
372
8091aa91 373=head2 set_from_related
503536d5 374
30236e47 375 $book->set_from_related('author', $author_obj);
ac8e89d7 376 $book->author($author_obj); ## same thing
30236e47 377
378Set column values on the current object, using related values from the given
379related object. This is used to associate previously separate objects, for
380example, to set the correct author for a book, find the Author object, then
381call set_from_related on the book.
382
ac8e89d7 383This is called internally when you pass existing objects as values to
384L<DBIx::Class::ResultSet/create>, or pass an object to a belongs_to acessor.
385
27f01d1f 386The columns are only set in the local copy of the object, call L</update> to
387set them in the storage.
503536d5 388
389=cut
390
55e2d745 391sub set_from_related {
392 my ($self, $rel, $f_obj) = @_;
4685e006 393 my $rel_obj = $self->relationship_info($rel);
701da8c4 394 $self->throw_exception( "No such relationship ${rel}" ) unless $rel_obj;
55e2d745 395 my $cond = $rel_obj->{cond};
bc0c9800 396 $self->throw_exception(
397 "set_from_related can only handle a hash condition; the ".
398 "condition for $rel is of type ".
399 (ref $cond ? ref $cond : 'plain scalar')
400 ) unless ref $cond eq 'HASH';
2c037e6b 401 if (defined $f_obj) {
402 my $f_class = $self->result_source->schema->class($rel_obj->{class});
403 $self->throw_exception( "Object $f_obj isn't a ".$f_class )
9eb32892 404 unless Scalar::Util::blessed($f_obj) and $f_obj->isa($f_class);
2c037e6b 405 }
fde6e28e 406 $self->set_columns(
407 $self->result_source->resolve_condition(
408 $rel_obj->{cond}, $f_obj, $rel));
55e2d745 409 return 1;
410}
411
8091aa91 412=head2 update_from_related
503536d5 413
30236e47 414 $book->update_from_related('author', $author_obj);
415
27f01d1f 416The same as L</"set_from_related">, but the changes are immediately updated
417in storage.
503536d5 418
419=cut
420
55e2d745 421sub update_from_related {
422 my $self = shift;
423 $self->set_from_related(@_);
424 $self->update;
425}
426
8091aa91 427=head2 delete_related
503536d5 428
30236e47 429 $obj->delete_related('relname', $cond, $attrs);
430
431Delete any related item subject to the given conditions.
503536d5 432
433=cut
434
55e2d745 435sub delete_related {
436 my $self = shift;
64acc2bc 437 my $obj = $self->search_related(@_)->delete;
438 delete $self->{related_resultsets}->{$_[0]};
439 return $obj;
55e2d745 440}
441
ec353f53 442=head2 add_to_$rel
443
444B<Currently only available for C<has_many>, C<many-to-many> and 'multi' type
445relationships.>
446
447=over 4
448
449=item Arguments: ($foreign_vals | $obj), $link_vals?
450
451=back
452
453 my $role = $schema->resultset('Role')->find(1);
454 $actor->add_to_roles($role);
455 # creates a My::DBIC::Schema::ActorRoles linking table row object
456
457 $actor->add_to_roles({ name => 'lead' }, { salary => 15_000_000 });
458 # creates a new My::DBIC::Schema::Role row object and the linking table
459 # object with an extra column in the link
460
461Adds a linking table object for C<$obj> or C<$foreign_vals>. If the first
462argument is a hash reference, the related object is created first with the
463column values in the hash. If an object reference is given, just the linking
464table object is created. In either case, any additional column values for the
465linking table object can be specified in C<$link_vals>.
466
467=head2 set_$rel
468
469B<Currently only available for C<many-to-many> relationships.>
470
471=over 4
472
4d3a827d 473=item Arguments: (\@hashrefs | \@objs)
ec353f53 474
475=back
476
477 my $actor = $schema->resultset('Actor')->find(1);
478 my @roles = $schema->resultset('Role')->search({ role =>
debccec3 479 { '-in' => ['Fred', 'Barney'] } } );
ec353f53 480
4d3a827d 481 $actor->set_roles(\@roles);
482 # Replaces all of $actor's previous roles with the two named
ec353f53 483
4d3a827d 484Replace all the related objects with the given reference to a list of
485objects. This does a C<delete> B<on the link table resultset> to remove the
486association between the current object and all related objects, then calls
487C<add_to_$rel> repeatedly to link all the new objects.
bba68c67 488
489Note that this means that this method will B<not> delete any objects in the
490table on the right side of the relation, merely that it will delete the link
491between them.
ec353f53 492
4d3a827d 493Due to a mistake in the original implementation of this method, it will also
494accept a list of objects or hash references. This is B<deprecated> and will be
495removed in a future version.
496
ec353f53 497=head2 remove_from_$rel
498
499B<Currently only available for C<many-to-many> relationships.>
500
501=over 4
502
503=item Arguments: $obj
504
505=back
506
507 my $role = $schema->resultset('Role')->find(1);
508 $actor->remove_from_roles($role);
509 # removes $role's My::DBIC::Schema::ActorRoles linking table row object
510
511Removes the link between the current object and the related object. Note that
512the related object itself won't be deleted unless you call ->delete() on
513it. This method just removes the link between the two objects.
514
55e2d745 515=head1 AUTHORS
516
daec44b8 517Matt S. Trout <mst@shadowcatsystems.co.uk>
55e2d745 518
519=head1 LICENSE
520
521You may distribute this code under the same terms as Perl itself.
522
523=cut
524
4d87db01 5251;