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