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