Merge 'DBIx-Class-current' into 'find_changes'
[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
32The condition needs to be an SQL::Abstract-style representation of the
30236e47 33join between the tables. When resolving the condition for use in a JOIN,
880a1a0c 34keys using the pseudo-table I<foreign> are resolved to mean "the Table on the
35other side of the relationship", and values using the pseudo-table I<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
38used. Please check your database for JOIN parameter support.
39
40For example, if you're creating a rel from Author to Book, where the Book
41table has a column author_id containing the ID of the Author row:
503536d5 42
30236e47 43 { 'foreign.author_id' => 'self.id' }
503536d5 44
8091aa91 45will result in the JOIN clause
503536d5 46
30236e47 47 author me JOIN book book ON bar.author_id = me.id
503536d5 48
30236e47 49You can specify as many foreign => self mappings as necessary. Each key/value
50pair provided in a hashref will be used as ANDed conditions, to add an ORed
51condition, use an arrayref of hashrefs. See the L<SQL::Abstract> documentation
52for more details.
8091aa91 53
54Valid attributes are as follows:
55
56=over 4
57
58=item join_type
59
60Explicitly specifies the type of join to use in the relationship. Any SQL
61join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in the SQL
62command immediately before C<JOIN>.
63
64=item proxy
65
30236e47 66An arrayref containing a list of accessors in the foreign class to create in
8091aa91 67the main class. If, for example, you do the following:
68
27f01d1f 69 MyDB::Schema::CD->might_have(liner_notes => 'MyDB::Schema::LinerNotes',
70 undef, {
71 proxy => [ qw/notes/ ],
72 });
8091aa91 73
30236e47 74Then, assuming MyDB::Schema::LinerNotes has an accessor named notes, you can do:
8091aa91 75
30236e47 76 my $cd = MyDB::Schema::CD->find(1);
77 $cd->notes('Notes go here'); # set notes -- LinerNotes object is
78 # created if it doesn't exist
8091aa91 79
80=item accessor
81
82Specifies the type of accessor that should be created for the relationship.
83Valid values are C<single> (for when there is only a single related object),
84C<multi> (when there can be many), and C<filter> (for when there is a single
85related object, but you also want the relationship accessor to double as
86a column accessor). For C<multi> accessors, an add_to_* method is also
87created, which calls C<create_related> for the relationship.
88
89=back
90
87c4e602 91=head2 register_relationship
92
27f01d1f 93=over 4
94
ebc77b53 95=item Arguments: $relname, $rel_info
27f01d1f 96
97=back
71e65b39 98
30236e47 99Registers a relationship on the class. This is called internally by
100L<DBIx::Class::ResultSourceProxy> to set up Accessors and Proxies.
71e65b39 101
55e2d745 102=cut
103
71e65b39 104sub register_relationship { }
105
27f01d1f 106=head2 related_resultset
107
108=over 4
109
ebc77b53 110=item Arguments: $relationship_name
27f01d1f 111
d601dc88 112=item Return Value: $related_resultset
27f01d1f 113
114=back
30236e47 115
27f01d1f 116 $rs = $cd->related_resultset('artist');
30236e47 117
27f01d1f 118Returns a L<DBIx::Class::ResultSet> for the relationship named
119$relationship_name.
30236e47 120
121=cut
122
123sub related_resultset {
124 my $self = shift;
bc0c9800 125 $self->throw_exception("Can't call *_related as class methods")
126 unless ref $self;
30236e47 127 my $rel = shift;
128 my $rel_obj = $self->relationship_info($rel);
bc0c9800 129 $self->throw_exception( "No such relationship ${rel}" )
130 unless $rel_obj;
30236e47 131
132 return $self->{related_resultsets}{$rel} ||= do {
133 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
134 $attrs = { %{$rel_obj->{attrs} || {}}, %$attrs };
135
bc0c9800 136 $self->throw_exception( "Invalid query: @_" )
137 if (@_ > 1 && (@_ % 2 == 1));
30236e47 138 my $query = ((@_ > 1) ? {@_} : shift);
139
bc0c9800 140 my $cond = $self->result_source->resolve_condition(
141 $rel_obj->{cond}, $rel, $self
142 );
30236e47 143 if (ref $cond eq 'ARRAY') {
144 $cond = [ map { my $hash;
145 foreach my $key (keys %$_) {
146 my $newkey = $key =~ /\./ ? "me.$key" : $key;
147 $hash->{$newkey} = $_->{$key};
148 }; $hash } @$cond ];
149 } else {
150 foreach my $key (grep { ! /\./ } keys %$cond) {
151 $cond->{"me.$key"} = delete $cond->{$key};
152 }
153 }
154 $query = ($query ? { '-and' => [ $cond, $query ] } : $cond);
bc0c9800 155 $self->result_source->related_source($rel)->resultset->search(
156 $query, $attrs
157 );
30236e47 158 };
159}
160
8091aa91 161=head2 search_related
503536d5 162
30236e47 163 $rs->search_related('relname', $cond, $attrs);
164
165Run a search on a related resultset. The search will be restricted to the
166item or items represented by the L<DBIx::Class::ResultSet> it was called
167upon. This method can be called on a ResultSet, a Row or a ResultSource class.
503536d5 168
169=cut
170
55e2d745 171sub search_related {
ff7bb7a1 172 return shift->related_resultset(shift)->search(@_);
b52e9bf8 173}
174
175=head2 count_related
176
7be93b07 177 $obj->count_related('relname', $cond, $attrs);
b52e9bf8 178
bc0c9800 179Returns the count of all the items in the related resultset, restricted by the
180current item or where conditions. Can be called on a
27f01d1f 181L<DBIx::Class::Manual::Glossary/"ResultSet"> or a
bc0c9800 182L<DBIx::Class::Manual::Glossary/"Row"> object.
30236e47 183
b52e9bf8 184=cut
185
186sub count_related {
187 my $self = shift;
188 return $self->search_related(@_)->count;
55e2d745 189}
190
30236e47 191=head2 new_related
192
193 my $new_obj = $obj->new_related('relname', \%col_data);
194
195Create a new item of the related foreign class. If called on a
27f01d1f 196L<DBIx::Class::Manual::Glossary/"Row"> object, it will magically set any
197primary key values into foreign key columns for you. The newly created item
198will not be saved into your storage until you call L<DBIx::Class::Row/insert>
30236e47 199on it.
200
201=cut
202
203sub new_related {
204 my ($self, $rel, $values, $attrs) = @_;
205 return $self->search_related($rel)->new($values, $attrs);
206}
207
8091aa91 208=head2 create_related
503536d5 209
30236e47 210 my $new_obj = $obj->create_related('relname', \%col_data);
211
212Creates a new item, similarly to new_related, and also inserts the item's data
213into your storage medium. See the distinction between C<create> and C<new>
214in L<DBIx::Class::ResultSet> for details.
503536d5 215
216=cut
217
55e2d745 218sub create_related {
3842b955 219 my $self = shift;
fea3d045 220 my $rel = shift;
64acc2bc 221 my $obj = $self->search_related($rel)->create(@_);
222 delete $self->{related_resultsets}->{$rel};
223 return $obj;
55e2d745 224}
225
8091aa91 226=head2 find_related
503536d5 227
30236e47 228 my $found_item = $obj->find_related('relname', @pri_vals | \%pri_vals);
229
230Attempt to find a related object using its primary key or unique constraints.
27f01d1f 231See L<DBIx::Class::ResultSet/find> for details.
503536d5 232
233=cut
234
1a14aa3f 235sub find_related {
236 my $self = shift;
237 my $rel = shift;
716b3d29 238 return $self->search_related($rel)->find(@_);
1a14aa3f 239}
240
8091aa91 241=head2 find_or_create_related
503536d5 242
30236e47 243 my $new_obj = $obj->find_or_create_related('relname', \%col_data);
244
27f01d1f 245Find or create an item of a related class. See
246L<DBIx::Class::ResultSet/"find_or_create"> for details.
503536d5 247
248=cut
249
55e2d745 250sub find_or_create_related {
251 my $self = shift;
1a14aa3f 252 return $self->find_related(@_) || $self->create_related(@_);
55e2d745 253}
254
8091aa91 255=head2 set_from_related
503536d5 256
30236e47 257 $book->set_from_related('author', $author_obj);
258
259Set column values on the current object, using related values from the given
260related object. This is used to associate previously separate objects, for
261example, to set the correct author for a book, find the Author object, then
262call set_from_related on the book.
263
27f01d1f 264The columns are only set in the local copy of the object, call L</update> to
265set them in the storage.
503536d5 266
267=cut
268
55e2d745 269sub set_from_related {
270 my ($self, $rel, $f_obj) = @_;
4685e006 271 my $rel_obj = $self->relationship_info($rel);
701da8c4 272 $self->throw_exception( "No such relationship ${rel}" ) unless $rel_obj;
55e2d745 273 my $cond = $rel_obj->{cond};
bc0c9800 274 $self->throw_exception(
275 "set_from_related can only handle a hash condition; the ".
276 "condition for $rel is of type ".
277 (ref $cond ? ref $cond : 'plain scalar')
278 ) unless ref $cond eq 'HASH';
7fb16f1a 279 my $f_class = $self->result_source->schema->class($rel_obj->{class});
701da8c4 280 $self->throw_exception( "Object $f_obj isn't a ".$f_class )
55e2d745 281 unless $f_obj->isa($f_class);
fde6e28e 282 $self->set_columns(
283 $self->result_source->resolve_condition(
284 $rel_obj->{cond}, $f_obj, $rel));
55e2d745 285 return 1;
286}
287
8091aa91 288=head2 update_from_related
503536d5 289
30236e47 290 $book->update_from_related('author', $author_obj);
291
27f01d1f 292The same as L</"set_from_related">, but the changes are immediately updated
293in storage.
503536d5 294
295=cut
296
55e2d745 297sub update_from_related {
298 my $self = shift;
299 $self->set_from_related(@_);
300 $self->update;
301}
302
8091aa91 303=head2 delete_related
503536d5 304
30236e47 305 $obj->delete_related('relname', $cond, $attrs);
306
307Delete any related item subject to the given conditions.
503536d5 308
309=cut
310
55e2d745 311sub delete_related {
312 my $self = shift;
64acc2bc 313 my $obj = $self->search_related(@_)->delete;
314 delete $self->{related_resultsets}->{$_[0]};
315 return $obj;
55e2d745 316}
317
3181;
319
55e2d745 320=head1 AUTHORS
321
daec44b8 322Matt S. Trout <mst@shadowcatsystems.co.uk>
55e2d745 323
324=head1 LICENSE
325
326You may distribute this code under the same terms as Perl itself.
327
328=cut
329