Crazy ass multi create fixes..
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Relationship / Base.pm
1 package DBIx::Class::Relationship::Base;
2
3 use strict;
4 use warnings;
5
6 use Scalar::Util ();
7 use base qw/DBIx::Class/;
8
9 =head1 NAME
10
11 DBIx::Class::Relationship::Base - Inter-table relationships
12
13 =head1 SYNOPSIS
14
15 =head1 DESCRIPTION
16
17 This class provides methods to describe the relationships between the
18 tables in your database model. These are the "bare bones" relationships
19 methods, for predefined ones, look in L<DBIx::Class::Relationship>.
20
21 =head1 METHODS
22
23 =head2 add_relationship
24
25 =over 4
26
27 =item Arguments: 'relname', 'Foreign::Class', $cond, $attrs
28
29 =back
30
31   __PACKAGE__->add_relationship('relname', 'Foreign::Class', $cond, $attrs);
32
33 The condition needs to be an L<SQL::Abstract>-style representation of the
34 join between the tables. When resolving the condition for use in a C<JOIN>,
35 keys using the pseudo-table C<foreign> are resolved to mean "the Table on the
36 other side of the relationship", and values using the pseudo-table C<self>
37 are resolved to mean "the Table this class is representing". Other
38 restrictions, such as by value, sub-select and other tables, may also be
39 used. Please check your database for C<JOIN> parameter support.
40
41 For example, if you're creating a relationship from C<Author> to C<Book>, where
42 the C<Book> table has a column C<author_id> containing the ID of the C<Author>
43 row:
44
45   { 'foreign.author_id' => 'self.id' }
46
47 will result in the C<JOIN> clause
48
49   author me JOIN book book ON book.author_id = me.id
50
51 For multi-column foreign keys, you will need to specify a C<foreign>-to-C<self>
52 mapping for each column in the key. For example, if you're creating a
53 relationship from C<Book> to C<Edition>, where the C<Edition> table refers to a
54 publisher and a type (e.g. "paperback"):
55
56   {
57     'foreign.publisher_id' => 'self.publisher_id',
58     'foreign.type_id'      => 'self.type_id',
59   }
60
61 This 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
66 Each key-value pair provided in a hashref will be used as C<AND>ed conditions.
67 To add an C<OR>ed condition, use an arrayref of hashrefs. See the
68 L<SQL::Abstract> documentation for more details.
69
70 In addition to the
71 L<standard ResultSet attributes|DBIx::Class::ResultSet/ATTRIBUTES>,
72 the following attributes are also valid:
73
74 =over 4
75
76 =item join_type
77
78 Explicitly specifies the type of join to use in the relationship. Any SQL
79 join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in the SQL
80 command immediately before C<JOIN>.
81
82 =item proxy
83
84 An arrayref containing a list of accessors in the foreign class to create in
85 the main class. If, for example, you do the following:
86   
87   MyDB::Schema::CD->might_have(liner_notes => 'MyDB::Schema::LinerNotes',
88     undef, {
89       proxy => [ qw/notes/ ],
90     });
91   
92 Then, assuming MyDB::Schema::LinerNotes has an accessor named notes, you can do:
93
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
97   
98 =item accessor
99
100 Specifies the type of accessor that should be created for the relationship.
101 Valid values are C<single> (for when there is only a single related object),
102 C<multi> (when there can be many), and C<filter> (for when there is a single
103 related object, but you also want the relationship accessor to double as
104 a column accessor). For C<multi> accessors, an add_to_* method is also
105 created, which calls C<create_related> for the relationship.
106
107 =item is_foreign_key_constraint
108
109 If you are using L<SQL::Translator> to create SQL for you and you find that it
110 is creating constraints where it shouldn't, or not creating them where it 
111 should, set this attribute to a true or false value to override the detection
112 of when to create constraints.
113
114 =item on_delete / on_update
115
116 If you are using L<SQL::Translator> to create SQL for you, you can use these
117 attributes to explicitly set the desired C<ON DELETE> or C<ON UPDATE> constraint 
118 type. If not supplied the SQLT parser will attempt to infer the constraint type by 
119 interrogating the attributes of the B<opposite> relationship. For any 'multi'
120 relationship with C<< cascade_delete => 1 >>, the corresponding belongs_to 
121 relationship will be created with an C<ON DELETE CASCADE> constraint. For any 
122 relationship bearing C<< cascade_copy => 1 >> the resulting belongs_to constraint
123 will be C<ON UPDATE CASCADE>. If you wish to disable this autodetection, and just
124 use the RDBMS' default constraint type, pass C<< on_delete => undef >> or 
125 C<< on_delete => '' >>, and the same for C<on_update> respectively.
126
127 =item is_deferrable
128
129 Tells L<SQL::Translator> that the foreign key constraint it creates should be
130 deferrable. In other words, the user may request that the constraint be ignored
131 until the end of the transaction. Currently, only the PostgreSQL producer
132 actually supports this.
133
134 =item add_fk_index
135
136 Tells L<SQL::Translator> to add an index for this constraint. Can also be
137 specified globally in the args to L<DBIx::Class::Schema/deploy> or
138 L<DBIx::Class::Schema/create_ddl_dir>. Default is on, set to 0 to disable.
139
140 =back
141
142 =head2 register_relationship
143
144 =over 4
145
146 =item Arguments: $relname, $rel_info
147
148 =back
149
150 Registers a relationship on the class. This is called internally by
151 DBIx::Class::ResultSourceProxy to set up Accessors and Proxies.
152
153 =cut
154
155 sub register_relationship { }
156
157 =head2 related_resultset
158
159 =over 4
160
161 =item Arguments: $relationship_name
162
163 =item Return Value: $related_resultset
164
165 =back
166
167   $rs = $cd->related_resultset('artist');
168
169 Returns a L<DBIx::Class::ResultSet> for the relationship named
170 $relationship_name.
171
172 =cut
173
174 sub related_resultset {
175   my $self = shift;
176   $self->throw_exception("Can't call *_related as class methods")
177     unless ref $self;
178   my $rel = shift;
179   my $rel_obj = $self->relationship_info($rel);
180   $self->throw_exception( "No such relationship ${rel}" )
181     unless $rel_obj;
182   
183   return $self->{related_resultsets}{$rel} ||= do {
184     my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
185     $attrs = { %{$rel_obj->{attrs} || {}}, %$attrs };
186
187     $self->throw_exception( "Invalid query: @_" )
188       if (@_ > 1 && (@_ % 2 == 1));
189     my $query = ((@_ > 1) ? {@_} : shift);
190
191     my $source = $self->result_source;
192     my $cond = $source->resolve_condition(
193       $rel_obj->{cond}, $rel, $self
194     );
195     if ($cond eq $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION) {
196       my $reverse = $source->reverse_relationship_info($rel);
197       foreach my $rev_rel (keys %$reverse) {
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         }
205       }
206     }
207     if (ref $cond eq 'ARRAY') {
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 ];
220     } elsif (ref $cond eq 'HASH') {
221       foreach my $key (grep { ! /\./ } keys %$cond) {
222         $cond->{"me.$key"} = delete $cond->{$key};
223       }
224     }
225     $query = ($query ? { '-and' => [ $cond, $query ] } : $cond);
226     $self->result_source->related_source($rel)->resultset->search(
227       $query, $attrs
228     );
229   };
230 }
231
232 =head2 search_related
233
234   @objects = $rs->search_related('relname', $cond, $attrs);
235   $objects_rs = $rs->search_related('relname', $cond, $attrs);
236
237 Run a search on a related resultset. The search will be restricted to the
238 item or items represented by the L<DBIx::Class::ResultSet> it was called
239 upon. This method can be called on a ResultSet, a Row or a ResultSource class.
240
241 =cut
242
243 sub search_related {
244   return shift->related_resultset(shift)->search(@_);
245 }
246
247 =head2 search_related_rs
248
249   ( $objects_rs ) = $rs->search_related_rs('relname', $cond, $attrs);
250
251 This method works exactly the same as search_related, except that 
252 it guarantees a restultset, even in list context.
253
254 =cut
255
256 sub search_related_rs {
257   return shift->related_resultset(shift)->search_rs(@_);
258 }
259
260 =head2 count_related
261
262   $obj->count_related('relname', $cond, $attrs);
263
264 Returns the count of all the items in the related resultset, restricted by the
265 current item or where conditions. Can be called on a
266 L<DBIx::Class::Manual::Glossary/"ResultSet"> or a
267 L<DBIx::Class::Manual::Glossary/"Row"> object.
268
269 =cut
270
271 sub count_related {
272   my $self = shift;
273   return $self->search_related(@_)->count;
274 }
275
276 =head2 new_related
277
278   my $new_obj = $obj->new_related('relname', \%col_data);
279
280 Create a new item of the related foreign class. If called on a
281 L<Row|DBIx::Class::Manual::Glossary/"Row"> object, it will magically 
282 set any foreign key columns of the new object to the related primary 
283 key columns of the source object for you.  The newly created item will 
284 not be saved into your storage until you call L<DBIx::Class::Row/insert>
285 on it.
286
287 =cut
288
289 sub new_related {
290   my ($self, $rel, $values, $attrs) = @_;
291   return $self->search_related($rel)->new($values, $attrs);
292 }
293
294 =head2 create_related
295
296   my $new_obj = $obj->create_related('relname', \%col_data);
297
298 Creates a new item, similarly to new_related, and also inserts the item's data
299 into your storage medium. See the distinction between C<create> and C<new>
300 in L<DBIx::Class::ResultSet> for details.
301
302 =cut
303
304 sub create_related {
305   my $self = shift;
306   my $rel = shift;
307   my $obj = $self->search_related($rel)->create(@_);
308   delete $self->{related_resultsets}->{$rel};
309   return $obj;
310 }
311
312 =head2 find_related
313
314   my $found_item = $obj->find_related('relname', @pri_vals | \%pri_vals);
315
316 Attempt to find a related object using its primary key or unique constraints.
317 See L<DBIx::Class::ResultSet/find> for details.
318
319 =cut
320
321 sub find_related {
322   my $self = shift;
323   my $rel = shift;
324   return $self->search_related($rel)->find(@_);
325 }
326
327 =head2 find_or_new_related
328
329   my $new_obj = $obj->find_or_new_related('relname', \%col_data);
330
331 Find an item of a related class. If none exists, instantiate a new item of the
332 related class. The object will not be saved into your storage until you call
333 L<DBIx::Class::Row/insert> on it.
334
335 =cut
336
337 sub find_or_new_related {
338   my $self = shift;
339   my $obj = $self->find_related(@_);
340   return defined $obj ? $obj : $self->new_related(@_);
341 }
342
343 =head2 find_or_create_related
344
345   my $new_obj = $obj->find_or_create_related('relname', \%col_data);
346
347 Find or create an item of a related class. See
348 L<DBIx::Class::ResultSet/find_or_create> for details.
349
350 =cut
351
352 sub find_or_create_related {
353   my $self = shift;
354   my $obj = $self->find_related(@_);
355   return (defined($obj) ? $obj : $self->create_related(@_));
356 }
357
358 =head2 update_or_create_related
359
360   my $updated_item = $obj->update_or_create_related('relname', \%col_data, \%attrs?);
361
362 Update or create an item of a related class. See
363 L<DBIx::Class::ResultSet/update_or_create> for details.
364
365 =cut
366
367 sub update_or_create_related {
368   my $self = shift;
369   my $rel = shift;
370   return $self->related_resultset($rel)->update_or_create(@_);
371 }
372
373 =head2 set_from_related
374
375   $book->set_from_related('author', $author_obj);
376   $book->author($author_obj);                      ## same thing
377
378 Set column values on the current object, using related values from the given
379 related object. This is used to associate previously separate objects, for
380 example, to set the correct author for a book, find the Author object, then
381 call set_from_related on the book.
382
383 This is called internally when you pass existing objects as values to
384 L<DBIx::Class::ResultSet/create>, or pass an object to a belongs_to acessor.
385
386 The columns are only set in the local copy of the object, call L</update> to
387 set them in the storage.
388
389 =cut
390
391 sub set_from_related {
392   my ($self, $rel, $f_obj) = @_;
393   my $rel_obj = $self->relationship_info($rel);
394   $self->throw_exception( "No such relationship ${rel}" ) unless $rel_obj;
395   my $cond = $rel_obj->{cond};
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';
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 )
404       unless Scalar::Util::blessed($f_obj) and $f_obj->isa($f_class);
405   }
406 #  print STDERR "set_from_related: ", $rel, Data::Dumper::Dumper({$f_obj->get_columns});
407   $self->set_columns(
408     $self->result_source->resolve_condition(
409        $rel_obj->{cond}, $f_obj, $rel));
410 #  print STDERR "set_: ", Data::Dumper::Dumper({$self->get_columns});
411   return 1;
412 }
413
414 =head2 update_from_related
415
416   $book->update_from_related('author', $author_obj);
417
418 The same as L</"set_from_related">, but the changes are immediately updated
419 in storage.
420
421 =cut
422
423 sub update_from_related {
424   my $self = shift;
425   $self->set_from_related(@_);
426   $self->update;
427 }
428
429 =head2 delete_related
430
431   $obj->delete_related('relname', $cond, $attrs);
432
433 Delete any related item subject to the given conditions.
434
435 =cut
436
437 sub delete_related {
438   my $self = shift;
439   my $obj = $self->search_related(@_)->delete;
440   delete $self->{related_resultsets}->{$_[0]};
441   return $obj;
442 }
443
444 =head2 add_to_$rel
445
446 B<Currently only available for C<has_many>, C<many-to-many> and 'multi' type
447 relationships.>
448
449 =over 4
450
451 =item Arguments: ($foreign_vals | $obj), $link_vals?
452
453 =back
454
455   my $role = $schema->resultset('Role')->find(1);
456   $actor->add_to_roles($role);
457       # creates a My::DBIC::Schema::ActorRoles linking table row object
458
459   $actor->add_to_roles({ name => 'lead' }, { salary => 15_000_000 });
460       # creates a new My::DBIC::Schema::Role row object and the linking table
461       # object with an extra column in the link
462
463 Adds a linking table object for C<$obj> or C<$foreign_vals>. If the first
464 argument is a hash reference, the related object is created first with the
465 column values in the hash. If an object reference is given, just the linking
466 table object is created. In either case, any additional column values for the
467 linking table object can be specified in C<$link_vals>.
468
469 =head2 set_$rel
470
471 B<Currently only available for C<many-to-many> relationships.>
472
473 =over 4
474
475 =item Arguments: (\@hashrefs | \@objs)
476
477 =back
478
479   my $actor = $schema->resultset('Actor')->find(1);
480   my @roles = $schema->resultset('Role')->search({ role => 
481      { '-in' => ['Fred', 'Barney'] } } );
482
483   $actor->set_roles(\@roles);
484      # Replaces all of $actor's previous roles with the two named
485
486 Replace all the related objects with the given reference to a list of
487 objects. This does a C<delete> B<on the link table resultset> to remove the
488 association between the current object and all related objects, then calls
489 C<add_to_$rel> repeatedly to link all the new objects.
490
491 Note that this means that this method will B<not> delete any objects in the
492 table on the right side of the relation, merely that it will delete the link
493 between them.
494
495 Due to a mistake in the original implementation of this method, it will also
496 accept a list of objects or hash references. This is B<deprecated> and will be
497 removed in a future version.
498
499 =head2 remove_from_$rel
500
501 B<Currently only available for C<many-to-many> relationships.>
502
503 =over 4
504
505 =item Arguments: $obj
506
507 =back
508
509   my $role = $schema->resultset('Role')->find(1);
510   $actor->remove_from_roles($role);
511       # removes $role's My::DBIC::Schema::ActorRoles linking table row object
512
513 Removes the link between the current object and the related object. Note that
514 the related object itself won't be deleted unless you call ->delete() on
515 it. This method just removes the link between the two objects.
516
517 =head1 AUTHORS
518
519 Matt S. Trout <mst@shadowcatsystems.co.uk>
520
521 =head1 LICENSE
522
523 You may distribute this code under the same terms as Perl itself.
524
525 =cut
526
527 1;