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