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