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