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