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