prevent objects implicitly passed via new_related having insertion cascaded to them...
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Row.pm
1 package DBIx::Class::Row;
2
3 use strict;
4 use warnings;
5
6 use base qw/DBIx::Class/;
7 use Carp::Clan qw/^DBIx::Class/;
8 use Scalar::Util ();
9 use Scope::Guard;
10
11 BEGIN {
12   *MULTICREATE_DEBUG =
13     $ENV{DBIC_MULTICREATE_DEBUG}
14       ? sub () { 1 }
15       : sub () { 0 };
16 }
17
18 __PACKAGE__->mk_group_accessors('simple' => qw/_source_handle/);
19
20 =head1 NAME
21
22 DBIx::Class::Row - Basic row methods
23
24 =head1 SYNOPSIS
25
26 =head1 DESCRIPTION
27
28 This class is responsible for defining and doing basic operations on rows
29 derived from L<DBIx::Class::ResultSource> objects.
30
31 Row objects are returned from L<DBIx::Class::ResultSet>s using the
32 L<create|DBIx::Class::ResultSet/create>, L<find|DBIx::Class::ResultSet/find>,
33 L<next|DBIx::Class::ResultSet/next> and L<all|DBIx::Class::ResultSet/all> methods,
34 as well as invocations of 'single' (
35 L<belongs_to|DBIx::Class::Relationship/belongs_to>,
36 L<has_one|DBIx::Class::Relationship/has_one> or
37 L<might_have|DBIx::Class::Relationship/might_have>)
38 relationship accessors of L<DBIx::Class::Row> objects.
39
40 =head1 METHODS
41
42 =head2 new
43
44   my $row = My::Class->new(\%attrs);
45
46   my $row = $schema->resultset('MySource')->new(\%colsandvalues);
47
48 =over
49
50 =item Arguments: \%attrs or \%colsandvalues
51
52 =item Returns: A Row object
53
54 =back
55
56 While you can create a new row object by calling C<new> directly on
57 this class, you are better off calling it on a
58 L<DBIx::Class::ResultSet> object.
59
60 When calling it directly, you will not get a complete, usable row
61 object until you pass or set the C<source_handle> attribute, to a
62 L<DBIx::Class::ResultSource> instance that is attached to a
63 L<DBIx::Class::Schema> with a valid connection.
64
65 C<$attrs> is a hashref of column name, value data. It can also contain
66 some other attributes such as the C<source_handle>.
67
68 Passing an object, or an arrayref of objects as a value will call
69 L<DBIx::Class::Relationship::Base/set_from_related> for you. When
70 passed a hashref or an arrayref of hashrefs as the value, these will
71 be turned into objects via new_related, and treated as if you had
72 passed objects.
73
74 For a more involved explanation, see L<DBIx::Class::ResultSet/create>.
75
76 =cut
77
78 ## It needs to store the new objects somewhere, and call insert on that list later when insert is called on this object. We may need an accessor for these so the user can retrieve them, if just doing ->new().
79 ## This only works because DBIC doesnt yet care to check whether the new_related objects have been passed all their mandatory columns
80 ## When doing the later insert, we need to make sure the PKs are set.
81 ## using _relationship_data in new and funky ways..
82 ## check Relationship::CascadeActions and Relationship::Accessor for compat
83 ## tests!
84
85 sub __new_related_find_or_new_helper {
86   my ($self, $relname, $data) = @_;
87   if ($self->__their_pk_needs_us($relname, $data)) {
88     return $self->result_source
89                 ->related_source($relname)
90                 ->resultset
91                 ->new_result($data);
92   }
93   if ($self->result_source->pk_depends_on($relname, $data)) {
94     return $self->result_source
95                 ->related_source($relname)
96                 ->resultset
97                 ->find_or_create($data);
98   }
99   return $self->find_or_new_related($relname, $data);
100 }
101
102 sub __their_pk_needs_us { # this should maybe be in resultsource.
103   my ($self, $relname, $data) = @_;
104   my $source = $self->result_source;
105   my $reverse = $source->reverse_relationship_info($relname);
106   my $rel_source = $source->related_source($relname);
107   my $us = { $self->get_columns };
108   foreach my $key (keys %$reverse) {
109     # if their primary key depends on us, then we have to
110     # just create a result and we'll fill it out afterwards
111     return 1 if $rel_source->pk_depends_on($key, $us);
112   }
113   return 0;
114 }
115
116 sub new {
117   my ($class, $attrs) = @_;
118   $class = ref $class if ref $class;
119
120   my $new = {
121       _column_data          => {},
122   };
123   bless $new, $class;
124
125   if (my $handle = delete $attrs->{-source_handle}) {
126     $new->_source_handle($handle);
127   }
128
129   my $source;
130   if ($source = delete $attrs->{-result_source}) {
131     $new->result_source($source);
132   }
133
134   if (my $related = delete $attrs->{-from_resultset}) {
135     @{$new->{_ignore_at_insert}={}}{@$related} = ();
136   }
137
138   if ($attrs) {
139     $new->throw_exception("attrs must be a hashref")
140       unless ref($attrs) eq 'HASH';
141     
142     my ($related,$inflated);
143     ## Pretend all the rels are actual objects, unset below if not, for insert() to fix
144     $new->{_rel_in_storage} = 1;
145
146     foreach my $key (keys %$attrs) {
147       if (ref $attrs->{$key}) {
148         ## Can we extract this lot to use with update(_or .. ) ?
149         confess "Can't do multi-create without result source" unless $source;
150         my $info = $source->relationship_info($key);
151         if ($info && $info->{attrs}{accessor}
152           && $info->{attrs}{accessor} eq 'single')
153         {
154           my $rel_obj = delete $attrs->{$key};
155           if(!Scalar::Util::blessed($rel_obj)) {
156             $rel_obj = $new->__new_related_find_or_new_helper($key, $rel_obj);
157           }
158
159           if ($rel_obj->in_storage) {
160             $new->set_from_related($key, $rel_obj);
161           } else {
162             $new->{_rel_in_storage} = 0;
163             MULTICREATE_DEBUG and warn "MC $new uninserted $key $rel_obj\n";
164           }
165
166           $related->{$key} = $rel_obj;
167           next;
168         } elsif ($info && $info->{attrs}{accessor}
169             && $info->{attrs}{accessor} eq 'multi'
170             && ref $attrs->{$key} eq 'ARRAY') {
171           my $others = delete $attrs->{$key};
172           my $total = @$others;
173           my @objects;
174           foreach my $idx (0 .. $#$others) {
175             my $rel_obj = $others->[$idx];
176             if(!Scalar::Util::blessed($rel_obj)) {
177               $rel_obj = $new->__new_related_find_or_new_helper($key, $rel_obj);
178             }
179
180             if ($rel_obj->in_storage) {
181               $new->set_from_related($key, $rel_obj);
182             } else {
183               $new->{_rel_in_storage} = 0;
184               MULTICREATE_DEBUG and
185                 warn "MC $new uninserted $key $rel_obj (${\($idx+1)} of $total)\n";
186             }
187             $new->set_from_related($key, $rel_obj) if $rel_obj->in_storage;
188             push(@objects, $rel_obj);
189           }
190           $related->{$key} = \@objects;
191           next;
192         } elsif ($info && $info->{attrs}{accessor}
193           && $info->{attrs}{accessor} eq 'filter')
194         {
195           ## 'filter' should disappear and get merged in with 'single' above!
196           my $rel_obj = delete $attrs->{$key};
197           if(!Scalar::Util::blessed($rel_obj)) {
198             $rel_obj = $new->__new_related_find_or_new_helper($key, $rel_obj);
199           }
200           unless ($rel_obj->in_storage) {
201             $new->{_rel_in_storage} = 0;
202             MULTICREATE_DEBUG and warn "MC $new uninserted $key $rel_obj";
203           }
204           $inflated->{$key} = $rel_obj;
205           next;
206         } elsif ($class->has_column($key)
207             && $class->column_info($key)->{_inflate_info}) {
208           $inflated->{$key} = $attrs->{$key};
209           next;
210         }
211       }
212       $new->throw_exception("No such column $key on $class")
213         unless $class->has_column($key);
214       $new->store_column($key => $attrs->{$key});          
215     }
216
217     $new->{_relationship_data} = $related if $related;
218     $new->{_inflated_column} = $inflated if $inflated;
219   }
220
221   return $new;
222 }
223
224 =head2 insert
225
226   $row->insert;
227
228 =over
229
230 =item Arguments: none
231
232 =item Returns: The Row object
233
234 =back
235
236 Inserts an object previously created by L</new> into the database if
237 it isn't already in there. Returns the object itself. Requires the
238 object's result source to be set, or the class to have a
239 result_source_instance method. To insert an entirely new row into
240 the database, use C<create> (see L<DBIx::Class::ResultSet/create>).
241
242 To fetch an uninserted row object, call
243 L<new|DBIx::Class::ResultSet/new> on a resultset.
244
245 This will also insert any uninserted, related objects held inside this
246 one, see L<DBIx::Class::ResultSet/create> for more details.
247
248 =cut
249
250 sub insert {
251   my ($self) = @_;
252   return $self if $self->in_storage;
253   my $source = $self->result_source;
254   $source ||=  $self->result_source($self->result_source_instance)
255     if $self->can('result_source_instance');
256   $self->throw_exception("No result_source set on this object; can't insert")
257     unless $source;
258
259   my $rollback_guard;
260
261   # Check if we stored uninserted relobjs here in new()
262   my %related_stuff = (%{$self->{_relationship_data} || {}}, 
263                        %{$self->{_inflated_column} || {}});
264
265   if(!$self->{_rel_in_storage}) {
266
267     # The guard will save us if we blow out of this scope via die
268     $rollback_guard = $source->storage->txn_scope_guard;
269
270     ## Should all be in relationship_data, but we need to get rid of the
271     ## 'filter' reltype..
272     ## These are the FK rels, need their IDs for the insert.
273
274     my @pri = $self->primary_columns;
275
276     REL: foreach my $relname (keys %related_stuff) {
277
278       my $rel_obj = $related_stuff{$relname};
279
280       next REL unless (Scalar::Util::blessed($rel_obj)
281                        && $rel_obj->isa('DBIx::Class::Row'));
282
283       next REL unless $source->pk_depends_on(
284                         $relname, { $rel_obj->get_columns }
285                       );
286
287       MULTICREATE_DEBUG and warn "MC $self pre-inserting $relname $rel_obj\n";
288
289       $rel_obj->insert();
290       $self->set_from_related($relname, $rel_obj);
291       delete $related_stuff{$relname};
292     }
293   }
294
295   MULTICREATE_DEBUG and do {
296     no warnings 'uninitialized';
297     warn "MC $self inserting (".join(', ', $self->get_columns).")\n";
298   };
299   my $updated_cols = $source->storage->insert($source, { $self->get_columns });
300   foreach my $col (keys %$updated_cols) {
301     $self->store_column($col, $updated_cols->{$col});
302   }
303
304   ## PK::Auto
305   my @auto_pri = grep {
306                    !defined $self->get_column($_) || 
307                    ref($self->get_column($_)) eq 'SCALAR'
308                  } $self->primary_columns;
309
310   if (@auto_pri) {
311     #$self->throw_exception( "More than one possible key found for auto-inc on ".ref $self )
312     #  if defined $too_many;
313     MULTICREATE_DEBUG and warn "MC $self fetching missing PKs ".join(', ', @auto_pri)."\n";
314     my $storage = $self->result_source->storage;
315     $self->throw_exception( "Missing primary key but Storage doesn't support last_insert_id" )
316       unless $storage->can('last_insert_id');
317     my @ids = $storage->last_insert_id($self->result_source,@auto_pri);
318     $self->throw_exception( "Can't get last insert id" )
319       unless (@ids == @auto_pri);
320     $self->store_column($auto_pri[$_] => $ids[$_]) for 0 .. $#ids;
321 #use Data::Dumper; warn Dumper($self);
322   }
323
324
325   $self->{_dirty_columns} = {};
326   $self->{related_resultsets} = {};
327
328   if(!$self->{_rel_in_storage}) {
329     ## Now do the relationships that need our ID (has_many etc.)
330     foreach my $relname (keys %related_stuff) {
331       my $rel_obj = $related_stuff{$relname};
332       my @cands;
333       if (Scalar::Util::blessed($rel_obj)
334           && $rel_obj->isa('DBIx::Class::Row')) {
335         @cands = ($rel_obj);
336       } elsif (ref $rel_obj eq 'ARRAY') {
337         @cands = @$rel_obj;
338       }
339       if (@cands) {
340         my $reverse = $source->reverse_relationship_info($relname);
341         foreach my $obj (@cands) {
342           $obj->set_from_related($_, $self) for keys %$reverse;
343           my $them = { %{$obj->{_relationship_data} || {} }, $obj->get_inflated_columns };
344           if ($self->__their_pk_needs_us($relname, $them)) {
345             if (exists $self->{_ignore_at_insert}{$relname}) {
346               MULTICREATE_DEBUG and warn "MC $self skipping post-insert on $relname";
347             } else {
348               MULTICREATE_DEBUG and warn "MC $self re-creating $relname $obj";
349               my $re = $self->find_or_create_related($relname, $them);
350               %{$obj} = %{$re};
351               MULTICREATE_DEBUG and warn "MC $self new $relname $obj";
352             }
353           } else {
354             MULTICREATE_DEBUG and warn "MC $self post-inserting $obj";
355             $obj->insert();
356           }
357         }
358       }
359     }
360     delete $self->{_ignore_at_insert};
361     $rollback_guard->commit;
362   }
363
364   $self->in_storage(1);
365   undef $self->{_orig_ident};
366   return $self;
367 }
368
369 =head2 in_storage
370
371   $row->in_storage; # Get value
372   $row->in_storage(1); # Set value
373
374 =over
375
376 =item Arguments: none or 1|0
377
378 =item Returns: 1|0
379
380 =back
381
382 Indicates whether the object exists as a row in the database or
383 not. This is set to true when L<DBIx::Class::ResultSet/find>,
384 L<DBIx::Class::ResultSet/create> or L<DBIx::Class::ResultSet/insert>
385 are used. 
386
387 Creating a row object using L<DBIx::Class::ResultSet/new>, or calling
388 L</delete> on one, sets it to false.
389
390 =cut
391
392 sub in_storage {
393   my ($self, $val) = @_;
394   $self->{_in_storage} = $val if @_ > 1;
395   return $self->{_in_storage};
396 }
397
398 =head2 update
399
400   $row->update(\%columns?)
401
402 =over
403
404 =item Arguments: none or a hashref
405
406 =item Returns: The Row object
407
408 =back
409
410 Throws an exception if the row object is not yet in the database,
411 according to L</in_storage>.
412
413 This method issues an SQL UPDATE query to commit any changes to the
414 object to the database if required.
415
416 Also takes an optional hashref of C<< column_name => value> >> pairs
417 to update on the object first. Be aware that the hashref will be
418 passed to C<set_inflated_columns>, which might edit it in place, so
419 don't rely on it being the same after a call to C<update>.  If you
420 need to preserve the hashref, it is sufficient to pass a shallow copy
421 to C<update>, e.g. ( { %{ $href } } )
422
423 If the values passed or any of the column values set on the object
424 contain scalar references, eg:
425
426   $row->last_modified(\'NOW()');
427   # OR
428   $row->update({ last_modified => \'NOW()' });
429
430 The update will pass the values verbatim into SQL. (See
431 L<SQL::Abstract> docs).  The values in your Row object will NOT change
432 as a result of the update call, if you want the object to be updated
433 with the actual values from the database, call L</discard_changes>
434 after the update.
435
436   $row->update()->discard_changes();
437
438 To determine before calling this method, which column values have
439 changed and will be updated, call L</get_dirty_columns>.
440
441 To check if any columns will be updated, call L</is_changed>.
442
443 To force a column to be updated, call L</make_column_dirty> before
444 this method.
445
446 =cut
447
448 sub update {
449   my ($self, $upd) = @_;
450   $self->throw_exception( "Not in database" ) unless $self->in_storage;
451   my $ident_cond = $self->ident_condition;
452   $self->throw_exception("Cannot safely update a row in a PK-less table")
453     if ! keys %$ident_cond;
454
455   $self->set_inflated_columns($upd) if $upd;
456   my %to_update = $self->get_dirty_columns;
457   return $self unless keys %to_update;
458   my $rows = $self->result_source->storage->update(
459                $self->result_source, \%to_update,
460                $self->{_orig_ident} || $ident_cond
461              );
462   if ($rows == 0) {
463     $self->throw_exception( "Can't update ${self}: row not found" );
464   } elsif ($rows > 1) {
465     $self->throw_exception("Can't update ${self}: updated more than one row");
466   }
467   $self->{_dirty_columns} = {};
468   $self->{related_resultsets} = {};
469   undef $self->{_orig_ident};
470   return $self;
471 }
472
473 =head2 delete
474
475   $row->delete
476
477 =over
478
479 =item Arguments: none
480
481 =item Returns: The Row object
482
483 =back
484
485 Throws an exception if the object is not in the database according to
486 L</in_storage>. Runs an SQL DELETE statement using the primary key
487 values to locate the row.
488
489 The object is still perfectly usable, but L</in_storage> will
490 now return 0 and the object must be reinserted using L</insert>
491 before it can be used to L</update> the row again. 
492
493 If you delete an object in a class with a C<has_many> relationship, an
494 attempt is made to delete all the related objects as well. To turn
495 this behaviour off, pass C<< cascade_delete => 0 >> in the C<$attr>
496 hashref of the relationship, see L<DBIx::Class::Relationship>. Any
497 database-level cascade or restrict will take precedence over a
498 DBIx-Class-based cascading delete. 
499
500 If you delete an object within a txn_do() (see L<DBIx::Class::Storage/txn_do>)
501 and the transaction subsequently fails, the row object will remain marked as
502 not being in storage. If you know for a fact that the object is still in
503 storage (i.e. by inspecting the cause of the transaction's failure), you can
504 use C<< $obj->in_storage(1) >> to restore consistency between the object and
505 the database. This would allow a subsequent C<< $obj->delete >> to work
506 as expected.
507
508 See also L<DBIx::Class::ResultSet/delete>.
509
510 =cut
511
512 sub delete {
513   my $self = shift;
514   if (ref $self) {
515     $self->throw_exception( "Not in database" ) unless $self->in_storage;
516     my $ident_cond = $self->{_orig_ident} || $self->ident_condition;
517     $self->throw_exception("Cannot safely delete a row in a PK-less table")
518       if ! keys %$ident_cond;
519     foreach my $column (keys %$ident_cond) {
520             $self->throw_exception("Can't delete the object unless it has loaded the primary keys")
521               unless exists $self->{_column_data}{$column};
522     }
523     $self->result_source->storage->delete(
524       $self->result_source, $ident_cond);
525     $self->in_storage(undef);
526   } else {
527     $self->throw_exception("Can't do class delete without a ResultSource instance")
528       unless $self->can('result_source_instance');
529     my $attrs = @_ > 1 && ref $_[$#_] eq 'HASH' ? { %{pop(@_)} } : {};
530     my $query = ref $_[0] eq 'HASH' ? $_[0] : {@_};
531     $self->result_source_instance->resultset->search(@_)->delete;
532   }
533   return $self;
534 }
535
536 =head2 get_column
537
538   my $val = $row->get_column($col);
539
540 =over
541
542 =item Arguments: $columnname
543
544 =item Returns: The value of the column
545
546 =back
547
548 Throws an exception if the column name given doesn't exist according
549 to L</has_column>.
550
551 Returns a raw column value from the row object, if it has already
552 been fetched from the database or set by an accessor.
553
554 If an L<inflated value|DBIx::Class::InflateColumn> has been set, it
555 will be deflated and returned.
556
557 Note that if you used the C<columns> or the C<select/as>
558 L<search attributes|DBIx::Class::ResultSet/ATTRIBUTES> on the resultset from
559 which C<$row> was derived, and B<did not include> C<$columnname> in the list,
560 this method will return C<undef> even if the database contains some value.
561
562 To retrieve all loaded column values as a hash, use L</get_columns>.
563
564 =cut
565
566 sub get_column {
567   my ($self, $column) = @_;
568   $self->throw_exception( "Can't fetch data as class method" ) unless ref $self;
569   return $self->{_column_data}{$column} if exists $self->{_column_data}{$column};
570   if (exists $self->{_inflated_column}{$column}) {
571     return $self->store_column($column,
572       $self->_deflated_column($column, $self->{_inflated_column}{$column}));   
573   }
574   $self->throw_exception( "No such column '${column}'" ) unless $self->has_column($column);
575   return undef;
576 }
577
578 =head2 has_column_loaded
579
580   if ( $row->has_column_loaded($col) ) {
581      print "$col has been loaded from db";
582   }
583
584 =over
585
586 =item Arguments: $columnname
587
588 =item Returns: 0|1
589
590 =back
591
592 Returns a true value if the column value has been loaded from the
593 database (or set locally).
594
595 =cut
596
597 sub has_column_loaded {
598   my ($self, $column) = @_;
599   $self->throw_exception( "Can't call has_column data as class method" ) unless ref $self;
600   return 1 if exists $self->{_inflated_column}{$column};
601   return exists $self->{_column_data}{$column};
602 }
603
604 =head2 get_columns
605
606   my %data = $row->get_columns;
607
608 =over
609
610 =item Arguments: none
611
612 =item Returns: A hash of columnname, value pairs.
613
614 =back
615
616 Returns all loaded column data as a hash, containing raw values. To
617 get just one value for a particular column, use L</get_column>.
618
619 =cut
620
621 sub get_columns {
622   my $self = shift;
623   if (exists $self->{_inflated_column}) {
624     foreach my $col (keys %{$self->{_inflated_column}}) {
625       $self->store_column($col, $self->_deflated_column($col, $self->{_inflated_column}{$col}))
626         unless exists $self->{_column_data}{$col};
627     }
628   }
629   return %{$self->{_column_data}};
630 }
631
632 =head2 get_dirty_columns
633
634   my %data = $row->get_dirty_columns;
635
636 =over
637
638 =item Arguments: none
639
640 =item Returns: A hash of column, value pairs
641
642 =back
643
644 Only returns the column, value pairs for those columns that have been
645 changed on this object since the last L</update> or L</insert> call.
646
647 See L</get_columns> to fetch all column/value pairs.
648
649 =cut
650
651 sub get_dirty_columns {
652   my $self = shift;
653   return map { $_ => $self->{_column_data}{$_} }
654            keys %{$self->{_dirty_columns}};
655 }
656
657 =head2 make_column_dirty
658
659   $row->make_column_dirty($col)
660
661 =over
662
663 =item Arguments: $columnname
664
665 =item Returns: undefined
666
667 =back
668
669 Throws an exception if the column does not exist.
670
671 Marks a column as having been changed regardless of whether it has
672 really changed.  
673
674 =cut
675 sub make_column_dirty {
676   my ($self, $column) = @_;
677
678   $self->throw_exception( "No such column '${column}'" )
679     unless exists $self->{_column_data}{$column} || $self->has_column($column);
680   $self->{_dirty_columns}{$column} = 1;
681 }
682
683 =head2 get_inflated_columns
684
685   my %inflated_data = $obj->get_inflated_columns;
686
687 =over
688
689 =item Arguments: none
690
691 =item Returns: A hash of column, object|value pairs
692
693 =back
694
695 Returns a hash of all column keys and associated values. Values for any
696 columns set to use inflation will be inflated and returns as objects.
697
698 See L</get_columns> to get the uninflated values.
699
700 See L<DBIx::Class::InflateColumn> for how to setup inflation.
701
702 =cut
703
704 sub get_inflated_columns {
705   my $self = shift;
706   return map {
707     my $accessor = $self->column_info($_)->{'accessor'} || $_;
708     ($_ => $self->$accessor);
709   } $self->columns;
710 }
711
712 =head2 set_column
713
714   $row->set_column($col => $val);
715
716 =over
717
718 =item Arguments: $columnname, $value
719
720 =item Returns: $value
721
722 =back
723
724 Sets a raw column value. If the new value is different from the old one,
725 the column is marked as dirty for when you next call L</update>.
726
727 If passed an object or reference as a value, this method will happily
728 attempt to store it, and a later L</insert> or L</update> will try and
729 stringify/numify as appropriate. To set an object to be deflated
730 instead, see L</set_inflated_columns>.
731
732 =cut
733
734 sub set_column {
735   my ($self, $column, $new_value) = @_;
736
737   $self->{_orig_ident} ||= $self->ident_condition;
738   my $old_value = $self->get_column($column);
739
740   $self->store_column($column, $new_value);
741   $self->{_dirty_columns}{$column} = 1
742     if (defined $old_value xor defined $new_value) || (defined $old_value && $old_value ne $new_value);
743
744   # XXX clear out the relation cache for this column
745   delete $self->{related_resultsets}{$column};
746
747   return $new_value;
748 }
749
750 =head2 set_columns
751
752   $row->set_columns({ $col => $val, ... });
753
754 =over 
755
756 =item Arguments: \%columndata
757
758 =item Returns: The Row object
759
760 =back
761
762 Sets multiple column, raw value pairs at once.
763
764 Works as L</set_column>.
765
766 =cut
767
768 sub set_columns {
769   my ($self,$data) = @_;
770   foreach my $col (keys %$data) {
771     $self->set_column($col,$data->{$col});
772   }
773   return $self;
774 }
775
776 =head2 set_inflated_columns
777
778   $row->set_inflated_columns({ $col => $val, $relname => $obj, ... });
779
780 =over
781
782 =item Arguments: \%columndata
783
784 =item Returns: The Row object
785
786 =back
787
788 Sets more than one column value at once. Any inflated values are
789 deflated and the raw values stored. 
790
791 Any related values passed as Row objects, using the relation name as a
792 key, are reduced to the appropriate foreign key values and stored. If
793 instead of related row objects, a hashref of column, value data is
794 passed, will create the related object first then store.
795
796 Will even accept arrayrefs of data as a value to a
797 L<DBIx::Class::Relationship/has_many> key, and create the related
798 objects if necessary.
799
800 Be aware that the input hashref might be edited in place, so dont rely
801 on it being the same after a call to C<set_inflated_columns>. If you
802 need to preserve the hashref, it is sufficient to pass a shallow copy
803 to C<set_inflated_columns>, e.g. ( { %{ $href } } )
804
805 See also L<DBIx::Class::Relationship::Base/set_from_related>.
806
807 =cut
808
809 sub set_inflated_columns {
810   my ( $self, $upd ) = @_;
811   foreach my $key (keys %$upd) {
812     if (ref $upd->{$key}) {
813       my $info = $self->relationship_info($key);
814       if ($info && $info->{attrs}{accessor}
815         && $info->{attrs}{accessor} eq 'single')
816       {
817         my $rel = delete $upd->{$key};
818         $self->set_from_related($key => $rel);
819         $self->{_relationship_data}{$key} = $rel;
820       } elsif ($info && $info->{attrs}{accessor}
821         && $info->{attrs}{accessor} eq 'multi') {
822           $self->throw_exception(
823             "Recursive update is not supported over relationships of type multi ($key)"
824           );
825       }
826       elsif ($self->has_column($key)
827         && exists $self->column_info($key)->{_inflate_info})
828       {
829         $self->set_inflated_column($key, delete $upd->{$key});
830       }
831     }
832   }
833   $self->set_columns($upd);    
834 }
835
836 =head2 copy
837
838   my $copy = $orig->copy({ change => $to, ... });
839
840 =over
841
842 =item Arguments: \%replacementdata
843
844 =item Returns: The Row object copy
845
846 =back
847
848 Inserts a new row into the database, as a copy of the original
849 object. If a hashref of replacement data is supplied, these will take
850 precedence over data in the original.
851
852 If the row has related objects in a
853 L<DBIx::Class::Relationship/has_many> then those objects may be copied
854 too depending on the L<cascade_copy|DBIx::Class::Relationship>
855 relationship attribute.
856
857 =cut
858
859 sub copy {
860   my ($self, $changes) = @_;
861   $changes ||= {};
862   my $col_data = { %{$self->{_column_data}} };
863   foreach my $col (keys %$col_data) {
864     delete $col_data->{$col}
865       if $self->result_source->column_info($col)->{is_auto_increment};
866   }
867
868   my $new = { _column_data => $col_data };
869   bless $new, ref $self;
870
871   $new->result_source($self->result_source);
872   $new->set_inflated_columns($changes);
873   $new->insert;
874
875   # Its possible we'll have 2 relations to the same Source. We need to make 
876   # sure we don't try to insert the same row twice esle we'll violate unique
877   # constraints
878   my $rels_copied = {};
879
880   foreach my $rel ($self->result_source->relationships) {
881     my $rel_info = $self->result_source->relationship_info($rel);
882
883     next unless $rel_info->{attrs}{cascade_copy};
884   
885     my $resolved = $self->result_source->resolve_condition(
886       $rel_info->{cond}, $rel, $new
887     );
888
889     my $copied = $rels_copied->{ $rel_info->{source} } ||= {};
890     foreach my $related ($self->search_related($rel)) {
891       my $id_str = join("\0", $related->id);
892       next if $copied->{$id_str};
893       $copied->{$id_str} = 1;
894       my $rel_copy = $related->copy($resolved);
895     }
896  
897   }
898   return $new;
899 }
900
901 =head2 store_column
902
903   $row->store_column($col => $val);
904
905 =over
906
907 =item Arguments: $columnname, $value
908
909 =item Returns: The value sent to storage
910
911 =back
912
913 Set a raw value for a column without marking it as changed. This
914 method is used internally by L</set_column> which you should probably
915 be using.
916
917 This is the lowest level at which data is set on a row object,
918 extend this method to catch all data setting methods.
919
920 =cut
921
922 sub store_column {
923   my ($self, $column, $value) = @_;
924   $self->throw_exception( "No such column '${column}'" )
925     unless exists $self->{_column_data}{$column} || $self->has_column($column);
926   $self->throw_exception( "set_column called for ${column} without value" )
927     if @_ < 3;
928   return $self->{_column_data}{$column} = $value;
929 }
930
931 =head2 inflate_result
932
933   Class->inflate_result($result_source, \%me, \%prefetch?)
934
935 =over
936
937 =item Arguments: $result_source, \%columndata, \%prefetcheddata
938
939 =item Returns: A Row object
940
941 =back
942
943 All L<DBIx::Class::ResultSet> methods that retrieve data from the
944 database and turn it into row objects call this method.
945
946 Extend this method in your Result classes to hook into this process,
947 for example to rebless the result into a different class.
948
949 Reblessing can also be done more easily by setting C<result_class> in
950 your Result class. See L<DBIx::Class::ResultSource/result_class>.
951
952 =cut
953
954 sub inflate_result {
955   my ($class, $source, $me, $prefetch) = @_;
956
957   my ($source_handle) = $source;
958
959   if ($source->isa('DBIx::Class::ResultSourceHandle')) {
960       $source = $source_handle->resolve
961   } else {
962       $source_handle = $source->handle
963   }
964
965   my $new = {
966     _source_handle => $source_handle,
967     _column_data => $me,
968     _in_storage => 1
969   };
970   bless $new, (ref $class || $class);
971
972   my $schema;
973   foreach my $pre (keys %{$prefetch||{}}) {
974     my $pre_val = $prefetch->{$pre};
975     my $pre_source = $source->related_source($pre);
976     $class->throw_exception("Can't prefetch non-existent relationship ${pre}")
977       unless $pre_source;
978     if (ref($pre_val->[0]) eq 'ARRAY') { # multi
979       my @pre_objects;
980       foreach my $pre_rec (@$pre_val) {
981         unless ($pre_source->primary_columns == grep { exists $pre_rec->[0]{$_}
982            and defined $pre_rec->[0]{$_} } $pre_source->primary_columns) {
983           next;
984         }
985         push(@pre_objects, $pre_source->result_class->inflate_result(
986                              $pre_source, @{$pre_rec}));
987       }
988       $new->related_resultset($pre)->set_cache(\@pre_objects);
989     } elsif (defined $pre_val->[0]) {
990       my $fetched;
991       unless ($pre_source->primary_columns == grep { exists $pre_val->[0]{$_}
992          and !defined $pre_val->[0]{$_} } $pre_source->primary_columns)
993       {
994         $fetched = $pre_source->result_class->inflate_result(
995                       $pre_source, @{$pre_val});
996       }
997       $new->related_resultset($pre)->set_cache([ $fetched ]);
998       my $accessor = $source->relationship_info($pre)->{attrs}{accessor};
999       $class->throw_exception("No accessor for prefetched $pre")
1000        unless defined $accessor;
1001       if ($accessor eq 'single') {
1002         $new->{_relationship_data}{$pre} = $fetched;
1003       } elsif ($accessor eq 'filter') {
1004         $new->{_inflated_column}{$pre} = $fetched;
1005       } else {
1006        $class->throw_exception("Prefetch not supported with accessor '$accessor'");
1007       }
1008     }
1009   }
1010   return $new;
1011 }
1012
1013 =head2 update_or_insert
1014
1015   $row->update_or_insert
1016
1017 =over
1018
1019 =item Arguments: none
1020
1021 =item Returns: Result of update or insert operation
1022
1023 =back
1024
1025 L</Update>s the object if it's already in the database, according to
1026 L</in_storage>, else L</insert>s it.
1027
1028 =head2 insert_or_update
1029
1030   $obj->insert_or_update
1031
1032 Alias for L</update_or_insert>
1033
1034 =cut
1035
1036 sub insert_or_update { shift->update_or_insert(@_) }
1037
1038 sub update_or_insert {
1039   my $self = shift;
1040   return ($self->in_storage ? $self->update : $self->insert);
1041 }
1042
1043 =head2 is_changed
1044
1045   my @changed_col_names = $row->is_changed();
1046   if ($row->is_changed()) { ... }
1047
1048 =over
1049
1050 =item Arguments: none
1051
1052 =item Returns: 0|1 or @columnnames
1053
1054 =back
1055
1056 In list context returns a list of columns with uncommited changes, or
1057 in scalar context returns a true value if there are uncommitted
1058 changes.
1059
1060 =cut
1061
1062 sub is_changed {
1063   return keys %{shift->{_dirty_columns} || {}};
1064 }
1065
1066 =head2 is_column_changed
1067
1068   if ($row->is_column_changed('col')) { ... }
1069
1070 =over
1071
1072 =item Arguments: $columname
1073
1074 =item Returns: 0|1
1075
1076 =back
1077
1078 Returns a true value if the column has uncommitted changes.
1079
1080 =cut
1081
1082 sub is_column_changed {
1083   my( $self, $col ) = @_;
1084   return exists $self->{_dirty_columns}->{$col};
1085 }
1086
1087 =head2 result_source
1088
1089   my $resultsource = $row->result_source;
1090
1091 =over
1092
1093 =item Arguments: none
1094
1095 =item Returns: a ResultSource instance
1096
1097 =back
1098
1099 Accessor to the L<DBIx::Class::ResultSource> this object was created from.
1100
1101 =cut
1102
1103 sub result_source {
1104     my $self = shift;
1105
1106     if (@_) {
1107         $self->_source_handle($_[0]->handle);
1108     } else {
1109         $self->_source_handle->resolve;
1110     }
1111 }
1112
1113 =head2 register_column
1114
1115   $column_info = { .... };
1116   $class->register_column($column_name, $column_info);
1117
1118 =over
1119
1120 =item Arguments: $columnname, \%columninfo
1121
1122 =item Returns: undefined
1123
1124 =back
1125
1126 Registers a column on the class. If the column_info has an 'accessor'
1127 key, creates an accessor named after the value if defined; if there is
1128 no such key, creates an accessor with the same name as the column
1129
1130 The column_info attributes are described in
1131 L<DBIx::Class::ResultSource/add_columns>
1132
1133 =cut
1134
1135 sub register_column {
1136   my ($class, $col, $info) = @_;
1137   my $acc = $col;
1138   if (exists $info->{accessor}) {
1139     return unless defined $info->{accessor};
1140     $acc = [ $info->{accessor}, $col ];
1141   }
1142   $class->mk_group_accessors('column' => $acc);
1143 }
1144
1145 =head2 get_from_storage
1146
1147   my $copy = $row->get_from_storage($attrs)
1148
1149 =over
1150
1151 =item Arguments: \%attrs
1152
1153 =item Returns: A Row object
1154
1155 =back
1156
1157 Fetches a fresh copy of the Row object from the database and returns it.
1158
1159 If passed the \%attrs argument, will first apply these attributes to
1160 the resultset used to find the row.
1161
1162 This copy can then be used to compare to an existing row object, to
1163 determine if any changes have been made in the database since it was
1164 created.
1165
1166 To just update your Row object with any latest changes from the
1167 database, use L</discard_changes> instead.
1168
1169 The \%attrs argument should be compatible with
1170 L<DBIx::Class::ResultSet/ATTRIBUTES>.
1171
1172 =cut
1173
1174 sub get_from_storage {
1175     my $self = shift @_;
1176     my $attrs = shift @_;
1177     my $resultset = $self->result_source->resultset;
1178     
1179     if(defined $attrs) {
1180         $resultset = $resultset->search(undef, $attrs);
1181     }
1182     
1183     return $resultset->find($self->{_orig_ident} || $self->ident_condition);
1184 }
1185
1186 =head2 throw_exception
1187
1188 See L<DBIx::Class::Schema/throw_exception>.
1189
1190 =cut
1191
1192 sub throw_exception {
1193   my $self=shift;
1194   if (ref $self && ref $self->result_source && $self->result_source->schema) {
1195     $self->result_source->schema->throw_exception(@_);
1196   } else {
1197     croak(@_);
1198   }
1199 }
1200
1201 =head2 id
1202
1203   my @pk = $row->id;
1204
1205 =over
1206
1207 =item Arguments: none
1208
1209 =item Returns: A list of primary key values
1210
1211 =back
1212
1213 Returns the primary key(s) for a row. Can't be called as a class method.
1214 Actually implemented in L<DBIx::Class::PK>
1215
1216 =head2 discard_changes
1217
1218   $row->discard_changes
1219
1220 =over
1221
1222 =item Arguments: none
1223
1224 =item Returns: nothing (updates object in-place)
1225
1226 =back
1227
1228 Retrieves and sets the row object data from the database, losing any
1229 local changes made.
1230
1231 This method can also be used to refresh from storage, retrieving any
1232 changes made since the row was last read from storage. Actually
1233 implemented in L<DBIx::Class::PK>
1234
1235 =cut
1236
1237 1;
1238
1239 =head1 AUTHORS
1240
1241 Matt S. Trout <mst@shadowcatsystems.co.uk>
1242
1243 =head1 LICENSE
1244
1245 You may distribute this code under the same terms as Perl itself.
1246
1247 =cut