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