Fix incorrect warning/exception originator
[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/;
1a58752c 7
6298a324 8use Scalar::Util 'blessed';
5ef76b8b 9use List::Util 'first';
9780718f 10use Try::Tiny;
1edd1722 11
0d5d1f12 12###
13### Internal method
14### Do not use
15###
e0cdf2cb 16BEGIN {
17 *MULTICREATE_DEBUG =
18 $ENV{DBIC_MULTICREATE_DEBUG}
19 ? sub () { 1 }
20 : sub () { 0 };
21}
22
9c1700e3 23use namespace::clean;
8c49f629 24
75d07914 25=head1 NAME
7624b19f 26
27DBIx::Class::Row - Basic row methods
28
29=head1 SYNOPSIS
30
31=head1 DESCRIPTION
32
33This class is responsible for defining and doing basic operations on rows
1ea77c14 34derived from L<DBIx::Class::ResultSource> objects.
7624b19f 35
fb13a49f 36Result objects are returned from L<DBIx::Class::ResultSet>s using the
ea36f4e4 37L<create|DBIx::Class::ResultSet/create>, L<find|DBIx::Class::ResultSet/find>,
38L<next|DBIx::Class::ResultSet/next> and L<all|DBIx::Class::ResultSet/all> methods,
39as well as invocations of 'single' (
40L<belongs_to|DBIx::Class::Relationship/belongs_to>,
41L<has_one|DBIx::Class::Relationship/has_one> or
42L<might_have|DBIx::Class::Relationship/might_have>)
fb13a49f 43relationship accessors of L<Result|DBIx::Class::Manual::ResultClass> objects.
a2531bf2 44
93711422 45=head1 NOTE
46
47All "Row objects" derived from a Schema-attached L<DBIx::Class::ResultSet>
48object (such as a typical C<< L<search|DBIx::Class::ResultSet/search
49>->L<next|DBIx::Class::ResultSet/next> >> call) are actually Result
50instances, based on your application's
51L<Result class|DBIx::Class::Manual::Glossary/Result_class>.
52
53L<DBIx::Class::Row> implements most of the row-based communication with the
54underlying storage, but a Result class B<should not inherit from it directly>.
55Usually, Result classes inherit from L<DBIx::Class::Core>, which in turn
56combines the methods from several classes, one of them being
57L<DBIx::Class::Row>. Therefore, while many of the methods available to a
58L<DBIx::Class::Core>-derived Result class are described in the following
59documentation, it does not detail all of the methods available to Result
fb13a49f 60objects. Refer to L<DBIx::Class::Manual::ResultClass> for more info.
93711422 61
7624b19f 62=head1 METHODS
63
8091aa91 64=head2 new
7624b19f 65
a2531bf2 66 my $row = My::Class->new(\%attrs);
67
68 my $row = $schema->resultset('MySource')->new(\%colsandvalues);
69
70=over
71
72=item Arguments: \%attrs or \%colsandvalues
73
fb13a49f 74=item Return Value: L<$result|DBIx::Class::Manual::ResultClass>
7624b19f 75
a2531bf2 76=back
77
fb13a49f 78While you can create a new result object by calling C<new> directly on
a2531bf2 79this class, you are better off calling it on a
80L<DBIx::Class::ResultSet> object.
81
82When calling it directly, you will not get a complete, usable row
50261284 83object until you pass or set the C<result_source> attribute, to a
a2531bf2 84L<DBIx::Class::ResultSource> instance that is attached to a
85L<DBIx::Class::Schema> with a valid connection.
86
87C<$attrs> is a hashref of column name, value data. It can also contain
50261284 88some other attributes such as the C<result_source>.
7624b19f 89
33dd4e80 90Passing an object, or an arrayref of objects as a value will call
91L<DBIx::Class::Relationship::Base/set_from_related> for you. When
92passed a hashref or an arrayref of hashrefs as the value, these will
93be turned into objects via new_related, and treated as if you had
94passed objects.
95
264f1571 96For a more involved explanation, see L<DBIx::Class::ResultSet/create>.
97
dc5f0ad3 98Please note that if a value is not passed to new, no value will be sent
99in the SQL INSERT call, and the column will therefore assume whatever
100default value was specified in your database. While DBIC will retrieve the
101value of autoincrement columns, it will never make an explicit database
102trip to retrieve default values assigned by the RDBMS. You can explicitly
103request that all values be fetched back from the database by calling
104L</discard_changes>, or you can supply an explicit C<undef> to columns
105with NULL as the default, and save yourself a SELECT.
106
107 CAVEAT:
108
109 The behavior described above will backfire if you use a foreign key column
110 with a database-defined default. If you call the relationship accessor on
111 an object that doesn't have a set value for the FK column, DBIC will throw
112 an exception, as it has no way of knowing the PK of the related object (if
113 there is one).
114
7624b19f 115=cut
116
33dd4e80 117## 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().
118## This only works because DBIC doesnt yet care to check whether the new_related objects have been passed all their mandatory columns
119## When doing the later insert, we need to make sure the PKs are set.
120## using _relationship_data in new and funky ways..
121## check Relationship::CascadeActions and Relationship::Accessor for compat
122## tests!
123
370f2ba2 124sub __new_related_find_or_new_helper {
125 my ($self, $relname, $data) = @_;
68888c09 126
b7ded743 127 my $rsrc = $self->result_source;
128
68888c09 129 # create a mock-object so all new/set_column component overrides will run:
b7ded743 130 my $rel_rs = $rsrc->related_source($relname)->resultset;
68888c09 131 my $new_rel_obj = $rel_rs->new_result($data);
132 my $proc_data = { $new_rel_obj->get_columns };
133
134 if ($self->__their_pk_needs_us($relname)) {
de404241 135 MULTICREATE_DEBUG and warn "MC $self constructing $relname via new_result";
68888c09 136 return $new_rel_obj;
370f2ba2 137 }
b7ded743 138 elsif ($rsrc->_pk_depends_on($relname, $proc_data )) {
68888c09 139 if (! keys %$proc_data) {
140 # there is nothing to search for - blind create
141 MULTICREATE_DEBUG and warn "MC $self constructing default-insert $relname";
142 }
143 else {
144 MULTICREATE_DEBUG and warn "MC $self constructing $relname via find_or_new";
145 # this is not *really* find or new, as we don't want to double-new the
146 # data (thus potentially double encoding or whatever)
147 my $exists = $rel_rs->find ($proc_data);
148 return $exists if $exists;
149 }
150 return $new_rel_obj;
370f2ba2 151 }
68888c09 152 else {
b7ded743 153 my $us = $rsrc->source_name;
854929cb 154 $self->throw_exception (
155 "Unable to determine relationship '$relname' direction from '$us', "
156 . "possibly due to a missing reverse-relationship on '$relname' to '$us'."
157 );
370f2ba2 158 }
370f2ba2 159}
160
161sub __their_pk_needs_us { # this should maybe be in resultsource.
68888c09 162 my ($self, $relname) = @_;
370f2ba2 163 my $source = $self->result_source;
164 my $reverse = $source->reverse_relationship_info($relname);
165 my $rel_source = $source->related_source($relname);
166 my $us = { $self->get_columns };
167 foreach my $key (keys %$reverse) {
168 # if their primary key depends on us, then we have to
169 # just create a result and we'll fill it out afterwards
6d0ee587 170 return 1 if $rel_source->_pk_depends_on($key, $us);
370f2ba2 171 }
172 return 0;
173}
174
7624b19f 175sub new {
448f820f 176 my ($class, $attrs) = @_;
7624b19f 177 $class = ref $class if ref $class;
04786a4c 178
50261284 179 my $new = bless { _column_data => {} }, $class;
09e1f723 180
7624b19f 181 if ($attrs) {
27f01d1f 182 $new->throw_exception("attrs must be a hashref")
183 unless ref($attrs) eq 'HASH';
b6d347e0 184
4376a157 185 my $source = delete $attrs->{-result_source};
186 if ( my $h = delete $attrs->{-source_handle} ) {
187 $source ||= $h->resolve;
188 }
189
190 $new->result_source($source) if $source;
191
192 if (my $col_from_rel = delete $attrs->{-cols_from_relations}) {
193 @{$new->{_ignore_at_insert}={}}{@$col_from_rel} = ();
194 }
195
61a622ee 196 my ($related,$inflated);
8222f722 197
61a622ee 198 foreach my $key (keys %$attrs) {
199 if (ref $attrs->{$key}) {
af2d42c0 200 ## Can we extract this lot to use with update(_or .. ) ?
1a58752c 201 $new->throw_exception("Can't do multi-create without result source")
202 unless $source;
370f2ba2 203 my $info = $source->relationship_info($key);
b82c8a28 204 my $acc_type = $info->{attrs}{accessor} || '';
205 if ($acc_type eq 'single') {
de7c7c53 206 my $rel_obj = delete $attrs->{$key};
6298a324 207 if(!blessed $rel_obj) {
370f2ba2 208 $rel_obj = $new->__new_related_find_or_new_helper($key, $rel_obj);
33dd4e80 209 }
2bc3c81e 210
e0cdf2cb 211 if ($rel_obj->in_storage) {
d4fe33d0 212 $new->{_rel_in_storage}{$key} = 1;
e0cdf2cb 213 $new->set_from_related($key, $rel_obj);
214 } else {
09e1f723 215 MULTICREATE_DEBUG and warn "MC $new uninserted $key $rel_obj\n";
e0cdf2cb 216 }
2bc3c81e 217
de7c7c53 218 $related->{$key} = $rel_obj;
61a622ee 219 next;
b82c8a28 220 }
221 elsif ($acc_type eq 'multi' && ref $attrs->{$key} eq 'ARRAY' ) {
2ec8e594 222 my $others = delete $attrs->{$key};
e0cdf2cb 223 my $total = @$others;
224 my @objects;
225 foreach my $idx (0 .. $#$others) {
226 my $rel_obj = $others->[$idx];
6298a324 227 if(!blessed $rel_obj) {
370f2ba2 228 $rel_obj = $new->__new_related_find_or_new_helper($key, $rel_obj);
33dd4e80 229 }
2bc3c81e 230
e0cdf2cb 231 if ($rel_obj->in_storage) {
d4fe33d0 232 $rel_obj->throw_exception ('A multi relationship can not be pre-existing when doing multicreate. Something went wrong');
e0cdf2cb 233 } else {
e0cdf2cb 234 MULTICREATE_DEBUG and
09e1f723 235 warn "MC $new uninserted $key $rel_obj (${\($idx+1)} of $total)\n";
e0cdf2cb 236 }
e0cdf2cb 237 push(@objects, $rel_obj);
2ec8e594 238 }
e0cdf2cb 239 $related->{$key} = \@objects;
2ec8e594 240 next;
b82c8a28 241 }
242 elsif ($acc_type eq 'filter') {
33dd4e80 243 ## 'filter' should disappear and get merged in with 'single' above!
2ec8e594 244 my $rel_obj = delete $attrs->{$key};
6298a324 245 if(!blessed $rel_obj) {
370f2ba2 246 $rel_obj = $new->__new_related_find_or_new_helper($key, $rel_obj);
33dd4e80 247 }
d4fe33d0 248 if ($rel_obj->in_storage) {
249 $new->{_rel_in_storage}{$key} = 1;
250 }
251 else {
09e1f723 252 MULTICREATE_DEBUG and warn "MC $new uninserted $key $rel_obj";
e0cdf2cb 253 }
33dd4e80 254 $inflated->{$key} = $rel_obj;
61a622ee 255 next;
2ec8e594 256 } elsif ($class->has_column($key)
257 && $class->column_info($key)->{_inflate_info}) {
61a622ee 258 $inflated->{$key} = $attrs->{$key};
259 next;
260 }
261 }
e705f529 262 $new->throw_exception("No such column '$key' on $class")
61a622ee 263 unless $class->has_column($key);
b6d347e0 264 $new->store_column($key => $attrs->{$key});
7624b19f 265 }
f90375dd 266
61a622ee 267 $new->{_relationship_data} = $related if $related;
268 $new->{_inflated_column} = $inflated if $inflated;
7624b19f 269 }
04786a4c 270
7624b19f 271 return $new;
272}
273
93711422 274=head2 $column_accessor
275
276 # Each pair does the same thing
277
278 # (un-inflated, regular column)
279 my $val = $row->get_column('first_name');
280 my $val = $row->first_name;
281
282 $row->set_column('first_name' => $val);
283 $row->first_name($val);
284
285 # (inflated column via DBIx::Class::InflateColumn::DateTime)
286 my $val = $row->get_inflated_column('last_modified');
287 my $val = $row->last_modified;
288
289 $row->set_inflated_column('last_modified' => $val);
290 $row->last_modified($val);
291
292=over
293
294=item Arguments: $value?
295
fb13a49f 296=item Return Value: $value
93711422 297
298=back
299
300A column accessor method is created for each column, which is used for
301getting/setting the value for that column.
302
8ed69929 303The actual method name is based on the
304L<accessor|DBIx::Class::ResultSource/accessor> name given during the
305L<Result Class|DBIx::Class::Manual::ResultClass> L<column definition
306|DBIx::Class::ResultSource/add_columns>. Like L</set_column>, this
307will not store the data in the database until L</insert> or L</update>
308is called on the row.
93711422 309
8091aa91 310=head2 insert
7624b19f 311
a2531bf2 312 $row->insert;
313
314=over
7624b19f 315
a2531bf2 316=item Arguments: none
317
fb13a49f 318=item Return Value: L<$result|DBIx::Class::Manual::ResultClass>
a2531bf2 319
320=back
321
322Inserts an object previously created by L</new> into the database if
5298bbb5 323it isn't already in there. Returns the object itself. To insert an
324entirely new row into the database, use L<DBIx::Class::ResultSet/create>.
7624b19f 325
fb13a49f 326To fetch an uninserted result object, call
69bc5f2b 327L<new_result|DBIx::Class::ResultSet/new_result> on a resultset.
e91e756c 328
264f1571 329This will also insert any uninserted, related objects held inside this
330one, see L<DBIx::Class::ResultSet/create> for more details.
331
7624b19f 332=cut
333
334sub insert {
335 my ($self) = @_;
336 return $self if $self->in_storage;
6aba697f 337 my $source = $self->result_source;
aeb1bf75 338 $self->throw_exception("No result_source set on this object; can't insert")
339 unless $source;
6e399b4f 340
a85b7ebe 341 my $storage = $source->storage;
342
9c6d6d93 343 my $rollback_guard;
344
33dd4e80 345 # Check if we stored uninserted relobjs here in new()
b6d347e0 346 my %related_stuff = (%{$self->{_relationship_data} || {}},
33dd4e80 347 %{$self->{_inflated_column} || {}});
9c6d6d93 348
d4fe33d0 349 # insert what needs to be inserted before us
350 my %pre_insert;
351 for my $relname (keys %related_stuff) {
352 my $rel_obj = $related_stuff{$relname};
9c6d6d93 353
d4fe33d0 354 if (! $self->{_rel_in_storage}{$relname}) {
6298a324 355 next unless (blessed $rel_obj && $rel_obj->isa('DBIx::Class::Row'));
a8c98174 356
d4fe33d0 357 next unless $source->_pk_depends_on(
358 $relname, { $rel_obj->get_columns }
359 );
a8c98174 360
d4fe33d0 361 # The guard will save us if we blow out of this scope via die
a85b7ebe 362 $rollback_guard ||= $storage->txn_scope_guard;
9c6d6d93 363
de404241 364 MULTICREATE_DEBUG and warn "MC $self pre-reconstructing $relname $rel_obj\n";
e0cdf2cb 365
380d34f5 366 my $them = { %{$rel_obj->{_relationship_data} || {} }, $rel_obj->get_columns };
68888c09 367 my $existing;
368
369 # if there are no keys - nothing to search for
370 if (keys %$them and $existing = $self->result_source
371 ->related_source($relname)
372 ->resultset
373 ->find($them)
374 ) {
375 %{$rel_obj} = %{$existing};
376 }
377 else {
378 $rel_obj->insert;
379 }
d4fe33d0 380
d4fe33d0 381 $self->{_rel_in_storage}{$relname} = 1;
33dd4e80 382 }
d4fe33d0 383
384 $self->set_from_related($relname, $rel_obj);
385 delete $related_stuff{$relname};
386 }
387
388 # start a transaction here if not started yet and there is more stuff
389 # to insert after us
390 if (keys %related_stuff) {
a85b7ebe 391 $rollback_guard ||= $storage->txn_scope_guard
33dd4e80 392 }
6e399b4f 393
09e1f723 394 MULTICREATE_DEBUG and do {
395 no warnings 'uninitialized';
396 warn "MC $self inserting (".join(', ', $self->get_columns).")\n";
397 };
ac8e89d7 398
8b9473f5 399 # perform the insert - the storage will return everything it is asked to
400 # (autoinc primary columns and any retrieve_on_insert columns)
a85b7ebe 401 my %current_rowdata = $self->get_columns;
a85b7ebe 402 my $returned_cols = $storage->insert(
1e45aa87 403 $source,
8b9473f5 404 { %current_rowdata }, # what to insert, copy because the storage *will* change it
1e45aa87 405 );
406
a85b7ebe 407 for (keys %$returned_cols) {
8b9473f5 408 $self->store_column($_, $returned_cols->{$_})
409 # this ensures we fire store_column only once
410 # (some asshats like overriding it)
411 if (
cf6692ad 412 (!exists $current_rowdata{$_})
8b9473f5 413 or
cf6692ad 414 (defined $current_rowdata{$_} xor defined $returned_cols->{$_})
415 or
416 (defined $current_rowdata{$_} and $current_rowdata{$_} ne $returned_cols->{$_})
8b9473f5 417 );
ac8e89d7 418 }
33dd4e80 419
5ef76b8b 420 delete $self->{_column_data_in_storage};
421 $self->in_storage(1);
e0cdf2cb 422
370f2ba2 423 $self->{_dirty_columns} = {};
424 $self->{related_resultsets} = {};
425
d4fe33d0 426 foreach my $relname (keys %related_stuff) {
31c3800e 427 next unless $source->has_relationship ($relname);
428
429 my @cands = ref $related_stuff{$relname} eq 'ARRAY'
430 ? @{$related_stuff{$relname}}
431 : $related_stuff{$relname}
432 ;
d4fe33d0 433
6298a324 434 if (@cands && blessed $cands[0] && $cands[0]->isa('DBIx::Class::Row')
31c3800e 435 ) {
d4fe33d0 436 my $reverse = $source->reverse_relationship_info($relname);
437 foreach my $obj (@cands) {
438 $obj->set_from_related($_, $self) for keys %$reverse;
68888c09 439 if ($self->__their_pk_needs_us($relname)) {
d4fe33d0 440 if (exists $self->{_ignore_at_insert}{$relname}) {
441 MULTICREATE_DEBUG and warn "MC $self skipping post-insert on $relname";
65ee2b31 442 }
443 else {
444 MULTICREATE_DEBUG and warn "MC $self inserting $relname $obj";
445 $obj->insert;
370f2ba2 446 }
d4fe33d0 447 } else {
448 MULTICREATE_DEBUG and warn "MC $self post-inserting $obj";
449 $obj->insert();
8222f722 450 }
33dd4e80 451 }
452 }
453 }
33dd4e80 454
d4fe33d0 455 delete $self->{_ignore_at_insert};
5ef76b8b 456
d4fe33d0 457 $rollback_guard->commit if $rollback_guard;
458
7624b19f 459 return $self;
460}
461
8091aa91 462=head2 in_storage
7624b19f 463
a2531bf2 464 $row->in_storage; # Get value
465 $row->in_storage(1); # Set value
466
467=over
468
469=item Arguments: none or 1|0
470
fb13a49f 471=item Return Value: 1|0
a2531bf2 472
473=back
7624b19f 474
e91e756c 475Indicates whether the object exists as a row in the database or
476not. This is set to true when L<DBIx::Class::ResultSet/find>,
477L<DBIx::Class::ResultSet/create> or L<DBIx::Class::ResultSet/insert>
b6d347e0 478are used.
e91e756c 479
69bc5f2b 480Creating a result object using L<DBIx::Class::ResultSet/new_result>, or
481calling L</delete> on one, sets it to false.
7624b19f 482
483=cut
484
485sub in_storage {
486 my ($self, $val) = @_;
487 $self->{_in_storage} = $val if @_ > 1;
63bb9738 488 return $self->{_in_storage} ? 1 : 0;
7624b19f 489}
490
8091aa91 491=head2 update
7624b19f 492
a2531bf2 493 $row->update(\%columns?)
494
495=over
7624b19f 496
a2531bf2 497=item Arguments: none or a hashref
7624b19f 498
fb13a49f 499=item Return Value: L<$result|DBIx::Class::Manual::ResultClass>
a2531bf2 500
501=back
502
fb13a49f 503Throws an exception if the result object is not yet in the database,
a2531bf2 504according to L</in_storage>.
505
506This method issues an SQL UPDATE query to commit any changes to the
d6988be8 507object to the database if required (see L</get_dirty_columns>).
508It throws an exception if a proper WHERE clause uniquely identifying
509the database row can not be constructed (see
510L<significance of primary keys|DBIx::Class::Manual::Intro/The Significance and Importance of Primary Keys>
511for more details).
a2531bf2 512
0d0fcdbf 513Also takes an optional hashref of C<< column_name => value >> pairs
a2531bf2 514to update on the object first. Be aware that the hashref will be
515passed to C<set_inflated_columns>, which might edit it in place, so
516don't rely on it being the same after a call to C<update>. If you
517need to preserve the hashref, it is sufficient to pass a shallow copy
518to C<update>, e.g. ( { %{ $href } } )
d5d833d9 519
05d1bc9c 520If the values passed or any of the column values set on the object
48580715 521contain scalar references, e.g.:
05d1bc9c 522
16667b3a 523 $row->last_modified(\'NOW()')->update();
05d1bc9c 524 # OR
a2531bf2 525 $row->update({ last_modified => \'NOW()' });
05d1bc9c 526
527The update will pass the values verbatim into SQL. (See
fb13a49f 528L<SQL::Abstract> docs). The values in your Result object will NOT change
05d1bc9c 529as a result of the update call, if you want the object to be updated
530with the actual values from the database, call L</discard_changes>
531after the update.
532
a2531bf2 533 $row->update()->discard_changes();
534
535To determine before calling this method, which column values have
536changed and will be updated, call L</get_dirty_columns>.
537
538To check if any columns will be updated, call L</is_changed>.
539
540To force a column to be updated, call L</make_column_dirty> before
541this method.
05d1bc9c 542
7624b19f 543=cut
544
545sub update {
546 my ($self, $upd) = @_;
6e399b4f 547
bacf6f12 548 $self->set_inflated_columns($upd) if $upd;
de5ce481 549
014789be 550 my %to_update = $self->get_dirty_columns
551 or return $self;
552
de5ce481 553 $self->throw_exception( "Not in database" ) unless $self->in_storage;
554
88cb6a1d 555 my $rows = $self->result_source->storage->update(
867f1b28 556 $self->result_source, \%to_update, $self->_storage_ident_condition
cf856357 557 );
7624b19f 558 if ($rows == 0) {
701da8c4 559 $self->throw_exception( "Can't update ${self}: row not found" );
7624b19f 560 } elsif ($rows > 1) {
701da8c4 561 $self->throw_exception("Can't update ${self}: updated more than one row");
7624b19f 562 }
563 $self->{_dirty_columns} = {};
64acc2bc 564 $self->{related_resultsets} = {};
5ef76b8b 565 delete $self->{_column_data_in_storage};
7624b19f 566 return $self;
567}
568
8091aa91 569=head2 delete
7624b19f 570
a2531bf2 571 $row->delete
572
573=over
574
575=item Arguments: none
7624b19f 576
fb13a49f 577=item Return Value: L<$result|DBIx::Class::Manual::ResultClass>
a2531bf2 578
579=back
580
581Throws an exception if the object is not in the database according to
d6988be8 582L</in_storage>. Also throws an exception if a proper WHERE clause
583uniquely identifying the database row can not be constructed (see
584L<significance of primary keys|DBIx::Class::Manual::Intro/The Significance and Importance of Primary Keys>
585for more details).
a2531bf2 586
587The object is still perfectly usable, but L</in_storage> will
ea36f4e4 588now return 0 and the object must be reinserted using L</insert>
b6d347e0 589before it can be used to L</update> the row again.
a2531bf2 590
591If you delete an object in a class with a C<has_many> relationship, an
592attempt is made to delete all the related objects as well. To turn
593this behaviour off, pass C<< cascade_delete => 0 >> in the C<$attr>
594hashref of the relationship, see L<DBIx::Class::Relationship>. Any
595database-level cascade or restrict will take precedence over a
281e677e 596DBIx-Class-based cascading delete, since DBIx-Class B<deletes the
597main row first> and only then attempts to delete any remaining related
598rows.
a2531bf2 599
b1d16ffd 600If you delete an object within a txn_do() (see L<DBIx::Class::Storage/txn_do>)
fb13a49f 601and the transaction subsequently fails, the result object will remain marked as
b1d16ffd 602not being in storage. If you know for a fact that the object is still in
603storage (i.e. by inspecting the cause of the transaction's failure), you can
604use C<< $obj->in_storage(1) >> to restore consistency between the object and
605the database. This would allow a subsequent C<< $obj->delete >> to work
606as expected.
607
a2531bf2 608See also L<DBIx::Class::ResultSet/delete>.
7624b19f 609
610=cut
611
612sub delete {
613 my $self = shift;
614 if (ref $self) {
701da8c4 615 $self->throw_exception( "Not in database" ) unless $self->in_storage;
cf856357 616
88cb6a1d 617 $self->result_source->storage->delete(
867f1b28 618 $self->result_source, $self->_storage_ident_condition
cf856357 619 );
620
5ef76b8b 621 delete $self->{_column_data_in_storage};
7624b19f 622 $self->in_storage(undef);
cf856357 623 }
624 else {
5298bbb5 625 my $rsrc = try { $self->result_source_instance }
626 or $self->throw_exception("Can't do class delete without a ResultSource instance");
627
aeb1bf75 628 my $attrs = @_ > 1 && ref $_[$#_] eq 'HASH' ? { %{pop(@_)} } : {};
629 my $query = ref $_[0] eq 'HASH' ? $_[0] : {@_};
5298bbb5 630 $rsrc->resultset->search(@_)->delete;
7624b19f 631 }
632 return $self;
633}
634
8091aa91 635=head2 get_column
7624b19f 636
a2531bf2 637 my $val = $row->get_column($col);
638
639=over
640
641=item Arguments: $columnname
642
fb13a49f 643=item Return Value: The value of the column
a2531bf2 644
645=back
646
647Throws an exception if the column name given doesn't exist according
16667b3a 648to L<has_column|DBIx::Class::ResultSource/has_column>.
7624b19f 649
fb13a49f 650Returns a raw column value from the result object, if it has already
e91e756c 651been fetched from the database or set by an accessor.
652
653If an L<inflated value|DBIx::Class::InflateColumn> has been set, it
654will be deflated and returned.
7624b19f 655
ea36f4e4 656Note that if you used the C<columns> or the C<select/as>
657L<search attributes|DBIx::Class::ResultSet/ATTRIBUTES> on the resultset from
658which C<$row> was derived, and B<did not include> C<$columnname> in the list,
659this method will return C<undef> even if the database contains some value.
660
a2531bf2 661To retrieve all loaded column values as a hash, use L</get_columns>.
662
7624b19f 663=cut
664
665sub get_column {
666 my ($self, $column) = @_;
701da8c4 667 $self->throw_exception( "Can't fetch data as class method" ) unless ref $self;
aeb1bf75 668 return $self->{_column_data}{$column} if exists $self->{_column_data}{$column};
61a622ee 669 if (exists $self->{_inflated_column}{$column}) {
670 return $self->store_column($column,
b6d347e0 671 $self->_deflated_column($column, $self->{_inflated_column}{$column}));
61a622ee 672 }
701da8c4 673 $self->throw_exception( "No such column '${column}'" ) unless $self->has_column($column);
7624b19f 674 return undef;
675}
676
9b83fccd 677=head2 has_column_loaded
678
a2531bf2 679 if ( $row->has_column_loaded($col) ) {
9b83fccd 680 print "$col has been loaded from db";
681 }
682
a2531bf2 683=over
684
685=item Arguments: $columnname
686
fb13a49f 687=item Return Value: 0|1
a2531bf2 688
689=back
690
9b83fccd 691Returns a true value if the column value has been loaded from the
692database (or set locally).
693
694=cut
695
def81720 696sub has_column_loaded {
697 my ($self, $column) = @_;
698 $self->throw_exception( "Can't call has_column data as class method" ) unless ref $self;
61a622ee 699 return 1 if exists $self->{_inflated_column}{$column};
aeb1bf75 700 return exists $self->{_column_data}{$column};
def81720 701}
702
8091aa91 703=head2 get_columns
076a6864 704
a2531bf2 705 my %data = $row->get_columns;
706
707=over
708
709=item Arguments: none
076a6864 710
fb13a49f 711=item Return Value: A hash of columnname, value pairs.
a2531bf2 712
713=back
714
715Returns all loaded column data as a hash, containing raw values. To
716get just one value for a particular column, use L</get_column>.
076a6864 717
c0a171bf 718See L</get_inflated_columns> to get the inflated values.
719
076a6864 720=cut
721
722sub get_columns {
723 my $self = shift;
61a622ee 724 if (exists $self->{_inflated_column}) {
725 foreach my $col (keys %{$self->{_inflated_column}}) {
726 $self->store_column($col, $self->_deflated_column($col, $self->{_inflated_column}{$col}))
c4a30d56 727 unless exists $self->{_column_data}{$col};
61a622ee 728 }
729 }
cb5f2eea 730 return %{$self->{_column_data}};
d7156e50 731}
732
733=head2 get_dirty_columns
734
a2531bf2 735 my %data = $row->get_dirty_columns;
736
737=over
738
739=item Arguments: none
d7156e50 740
fb13a49f 741=item Return Value: A hash of column, value pairs
a2531bf2 742
743=back
744
745Only returns the column, value pairs for those columns that have been
746changed on this object since the last L</update> or L</insert> call.
747
748See L</get_columns> to fetch all column/value pairs.
d7156e50 749
750=cut
751
752sub get_dirty_columns {
753 my $self = shift;
754 return map { $_ => $self->{_column_data}{$_} }
755 keys %{$self->{_dirty_columns}};
076a6864 756}
757
6dbea98e 758=head2 make_column_dirty
759
a2531bf2 760 $row->make_column_dirty($col)
761
762=over
763
764=item Arguments: $columnname
765
fb13a49f 766=item Return Value: not defined
a2531bf2 767
768=back
769
770Throws an exception if the column does not exist.
771
772Marks a column as having been changed regardless of whether it has
b6d347e0 773really changed.
6dbea98e 774
775=cut
776sub make_column_dirty {
777 my ($self, $column) = @_;
778
779 $self->throw_exception( "No such column '${column}'" )
780 unless exists $self->{_column_data}{$column} || $self->has_column($column);
497d874a 781
b6d347e0 782 # the entire clean/dirty code relies on exists, not on true/false
497d874a 783 return 1 if exists $self->{_dirty_columns}{$column};
784
6dbea98e 785 $self->{_dirty_columns}{$column} = 1;
497d874a 786
787 # if we are just now making the column dirty, and if there is an inflated
788 # value, force it over the deflated one
789 if (exists $self->{_inflated_column}{$column}) {
790 $self->store_column($column,
791 $self->_deflated_column(
792 $column, $self->{_inflated_column}{$column}
793 )
794 );
795 }
6dbea98e 796}
797
ba4a6453 798=head2 get_inflated_columns
799
e91e756c 800 my %inflated_data = $obj->get_inflated_columns;
ba4a6453 801
a2531bf2 802=over
803
804=item Arguments: none
805
fb13a49f 806=item Return Value: A hash of column, object|value pairs
a2531bf2 807
808=back
809
810Returns a hash of all column keys and associated values. Values for any
811columns set to use inflation will be inflated and returns as objects.
812
813See L</get_columns> to get the uninflated values.
814
815See L<DBIx::Class::InflateColumn> for how to setup inflation.
ba4a6453 816
817=cut
818
819sub get_inflated_columns {
820 my $self = shift;
d61b2132 821
52416317 822 my $loaded_colinfo = $self->columns_info ([
823 grep { $self->has_column_loaded($_) } $self->columns
824 ]);
d61b2132 825
826 my %inflated;
52416317 827 for my $col (keys %$loaded_colinfo) {
828 if (exists $loaded_colinfo->{$col}{accessor}) {
829 my $acc = $loaded_colinfo->{$col}{accessor};
9c042209 830 $inflated{$col} = $self->$acc if defined $acc;
d61b2132 831 }
832 else {
833 $inflated{$col} = $self->$col;
834 }
835 }
836
837 # return all loaded columns with the inflations overlayed on top
edc89064 838 return %{ { $self->get_columns, %inflated } };
ba4a6453 839}
840
ca8a1270 841sub _is_column_numeric {
0bb1a52f 842 my ($self, $column) = @_;
843 my $colinfo = $self->column_info ($column);
844
845 # cache for speed (the object may *not* have a resultsource instance)
50261284 846 if (
847 ! defined $colinfo->{is_numeric}
848 and
849 my $storage = try { $self->result_source->schema->storage }
850 ) {
0bb1a52f 851 $colinfo->{is_numeric} =
50261284 852 $storage->is_datatype_numeric ($colinfo->{data_type})
0bb1a52f 853 ? 1
854 : 0
855 ;
856 }
857
858 return $colinfo->{is_numeric};
859}
860
8091aa91 861=head2 set_column
7624b19f 862
a2531bf2 863 $row->set_column($col => $val);
864
865=over
866
867=item Arguments: $columnname, $value
868
fb13a49f 869=item Return Value: $value
a2531bf2 870
871=back
7624b19f 872
e91e756c 873Sets a raw column value. If the new value is different from the old one,
a2531bf2 874the column is marked as dirty for when you next call L</update>.
7624b19f 875
ea36f4e4 876If passed an object or reference as a value, this method will happily
877attempt to store it, and a later L</insert> or L</update> will try and
a2531bf2 878stringify/numify as appropriate. To set an object to be deflated
93711422 879instead, see L</set_inflated_columns>, or better yet, use L</$column_accessor>.
e91e756c 880
7624b19f 881=cut
882
883sub set_column {
1d0057bd 884 my ($self, $column, $new_value) = @_;
885
5ef76b8b 886 my $had_value = $self->has_column_loaded($column);
887 my ($old_value, $in_storage) = ($self->get_column($column), $self->in_storage)
888 if $had_value;
1d0057bd 889
b236052f 890 $new_value = $self->store_column($column, $new_value);
8f9eff75 891
cde96798 892 my $dirty =
893 $self->{_dirty_columns}{$column}
894 ||
5ef76b8b 895 $in_storage # no point tracking dirtyness on uninserted data
cde96798 896 ? ! $self->_eq_column_values ($column, $old_value, $new_value)
897 : 1
898 ;
8f9eff75 899
35f5c265 900 if ($dirty) {
901 # FIXME sadly the update code just checks for keys, not for their value
902 $self->{_dirty_columns}{$column} = 1;
903
904 # Clear out the relation/inflation cache related to this column
905 #
906 # FIXME - this is a quick *largely incorrect* hack, pending a more
907 # serious rework during the merge of single and filter rels
908 my $rels = $self->result_source->{_relationships};
909 for my $rel (keys %$rels) {
910
911 my $acc = $rels->{$rel}{attrs}{accessor} || '';
912
913 if ( $acc eq 'single' and $rels->{$rel}{attrs}{fk_columns}{$column} ) {
914 delete $self->{related_resultsets}{$rel};
915 delete $self->{_relationship_data}{$rel};
916 #delete $self->{_inflated_column}{$rel};
917 }
918 elsif ( $acc eq 'filter' and $rel eq $column) {
919 delete $self->{related_resultsets}{$rel};
920 #delete $self->{_relationship_data}{$rel};
921 delete $self->{_inflated_column}{$rel};
922 }
8f9eff75 923 }
5ef76b8b 924
925 if (
926 # value change from something (even if NULL)
927 $had_value
928 and
929 # no storage - no storage-value
930 $in_storage
931 and
932 # no value already stored (multiple changes before commit to storage)
933 ! exists $self->{_column_data_in_storage}{$column}
934 and
935 $self->_track_storage_value($column)
936 ) {
937 $self->{_column_data_in_storage}{$column} = $old_value;
8f9eff75 938 }
939 }
940
1d0057bd 941 return $new_value;
7624b19f 942}
e60dc79f 943
cde96798 944sub _eq_column_values {
945 my ($self, $col, $old, $new) = @_;
e60dc79f 946
cde96798 947 if (defined $old xor defined $new) {
948 return 0;
949 }
950 elsif (not defined $old) { # both undef
951 return 1;
952 }
953 elsif ($old eq $new) {
954 return 1;
955 }
956 elsif ($self->_is_column_numeric($col)) { # do a numeric comparison if datatype allows it
957 return $old == $new;
958 }
959 else {
960 return 0;
961 }
962}
963
5ef76b8b 964# returns a boolean indicating if the passed column should have its original
965# value tracked between column changes and commitment to storage
966sub _track_storage_value {
967 my ($self, $col) = @_;
968 return defined first { $col eq $_ } ($self->primary_columns);
7624b19f 969}
970
8091aa91 971=head2 set_columns
076a6864 972
a2531bf2 973 $row->set_columns({ $col => $val, ... });
974
b6d347e0 975=over
076a6864 976
a2531bf2 977=item Arguments: \%columndata
978
fb13a49f 979=item Return Value: L<$result|DBIx::Class::Manual::ResultClass>
a2531bf2 980
981=back
982
983Sets multiple column, raw value pairs at once.
984
985Works as L</set_column>.
076a6864 986
987=cut
988
989sub set_columns {
990 my ($self,$data) = @_;
a2ca474b 991 foreach my $col (keys %$data) {
992 $self->set_column($col,$data->{$col});
076a6864 993 }
c01ab172 994 return $self;
076a6864 995}
996
bacf6f12 997=head2 set_inflated_columns
998
a2531bf2 999 $row->set_inflated_columns({ $col => $val, $relname => $obj, ... });
1000
1001=over
1002
1003=item Arguments: \%columndata
1004
fb13a49f 1005=item Return Value: L<$result|DBIx::Class::Manual::ResultClass>
a2531bf2 1006
1007=back
1008
1009Sets more than one column value at once. Any inflated values are
b6d347e0 1010deflated and the raw values stored.
bacf6f12 1011
fb13a49f 1012Any related values passed as Result objects, using the relation name as a
a2531bf2 1013key, are reduced to the appropriate foreign key values and stored. If
fb13a49f 1014instead of related result objects, a hashref of column, value data is
a2531bf2 1015passed, will create the related object first then store.
1016
1017Will even accept arrayrefs of data as a value to a
1018L<DBIx::Class::Relationship/has_many> key, and create the related
1019objects if necessary.
1020
c1300297 1021Be aware that the input hashref might be edited in place, so don't rely
a2531bf2 1022on it being the same after a call to C<set_inflated_columns>. If you
1023need to preserve the hashref, it is sufficient to pass a shallow copy
1024to C<set_inflated_columns>, e.g. ( { %{ $href } } )
1025
1026See also L<DBIx::Class::Relationship::Base/set_from_related>.
bacf6f12 1027
1028=cut
1029
1030sub set_inflated_columns {
1031 my ( $self, $upd ) = @_;
1032 foreach my $key (keys %$upd) {
1033 if (ref $upd->{$key}) {
1034 my $info = $self->relationship_info($key);
b82c8a28 1035 my $acc_type = $info->{attrs}{accessor} || '';
1036 if ($acc_type eq 'single') {
bacf6f12 1037 my $rel = delete $upd->{$key};
1038 $self->set_from_related($key => $rel);
a7be8807 1039 $self->{_relationship_data}{$key} = $rel;
bacf6f12 1040 }
b82c8a28 1041 elsif ($acc_type eq 'multi') {
1042 $self->throw_exception(
1043 "Recursive update is not supported over relationships of type '$acc_type' ($key)"
1044 );
1045 }
1046 elsif ($self->has_column($key) && exists $self->column_info($key)->{_inflate_info}) {
a7be8807 1047 $self->set_inflated_column($key, delete $upd->{$key});
bacf6f12 1048 }
1049 }
1050 }
b6d347e0 1051 $self->set_columns($upd);
bacf6f12 1052}
1053
8091aa91 1054=head2 copy
076a6864 1055
1056 my $copy = $orig->copy({ change => $to, ... });
1057
a2531bf2 1058=over
1059
1060=item Arguments: \%replacementdata
1061
fb13a49f 1062=item Return Value: L<$result|DBIx::Class::Manual::ResultClass> copy
a2531bf2 1063
1064=back
1065
1066Inserts a new row into the database, as a copy of the original
1067object. If a hashref of replacement data is supplied, these will take
ce0893e0 1068precedence over data in the original. Also any columns which have
1069the L<column info attribute|DBIx::Class::ResultSource/add_columns>
1070C<< is_auto_increment => 1 >> are explicitly removed before the copy,
1071so that the database can insert its own autoincremented values into
1072the new object.
a2531bf2 1073
f928c965 1074Relationships will be followed by the copy procedure B<only> if the
48580715 1075relationship specifies a true value for its
f928c965 1076L<cascade_copy|DBIx::Class::Relationship::Base> attribute. C<cascade_copy>
1077is set by default on C<has_many> relationships and unset on all others.
076a6864 1078
1079=cut
1080
c01ab172 1081sub copy {
1082 my ($self, $changes) = @_;
333cce60 1083 $changes ||= {};
fde6e28e 1084 my $col_data = { %{$self->{_column_data}} };
52416317 1085
1086 my $colinfo = $self->columns_info([ keys %$col_data ]);
fde6e28e 1087 foreach my $col (keys %$col_data) {
1088 delete $col_data->{$col}
52416317 1089 if $colinfo->{$col}{is_auto_increment};
fde6e28e 1090 }
04786a4c 1091
1092 my $new = { _column_data => $col_data };
1093 bless $new, ref $self;
1094
83419ec6 1095 $new->result_source($self->result_source);
bacf6f12 1096 $new->set_inflated_columns($changes);
333cce60 1097 $new->insert;
35688220 1098
b6d347e0 1099 # Its possible we'll have 2 relations to the same Source. We need to make
48580715 1100 # sure we don't try to insert the same row twice else we'll violate unique
35688220 1101 # constraints
1102 my $rels_copied = {};
1103
333cce60 1104 foreach my $rel ($self->result_source->relationships) {
1105 my $rel_info = $self->result_source->relationship_info($rel);
35688220 1106
1107 next unless $rel_info->{attrs}{cascade_copy};
b6d347e0 1108
6d0ee587 1109 my $resolved = $self->result_source->_resolve_condition(
16053767 1110 $rel_info->{cond}, $rel, $new, $rel
35688220 1111 );
1112
1113 my $copied = $rels_copied->{ $rel_info->{source} } ||= {};
1114 foreach my $related ($self->search_related($rel)) {
1115 my $id_str = join("\0", $related->id);
1116 next if $copied->{$id_str};
1117 $copied->{$id_str} = 1;
1118 my $rel_copy = $related->copy($resolved);
333cce60 1119 }
b6d347e0 1120
333cce60 1121 }
2c4c67b6 1122 return $new;
c01ab172 1123}
1124
8091aa91 1125=head2 store_column
7624b19f 1126
a2531bf2 1127 $row->store_column($col => $val);
7624b19f 1128
a2531bf2 1129=over
1130
1131=item Arguments: $columnname, $value
1132
fb13a49f 1133=item Return Value: The value sent to storage
a2531bf2 1134
1135=back
1136
1137Set a raw value for a column without marking it as changed. This
1138method is used internally by L</set_column> which you should probably
1139be using.
1140
fb13a49f 1141This is the lowest level at which data is set on a result object,
a2531bf2 1142extend this method to catch all data setting methods.
7624b19f 1143
1144=cut
1145
1146sub store_column {
1147 my ($self, $column, $value) = @_;
75d07914 1148 $self->throw_exception( "No such column '${column}'" )
d7156e50 1149 unless exists $self->{_column_data}{$column} || $self->has_column($column);
75d07914 1150 $self->throw_exception( "set_column called for ${column} without value" )
7624b19f 1151 if @_ < 3;
1152 return $self->{_column_data}{$column} = $value;
1153}
1154
b52e9bf8 1155=head2 inflate_result
1156
c01ab172 1157 Class->inflate_result($result_source, \%me, \%prefetch?)
b52e9bf8 1158
a2531bf2 1159=over
1160
fb13a49f 1161=item Arguments: L<$result_source|DBIx::Class::ResultSource>, \%columndata, \%prefetcheddata
a2531bf2 1162
fb13a49f 1163=item Return Value: L<$result|DBIx::Class::Manual::ResultClass>
a2531bf2 1164
1165=back
1166
1167All L<DBIx::Class::ResultSet> methods that retrieve data from the
fb13a49f 1168database and turn it into result objects call this method.
a2531bf2 1169
1170Extend this method in your Result classes to hook into this process,
1171for example to rebless the result into a different class.
1172
1173Reblessing can also be done more easily by setting C<result_class> in
1174your Result class. See L<DBIx::Class::ResultSource/result_class>.
b52e9bf8 1175
db2b2eb6 1176Different types of results can also be created from a particular
1177L<DBIx::Class::ResultSet>, see L<DBIx::Class::ResultSet/result_class>.
1178
b52e9bf8 1179=cut
1180
1181sub inflate_result {
c01ab172 1182 my ($class, $source, $me, $prefetch) = @_;
aec3eff1 1183
50261284 1184 $source = $source->resolve
1185 if $source->isa('DBIx::Class::ResultSourceHandle');
aec3eff1 1186
50261284 1187 my $new = bless
1188 { _column_data => $me, _result_source => $source },
1189 ref $class || $class
1190 ;
04786a4c 1191
64acc2bc 1192 foreach my $pre (keys %{$prefetch||{}}) {
35c77aa3 1193
c9733800 1194 my (@pre_vals, $is_multi);
1195 if (ref $prefetch->{$pre}[0] eq 'ARRAY') {
1196 $is_multi = 1;
1197 @pre_vals = @{$prefetch->{$pre}};
1198 }
1199 else {
1200 @pre_vals = $prefetch->{$pre};
1201 }
13d06949 1202
c9733800 1203 my $pre_source = try {
1204 $source->related_source($pre)
1205 }
1206 catch {
1207 $class->throw_exception(sprintf
1208
1209 "Can't inflate manual prefetch into non-existent relationship '%s' from '%s', "
1210 . "check the inflation specification (columns/as) ending in '%s.%s'.",
1211
1212 $pre,
1213 $source->source_name,
1214 $pre,
1215 (keys %{$pre_vals[0][0]})[0] || 'something.something...',
1216 );
1217 };
ce9f555e 1218
1219 my $accessor = $source->relationship_info($pre)->{attrs}{accessor}
c9733800 1220 or $class->throw_exception("No accessor type declared for prefetched $pre");
1221
1222 if (! $is_multi and $accessor eq 'multi') {
1223 $class->throw_exception("Manual prefetch (via select/columns) not supported with accessor 'multi'");
1224 }
13d06949 1225
1226 my @pre_objects;
1227 for my $me_pref (@pre_vals) {
908aa1bb 1228
c9733800 1229 # FIXME - this should not be necessary
1230 # the collapser currently *could* return bogus elements with all
1231 # columns set to undef
1232 my $has_def;
1233 for (values %{$me_pref->[0]}) {
1234 if (defined $_) {
1235 $has_def++;
1236 last;
1237 }
1238 }
1239 next unless $has_def;
908aa1bb 1240
c9733800 1241 push @pre_objects, $pre_source->result_class->inflate_result(
1242 $pre_source, @$me_pref
1243 );
13d06949 1244 }
b82c8a28 1245
13d06949 1246 if ($accessor eq 'single') {
1247 $new->{_relationship_data}{$pre} = $pre_objects[0];
b52e9bf8 1248 }
13d06949 1249 elsif ($accessor eq 'filter') {
1250 $new->{_inflated_column}{$pre} = $pre_objects[0];
1251 }
1252
1253 $new->related_resultset($pre)->set_cache(\@pre_objects);
b52e9bf8 1254 }
35c77aa3 1255
1256 $new->in_storage (1);
7624b19f 1257 return $new;
1258}
1259
9b465d00 1260=head2 update_or_insert
7624b19f 1261
a2531bf2 1262 $row->update_or_insert
1263
1264=over
7624b19f 1265
a2531bf2 1266=item Arguments: none
1267
fb13a49f 1268=item Return Value: Result of update or insert operation
a2531bf2 1269
1270=back
1271
1272L</Update>s the object if it's already in the database, according to
1273L</in_storage>, else L</insert>s it.
7624b19f 1274
9b83fccd 1275=head2 insert_or_update
1276
1277 $obj->insert_or_update
1278
1279Alias for L</update_or_insert>
1280
7624b19f 1281=cut
1282
370f2ba2 1283sub insert_or_update { shift->update_or_insert(@_) }
1284
9b465d00 1285sub update_or_insert {
7624b19f 1286 my $self = shift;
1287 return ($self->in_storage ? $self->update : $self->insert);
1288}
1289
8091aa91 1290=head2 is_changed
7624b19f 1291
a2531bf2 1292 my @changed_col_names = $row->is_changed();
1293 if ($row->is_changed()) { ... }
1294
1295=over
7624b19f 1296
a2531bf2 1297=item Arguments: none
1298
fb13a49f 1299=item Return Value: 0|1 or @columnnames
a2531bf2 1300
1301=back
1302
1303In list context returns a list of columns with uncommited changes, or
9b83fccd 1304in scalar context returns a true value if there are uncommitted
1305changes.
1306
7624b19f 1307=cut
1308
1309sub is_changed {
1310 return keys %{shift->{_dirty_columns} || {}};
1311}
228dbcb4 1312
1313=head2 is_column_changed
1314
a2531bf2 1315 if ($row->is_column_changed('col')) { ... }
1316
1317=over
1318
1319=item Arguments: $columname
1320
fb13a49f 1321=item Return Value: 0|1
a2531bf2 1322
1323=back
228dbcb4 1324
9b83fccd 1325Returns a true value if the column has uncommitted changes.
1326
228dbcb4 1327=cut
1328
1329sub is_column_changed {
1330 my( $self, $col ) = @_;
1331 return exists $self->{_dirty_columns}->{$col};
1332}
7624b19f 1333
097d3227 1334=head2 result_source
1335
a2531bf2 1336 my $resultsource = $row->result_source;
1337
1338=over
1339
fb13a49f 1340=item Arguments: L<$result_source?|DBIx::Class::ResultSource>
097d3227 1341
fb13a49f 1342=item Return Value: L<$result_source|DBIx::Class::ResultSource>
a2531bf2 1343
1344=back
1345
1346Accessor to the L<DBIx::Class::ResultSource> this object was created from.
87c4e602 1347
aec3eff1 1348=cut
1349
1350sub result_source {
5298bbb5 1351 $_[0]->throw_exception( 'result_source can be called on instances only' )
1352 unless ref $_[0];
1353
1354 @_ > 1
1355 ? $_[0]->{_result_source} = $_[1]
1356
1357 # note this is a || not a ||=, the difference is important
1358 : $_[0]->{_result_source} || do {
1359 my $class = ref $_[0];
1360 $_[0]->can('result_source_instance')
1361 ? $_[0]->result_source_instance
1362 : $_[0]->throw_exception(
1363 "No result source instance registered for $class, did you forget to call $class->table(...) ?"
1364 )
1365 }
1366 ;
aec3eff1 1367}
1368
9b83fccd 1369=head2 register_column
27f01d1f 1370
9b83fccd 1371 $column_info = { .... };
1372 $class->register_column($column_name, $column_info);
27f01d1f 1373
a2531bf2 1374=over
1375
1376=item Arguments: $columnname, \%columninfo
1377
fb13a49f 1378=item Return Value: not defined
a2531bf2 1379
1380=back
1381
9b83fccd 1382Registers a column on the class. If the column_info has an 'accessor'
1383key, creates an accessor named after the value if defined; if there is
1384no such key, creates an accessor with the same name as the column
1f23a877 1385
9b83fccd 1386The column_info attributes are described in
1387L<DBIx::Class::ResultSource/add_columns>
1f23a877 1388
097d3227 1389=cut
1390
1f23a877 1391sub register_column {
1392 my ($class, $col, $info) = @_;
91b0fbd7 1393 my $acc = $col;
1394 if (exists $info->{accessor}) {
1395 return unless defined $info->{accessor};
1396 $acc = [ $info->{accessor}, $col ];
1397 }
1398 $class->mk_group_accessors('column' => $acc);
1f23a877 1399}
1400
a2531bf2 1401=head2 get_from_storage
1402
1403 my $copy = $row->get_from_storage($attrs)
1404
1405=over
b9b4e52f 1406
a2531bf2 1407=item Arguments: \%attrs
b9b4e52f 1408
fb13a49f 1409=item Return Value: A Result object
a2531bf2 1410
1411=back
1412
fb13a49f 1413Fetches a fresh copy of the Result object from the database and returns it.
d6988be8 1414Throws an exception if a proper WHERE clause identifying the database row
1415can not be constructed (i.e. if the original object does not contain its
1416entire
1417 L<primary key|DBIx::Class::Manual::Intro/The Significance and Importance of Primary Keys>
1418). If passed the \%attrs argument, will first apply these attributes to
a2531bf2 1419the resultset used to find the row.
1420
fb13a49f 1421This copy can then be used to compare to an existing result object, to
a2531bf2 1422determine if any changes have been made in the database since it was
1423created.
1424
fb13a49f 1425To just update your Result object with any latest changes from the
a2531bf2 1426database, use L</discard_changes> instead.
1427
1428The \%attrs argument should be compatible with
1429L<DBIx::Class::ResultSet/ATTRIBUTES>.
7e38d850 1430
b9b4e52f 1431=cut
1432
a737512c 1433sub get_from_storage {
b9b4e52f 1434 my $self = shift @_;
7e38d850 1435 my $attrs = shift @_;
7e38d850 1436 my $resultset = $self->result_source->resultset;
b6d347e0 1437
7e38d850 1438 if(defined $attrs) {
bbd107cf 1439 $resultset = $resultset->search(undef, $attrs);
7e38d850 1440 }
b6d347e0 1441
867f1b28 1442 return $resultset->find($self->_storage_ident_condition);
b9b4e52f 1443}
701da8c4 1444
93711422 1445=head2 discard_changes
fde05eb9 1446
1447 $row->discard_changes
1448
1449=over
1450
1451=item Arguments: none or $attrs
1452
fb13a49f 1453=item Return Value: self (updates object in-place)
fde05eb9 1454
1455=back
bbd107cf 1456
1457Re-selects the row from the database, losing any changes that had
fde05eb9 1458been made. Throws an exception if a proper C<WHERE> clause identifying
d6988be8 1459the database row can not be constructed (i.e. if the original object
1460does not contain its entire
fde05eb9 1461L<primary key|DBIx::Class::Manual::Intro/The Significance and Importance of Primary Keys>).
bbd107cf 1462
1463This method can also be used to refresh from storage, retrieving any
1464changes made since the row was last read from storage.
1465
fde05eb9 1466$attrs, if supplied, is expected to be a hashref of attributes suitable for passing as the
1467second argument to C<< $resultset->search($cond, $attrs) >>;
1468
1469Note: If you are using L<DBIx::Class::Storage::DBI::Replicated> as your
1470storage, please kept in mind that if you L</discard_changes> on a row that you
1471just updated or created, you should wrap the entire bit inside a transaction.
1472Otherwise you run the risk that you insert or update to the master database
1473but read from a replicant database that has not yet been updated from the
1474master. This will result in unexpected results.
bbd107cf 1475
1476=cut
1477
1478sub discard_changes {
1479 my ($self, $attrs) = @_;
bbd107cf 1480 return unless $self->in_storage; # Don't reload if we aren't real!
1481
1482 # add a replication default to read from the master only
1483 $attrs = { force_pool => 'master', %{$attrs||{}} };
1484
1485 if( my $current_storage = $self->get_from_storage($attrs)) {
1486
1487 # Set $self to the current.
1488 %$self = %$current_storage;
1489
1490 # Avoid a possible infinite loop with
1491 # sub DESTROY { $_[0]->discard_changes }
1492 bless $current_storage, 'Do::Not::Exist';
1493
1494 return $self;
1495 }
1496 else {
1497 $self->in_storage(0);
1498 return $self;
1499 }
1500}
1501
5160b401 1502=head2 throw_exception
701da8c4 1503
a2531bf2 1504See L<DBIx::Class::Schema/throw_exception>.
701da8c4 1505
1506=cut
1507
1508sub throw_exception {
1509 my $self=shift;
1a58752c 1510
4376a157 1511 if (ref $self && ref $self->result_source ) {
1512 $self->result_source->throw_exception(@_)
1a58752c 1513 }
1514 else {
1515 DBIx::Class::Exception->throw(@_);
701da8c4 1516 }
1517}
1518
33cf6616 1519=head2 id
1520
a2531bf2 1521 my @pk = $row->id;
1522
1523=over
1524
1525=item Arguments: none
1526
1527=item Returns: A list of primary key values
1528
1529=back
1530
33cf6616 1531Returns the primary key(s) for a row. Can't be called as a class method.
f7043881 1532Actually implemented in L<DBIx::Class::PK>
33cf6616 1533
0c11ad0e 1534=head1 AUTHOR AND CONTRIBUTORS
7624b19f 1535
0c11ad0e 1536See L<AUTHOR|DBIx::Class/AUTHOR> and L<CONTRIBUTORS|DBIx::Class/CONTRIBUTORS> in DBIx::Class
7624b19f 1537
1538=head1 LICENSE
1539
1540You may distribute this code under the same terms as Perl itself.
1541
1542=cut
fde05eb9 1543
15441;