performance fix for cascade_update
[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
8091aa91 256=head2 find_or_create_related
503536d5 257
30236e47 258 my $new_obj = $obj->find_or_create_related('relname', \%col_data);
259
27f01d1f 260Find or create an item of a related class. See
261L<DBIx::Class::ResultSet/"find_or_create"> for details.
503536d5 262
263=cut
264
55e2d745 265sub find_or_create_related {
266 my $self = shift;
1a14aa3f 267 return $self->find_related(@_) || $self->create_related(@_);
55e2d745 268}
269
8091aa91 270=head2 set_from_related
503536d5 271
30236e47 272 $book->set_from_related('author', $author_obj);
273
274Set column values on the current object, using related values from the given
275related object. This is used to associate previously separate objects, for
276example, to set the correct author for a book, find the Author object, then
277call set_from_related on the book.
278
27f01d1f 279The columns are only set in the local copy of the object, call L</update> to
280set them in the storage.
503536d5 281
282=cut
283
55e2d745 284sub set_from_related {
285 my ($self, $rel, $f_obj) = @_;
4685e006 286 my $rel_obj = $self->relationship_info($rel);
701da8c4 287 $self->throw_exception( "No such relationship ${rel}" ) unless $rel_obj;
55e2d745 288 my $cond = $rel_obj->{cond};
bc0c9800 289 $self->throw_exception(
290 "set_from_related can only handle a hash condition; the ".
291 "condition for $rel is of type ".
292 (ref $cond ? ref $cond : 'plain scalar')
293 ) unless ref $cond eq 'HASH';
2c037e6b 294 if (defined $f_obj) {
295 my $f_class = $self->result_source->schema->class($rel_obj->{class});
296 $self->throw_exception( "Object $f_obj isn't a ".$f_class )
297 unless $f_obj->isa($f_class);
298 }
fde6e28e 299 $self->set_columns(
300 $self->result_source->resolve_condition(
301 $rel_obj->{cond}, $f_obj, $rel));
55e2d745 302 return 1;
303}
304
8091aa91 305=head2 update_from_related
503536d5 306
30236e47 307 $book->update_from_related('author', $author_obj);
308
27f01d1f 309The same as L</"set_from_related">, but the changes are immediately updated
310in storage.
503536d5 311
312=cut
313
55e2d745 314sub update_from_related {
315 my $self = shift;
316 $self->set_from_related(@_);
317 $self->update;
318}
319
8091aa91 320=head2 delete_related
503536d5 321
30236e47 322 $obj->delete_related('relname', $cond, $attrs);
323
324Delete any related item subject to the given conditions.
503536d5 325
326=cut
327
55e2d745 328sub delete_related {
329 my $self = shift;
64acc2bc 330 my $obj = $self->search_related(@_)->delete;
331 delete $self->{related_resultsets}->{$_[0]};
332 return $obj;
55e2d745 333}
334
3351;
336
55e2d745 337=head1 AUTHORS
338
daec44b8 339Matt S. Trout <mst@shadowcatsystems.co.uk>
55e2d745 340
341=head1 LICENSE
342
343You may distribute this code under the same terms as Perl itself.
344
345=cut
346