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