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