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