Docs on using multiple db schemas (from abraxxa maybe, I forget)
[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/;
701da8c4 7use Carp::Clan qw/^DBIx::Class/;
33dd4e80 8use Scalar::Util ();
9c6d6d93 9use Scope::Guard;
1edd1722 10
0d5d1f12 11###
12### Internal method
13### Do not use
14###
e0cdf2cb 15BEGIN {
16 *MULTICREATE_DEBUG =
17 $ENV{DBIC_MULTICREATE_DEBUG}
18 ? sub () { 1 }
19 : sub () { 0 };
20}
21
aec3eff1 22__PACKAGE__->mk_group_accessors('simple' => qw/_source_handle/);
8c49f629 23
75d07914 24=head1 NAME
7624b19f 25
26DBIx::Class::Row - Basic row methods
27
28=head1 SYNOPSIS
29
30=head1 DESCRIPTION
31
32This class is responsible for defining and doing basic operations on rows
1ea77c14 33derived from L<DBIx::Class::ResultSource> objects.
7624b19f 34
a2531bf2 35Row objects are returned from L<DBIx::Class::ResultSet>s using the
ea36f4e4 36L<create|DBIx::Class::ResultSet/create>, L<find|DBIx::Class::ResultSet/find>,
37L<next|DBIx::Class::ResultSet/next> and L<all|DBIx::Class::ResultSet/all> methods,
38as well as invocations of 'single' (
39L<belongs_to|DBIx::Class::Relationship/belongs_to>,
40L<has_one|DBIx::Class::Relationship/has_one> or
41L<might_have|DBIx::Class::Relationship/might_have>)
42relationship accessors of L<DBIx::Class::Row> objects.
a2531bf2 43
7624b19f 44=head1 METHODS
45
8091aa91 46=head2 new
7624b19f 47
a2531bf2 48 my $row = My::Class->new(\%attrs);
49
50 my $row = $schema->resultset('MySource')->new(\%colsandvalues);
51
52=over
53
54=item Arguments: \%attrs or \%colsandvalues
55
56=item Returns: A Row object
7624b19f 57
a2531bf2 58=back
59
60While you can create a new row object by calling C<new> directly on
61this class, you are better off calling it on a
62L<DBIx::Class::ResultSet> object.
63
64When calling it directly, you will not get a complete, usable row
65object until you pass or set the C<source_handle> attribute, to a
66L<DBIx::Class::ResultSource> instance that is attached to a
67L<DBIx::Class::Schema> with a valid connection.
68
69C<$attrs> is a hashref of column name, value data. It can also contain
70some other attributes such as the C<source_handle>.
7624b19f 71
33dd4e80 72Passing an object, or an arrayref of objects as a value will call
73L<DBIx::Class::Relationship::Base/set_from_related> for you. When
74passed a hashref or an arrayref of hashrefs as the value, these will
75be turned into objects via new_related, and treated as if you had
76passed objects.
77
264f1571 78For a more involved explanation, see L<DBIx::Class::ResultSet/create>.
79
dc5f0ad3 80Please note that if a value is not passed to new, no value will be sent
81in the SQL INSERT call, and the column will therefore assume whatever
82default value was specified in your database. While DBIC will retrieve the
83value of autoincrement columns, it will never make an explicit database
84trip to retrieve default values assigned by the RDBMS. You can explicitly
85request that all values be fetched back from the database by calling
86L</discard_changes>, or you can supply an explicit C<undef> to columns
87with NULL as the default, and save yourself a SELECT.
88
89 CAVEAT:
90
91 The behavior described above will backfire if you use a foreign key column
92 with a database-defined default. If you call the relationship accessor on
93 an object that doesn't have a set value for the FK column, DBIC will throw
94 an exception, as it has no way of knowing the PK of the related object (if
95 there is one).
96
7624b19f 97=cut
98
33dd4e80 99## 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().
100## This only works because DBIC doesnt yet care to check whether the new_related objects have been passed all their mandatory columns
101## When doing the later insert, we need to make sure the PKs are set.
102## using _relationship_data in new and funky ways..
103## check Relationship::CascadeActions and Relationship::Accessor for compat
104## tests!
105
370f2ba2 106sub __new_related_find_or_new_helper {
107 my ($self, $relname, $data) = @_;
108 if ($self->__their_pk_needs_us($relname, $data)) {
de404241 109 MULTICREATE_DEBUG and warn "MC $self constructing $relname via new_result";
370f2ba2 110 return $self->result_source
111 ->related_source($relname)
112 ->resultset
113 ->new_result($data);
114 }
115 if ($self->result_source->pk_depends_on($relname, $data)) {
de404241 116 MULTICREATE_DEBUG and warn "MC $self constructing $relname via find_or_new";
370f2ba2 117 return $self->result_source
118 ->related_source($relname)
119 ->resultset
de404241 120 ->find_or_new($data);
370f2ba2 121 }
de404241 122 MULTICREATE_DEBUG and warn "MC $self constructing $relname via find_or_new_related";
370f2ba2 123 return $self->find_or_new_related($relname, $data);
124}
125
126sub __their_pk_needs_us { # this should maybe be in resultsource.
127 my ($self, $relname, $data) = @_;
128 my $source = $self->result_source;
129 my $reverse = $source->reverse_relationship_info($relname);
130 my $rel_source = $source->related_source($relname);
131 my $us = { $self->get_columns };
132 foreach my $key (keys %$reverse) {
133 # if their primary key depends on us, then we have to
134 # just create a result and we'll fill it out afterwards
135 return 1 if $rel_source->pk_depends_on($key, $us);
136 }
137 return 0;
138}
139
7624b19f 140sub new {
448f820f 141 my ($class, $attrs) = @_;
7624b19f 142 $class = ref $class if ref $class;
04786a4c 143
e60dc79f 144 my $new = {
145 _column_data => {},
146 };
04786a4c 147 bless $new, $class;
148
448f820f 149 if (my $handle = delete $attrs->{-source_handle}) {
150 $new->_source_handle($handle);
151 }
370f2ba2 152
153 my $source;
154 if ($source = delete $attrs->{-result_source}) {
e9fe476b 155 $new->result_source($source);
156 }
a6a280b9 157
09e1f723 158 if (my $related = delete $attrs->{-from_resultset}) {
159 @{$new->{_ignore_at_insert}={}}{@$related} = ();
160 }
161
7624b19f 162 if ($attrs) {
27f01d1f 163 $new->throw_exception("attrs must be a hashref")
164 unless ref($attrs) eq 'HASH';
61a622ee 165
166 my ($related,$inflated);
de7c7c53 167 ## Pretend all the rels are actual objects, unset below if not, for insert() to fix
168 $new->{_rel_in_storage} = 1;
8222f722 169
61a622ee 170 foreach my $key (keys %$attrs) {
171 if (ref $attrs->{$key}) {
af2d42c0 172 ## Can we extract this lot to use with update(_or .. ) ?
370f2ba2 173 confess "Can't do multi-create without result source" unless $source;
174 my $info = $source->relationship_info($key);
61a622ee 175 if ($info && $info->{attrs}{accessor}
c4a30d56 176 && $info->{attrs}{accessor} eq 'single')
61a622ee 177 {
de7c7c53 178 my $rel_obj = delete $attrs->{$key};
33dd4e80 179 if(!Scalar::Util::blessed($rel_obj)) {
370f2ba2 180 $rel_obj = $new->__new_related_find_or_new_helper($key, $rel_obj);
33dd4e80 181 }
2bc3c81e 182
e0cdf2cb 183 if ($rel_obj->in_storage) {
184 $new->set_from_related($key, $rel_obj);
185 } else {
186 $new->{_rel_in_storage} = 0;
09e1f723 187 MULTICREATE_DEBUG and warn "MC $new uninserted $key $rel_obj\n";
e0cdf2cb 188 }
2bc3c81e 189
de7c7c53 190 $related->{$key} = $rel_obj;
61a622ee 191 next;
33dd4e80 192 } elsif ($info && $info->{attrs}{accessor}
193 && $info->{attrs}{accessor} eq 'multi'
194 && ref $attrs->{$key} eq 'ARRAY') {
2ec8e594 195 my $others = delete $attrs->{$key};
e0cdf2cb 196 my $total = @$others;
197 my @objects;
198 foreach my $idx (0 .. $#$others) {
199 my $rel_obj = $others->[$idx];
2ec8e594 200 if(!Scalar::Util::blessed($rel_obj)) {
370f2ba2 201 $rel_obj = $new->__new_related_find_or_new_helper($key, $rel_obj);
33dd4e80 202 }
2bc3c81e 203
e0cdf2cb 204 if ($rel_obj->in_storage) {
205 $new->set_from_related($key, $rel_obj);
206 } else {
207 $new->{_rel_in_storage} = 0;
208 MULTICREATE_DEBUG and
09e1f723 209 warn "MC $new uninserted $key $rel_obj (${\($idx+1)} of $total)\n";
e0cdf2cb 210 }
370f2ba2 211 $new->set_from_related($key, $rel_obj) if $rel_obj->in_storage;
e0cdf2cb 212 push(@objects, $rel_obj);
2ec8e594 213 }
e0cdf2cb 214 $related->{$key} = \@objects;
2ec8e594 215 next;
216 } elsif ($info && $info->{attrs}{accessor}
217 && $info->{attrs}{accessor} eq 'filter')
61a622ee 218 {
33dd4e80 219 ## 'filter' should disappear and get merged in with 'single' above!
2ec8e594 220 my $rel_obj = delete $attrs->{$key};
33dd4e80 221 if(!Scalar::Util::blessed($rel_obj)) {
370f2ba2 222 $rel_obj = $new->__new_related_find_or_new_helper($key, $rel_obj);
33dd4e80 223 }
e0cdf2cb 224 unless ($rel_obj->in_storage) {
225 $new->{_rel_in_storage} = 0;
09e1f723 226 MULTICREATE_DEBUG and warn "MC $new uninserted $key $rel_obj";
e0cdf2cb 227 }
33dd4e80 228 $inflated->{$key} = $rel_obj;
61a622ee 229 next;
2ec8e594 230 } elsif ($class->has_column($key)
231 && $class->column_info($key)->{_inflate_info}) {
61a622ee 232 $inflated->{$key} = $attrs->{$key};
233 next;
234 }
235 }
236 $new->throw_exception("No such column $key on $class")
237 unless $class->has_column($key);
238 $new->store_column($key => $attrs->{$key});
7624b19f 239 }
f90375dd 240
61a622ee 241 $new->{_relationship_data} = $related if $related;
242 $new->{_inflated_column} = $inflated if $inflated;
7624b19f 243 }
04786a4c 244
7624b19f 245 return $new;
246}
247
8091aa91 248=head2 insert
7624b19f 249
a2531bf2 250 $row->insert;
251
252=over
7624b19f 253
a2531bf2 254=item Arguments: none
255
256=item Returns: The Row object
257
258=back
259
260Inserts an object previously created by L</new> into the database if
261it isn't already in there. Returns the object itself. Requires the
262object's result source to be set, or the class to have a
263result_source_instance method. To insert an entirely new row into
264the database, use C<create> (see L<DBIx::Class::ResultSet/create>).
7624b19f 265
e91e756c 266To fetch an uninserted row object, call
267L<new|DBIx::Class::ResultSet/new> on a resultset.
268
264f1571 269This will also insert any uninserted, related objects held inside this
270one, see L<DBIx::Class::ResultSet/create> for more details.
271
7624b19f 272=cut
273
274sub insert {
275 my ($self) = @_;
276 return $self if $self->in_storage;
6aba697f 277 my $source = $self->result_source;
278 $source ||= $self->result_source($self->result_source_instance)
097d3227 279 if $self->can('result_source_instance');
aeb1bf75 280 $self->throw_exception("No result_source set on this object; can't insert")
281 unless $source;
6e399b4f 282
9c6d6d93 283 my $rollback_guard;
284
33dd4e80 285 # Check if we stored uninserted relobjs here in new()
33dd4e80 286 my %related_stuff = (%{$self->{_relationship_data} || {}},
287 %{$self->{_inflated_column} || {}});
9c6d6d93 288
ae66ef47 289 if(!$self->{_rel_in_storage}) {
8222f722 290
9c6d6d93 291 # The guard will save us if we blow out of this scope via die
1bc193ac 292 $rollback_guard = $source->storage->txn_scope_guard;
9c6d6d93 293
8222f722 294 ## Should all be in relationship_data, but we need to get rid of the
295 ## 'filter' reltype..
296 ## These are the FK rels, need their IDs for the insert.
9c6d6d93 297
298 my @pri = $self->primary_columns;
299
300 REL: foreach my $relname (keys %related_stuff) {
a8c98174 301
302 my $rel_obj = $related_stuff{$relname};
303
304 next REL unless (Scalar::Util::blessed($rel_obj)
305 && $rel_obj->isa('DBIx::Class::Row'));
306
370f2ba2 307 next REL unless $source->pk_depends_on(
308 $relname, { $rel_obj->get_columns }
309 );
9c6d6d93 310
de404241 311 MULTICREATE_DEBUG and warn "MC $self pre-reconstructing $relname $rel_obj\n";
e0cdf2cb 312
de404241 313 my $them = { %{$rel_obj->{_relationship_data} || {} }, $rel_obj->get_inflated_columns };
8cfe052c 314 my $re = $self->result_source
315 ->related_source($relname)
316 ->resultset
317 ->find_or_create($them);
de404241 318 %{$rel_obj} = %{$re};
a8c98174 319 $self->set_from_related($relname, $rel_obj);
320 delete $related_stuff{$relname};
33dd4e80 321 }
322 }
6e399b4f 323
09e1f723 324 MULTICREATE_DEBUG and do {
325 no warnings 'uninitialized';
326 warn "MC $self inserting (".join(', ', $self->get_columns).")\n";
327 };
ef5f6b0a 328 my $updated_cols = $source->storage->insert($source, { $self->get_columns });
645de900 329 foreach my $col (keys %$updated_cols) {
330 $self->store_column($col, $updated_cols->{$col});
331 }
ac8e89d7 332
333 ## PK::Auto
3fda409f 334 my @auto_pri = grep {
335 !defined $self->get_column($_) ||
336 ref($self->get_column($_)) eq 'SCALAR'
337 } $self->primary_columns;
338
339 if (@auto_pri) {
340 #$self->throw_exception( "More than one possible key found for auto-inc on ".ref $self )
341 # if defined $too_many;
e0cdf2cb 342 MULTICREATE_DEBUG and warn "MC $self fetching missing PKs ".join(', ', @auto_pri)."\n";
ac8e89d7 343 my $storage = $self->result_source->storage;
344 $self->throw_exception( "Missing primary key but Storage doesn't support last_insert_id" )
345 unless $storage->can('last_insert_id');
3fda409f 346 my @ids = $storage->last_insert_id($self->result_source,@auto_pri);
347 $self->throw_exception( "Can't get last insert id" )
348 unless (@ids == @auto_pri);
349 $self->store_column($auto_pri[$_] => $ids[$_]) for 0 .. $#ids;
e0cdf2cb 350#use Data::Dumper; warn Dumper($self);
ac8e89d7 351 }
33dd4e80 352
e0cdf2cb 353
370f2ba2 354 $self->{_dirty_columns} = {};
355 $self->{related_resultsets} = {};
356
ae66ef47 357 if(!$self->{_rel_in_storage}) {
09e1f723 358 ## Now do the relationships that need our ID (has_many etc.)
8222f722 359 foreach my $relname (keys %related_stuff) {
9c6d6d93 360 my $rel_obj = $related_stuff{$relname};
361 my @cands;
362 if (Scalar::Util::blessed($rel_obj)
363 && $rel_obj->isa('DBIx::Class::Row')) {
364 @cands = ($rel_obj);
365 } elsif (ref $rel_obj eq 'ARRAY') {
366 @cands = @$rel_obj;
367 }
368 if (@cands) {
369 my $reverse = $source->reverse_relationship_info($relname);
370 foreach my $obj (@cands) {
371 $obj->set_from_related($_, $self) for keys %$reverse;
e912f5f0 372 my $them = { %{$obj->{_relationship_data} || {} }, $obj->get_inflated_columns };
370f2ba2 373 if ($self->__their_pk_needs_us($relname, $them)) {
09e1f723 374 if (exists $self->{_ignore_at_insert}{$relname}) {
375 MULTICREATE_DEBUG and warn "MC $self skipping post-insert on $relname";
376 } else {
377 MULTICREATE_DEBUG and warn "MC $self re-creating $relname $obj";
de404241 378 my $re = $self->result_source
379 ->related_source($relname)
380 ->resultset
381 ->find_or_create($them);
09e1f723 382 %{$obj} = %{$re};
383 MULTICREATE_DEBUG and warn "MC $self new $relname $obj";
384 }
370f2ba2 385 } else {
e0cdf2cb 386 MULTICREATE_DEBUG and warn "MC $self post-inserting $obj";
370f2ba2 387 $obj->insert();
388 }
8222f722 389 }
33dd4e80 390 }
391 }
09e1f723 392 delete $self->{_ignore_at_insert};
1bc193ac 393 $rollback_guard->commit;
33dd4e80 394 }
33dd4e80 395
7624b19f 396 $self->in_storage(1);
729b29ae 397 undef $self->{_orig_ident};
7624b19f 398 return $self;
399}
400
8091aa91 401=head2 in_storage
7624b19f 402
a2531bf2 403 $row->in_storage; # Get value
404 $row->in_storage(1); # Set value
405
406=over
407
408=item Arguments: none or 1|0
409
410=item Returns: 1|0
411
412=back
7624b19f 413
e91e756c 414Indicates whether the object exists as a row in the database or
415not. This is set to true when L<DBIx::Class::ResultSet/find>,
416L<DBIx::Class::ResultSet/create> or L<DBIx::Class::ResultSet/insert>
417are used.
418
419Creating a row object using L<DBIx::Class::ResultSet/new>, or calling
420L</delete> on one, sets it to false.
7624b19f 421
422=cut
423
424sub in_storage {
425 my ($self, $val) = @_;
426 $self->{_in_storage} = $val if @_ > 1;
427 return $self->{_in_storage};
428}
429
8091aa91 430=head2 update
7624b19f 431
a2531bf2 432 $row->update(\%columns?)
433
434=over
7624b19f 435
a2531bf2 436=item Arguments: none or a hashref
7624b19f 437
a2531bf2 438=item Returns: The Row object
439
440=back
441
442Throws an exception if the row object is not yet in the database,
443according to L</in_storage>.
444
445This method issues an SQL UPDATE query to commit any changes to the
446object to the database if required.
447
448Also takes an optional hashref of C<< column_name => value> >> pairs
449to update on the object first. Be aware that the hashref will be
450passed to C<set_inflated_columns>, which might edit it in place, so
451don't rely on it being the same after a call to C<update>. If you
452need to preserve the hashref, it is sufficient to pass a shallow copy
453to C<update>, e.g. ( { %{ $href } } )
d5d833d9 454
05d1bc9c 455If the values passed or any of the column values set on the object
456contain scalar references, eg:
457
a2531bf2 458 $row->last_modified(\'NOW()');
05d1bc9c 459 # OR
a2531bf2 460 $row->update({ last_modified => \'NOW()' });
05d1bc9c 461
462The update will pass the values verbatim into SQL. (See
463L<SQL::Abstract> docs). The values in your Row object will NOT change
464as a result of the update call, if you want the object to be updated
465with the actual values from the database, call L</discard_changes>
466after the update.
467
a2531bf2 468 $row->update()->discard_changes();
469
470To determine before calling this method, which column values have
471changed and will be updated, call L</get_dirty_columns>.
472
473To check if any columns will be updated, call L</is_changed>.
474
475To force a column to be updated, call L</make_column_dirty> before
476this method.
05d1bc9c 477
7624b19f 478=cut
479
480sub update {
481 my ($self, $upd) = @_;
701da8c4 482 $self->throw_exception( "Not in database" ) unless $self->in_storage;
4b12b3c2 483 my $ident_cond = $self->ident_condition;
484 $self->throw_exception("Cannot safely update a row in a PK-less table")
485 if ! keys %$ident_cond;
6e399b4f 486
bacf6f12 487 $self->set_inflated_columns($upd) if $upd;
5a9e0e60 488 my %to_update = $self->get_dirty_columns;
489 return $self unless keys %to_update;
88cb6a1d 490 my $rows = $self->result_source->storage->update(
f4afcd5d 491 $self->result_source, \%to_update,
492 $self->{_orig_ident} || $ident_cond
493 );
7624b19f 494 if ($rows == 0) {
701da8c4 495 $self->throw_exception( "Can't update ${self}: row not found" );
7624b19f 496 } elsif ($rows > 1) {
701da8c4 497 $self->throw_exception("Can't update ${self}: updated more than one row");
7624b19f 498 }
499 $self->{_dirty_columns} = {};
64acc2bc 500 $self->{related_resultsets} = {};
729b29ae 501 undef $self->{_orig_ident};
7624b19f 502 return $self;
503}
504
8091aa91 505=head2 delete
7624b19f 506
a2531bf2 507 $row->delete
508
509=over
510
511=item Arguments: none
7624b19f 512
a2531bf2 513=item Returns: The Row object
514
515=back
516
517Throws an exception if the object is not in the database according to
518L</in_storage>. Runs an SQL DELETE statement using the primary key
519values to locate the row.
520
521The object is still perfectly usable, but L</in_storage> will
ea36f4e4 522now return 0 and the object must be reinserted using L</insert>
a2531bf2 523before it can be used to L</update> the row again.
524
525If you delete an object in a class with a C<has_many> relationship, an
526attempt is made to delete all the related objects as well. To turn
527this behaviour off, pass C<< cascade_delete => 0 >> in the C<$attr>
528hashref of the relationship, see L<DBIx::Class::Relationship>. Any
529database-level cascade or restrict will take precedence over a
530DBIx-Class-based cascading delete.
531
b1d16ffd 532If you delete an object within a txn_do() (see L<DBIx::Class::Storage/txn_do>)
533and the transaction subsequently fails, the row object will remain marked as
534not being in storage. If you know for a fact that the object is still in
535storage (i.e. by inspecting the cause of the transaction's failure), you can
536use C<< $obj->in_storage(1) >> to restore consistency between the object and
537the database. This would allow a subsequent C<< $obj->delete >> to work
538as expected.
539
a2531bf2 540See also L<DBIx::Class::ResultSet/delete>.
7624b19f 541
542=cut
543
544sub delete {
545 my $self = shift;
546 if (ref $self) {
701da8c4 547 $self->throw_exception( "Not in database" ) unless $self->in_storage;
728e60a3 548 my $ident_cond = $self->{_orig_ident} || $self->ident_condition;
4b12b3c2 549 $self->throw_exception("Cannot safely delete a row in a PK-less table")
550 if ! keys %$ident_cond;
e0f56292 551 foreach my $column (keys %$ident_cond) {
75d07914 552 $self->throw_exception("Can't delete the object unless it has loaded the primary keys")
553 unless exists $self->{_column_data}{$column};
e0f56292 554 }
88cb6a1d 555 $self->result_source->storage->delete(
7af8b477 556 $self->result_source, $ident_cond);
7624b19f 557 $self->in_storage(undef);
7624b19f 558 } else {
701da8c4 559 $self->throw_exception("Can't do class delete without a ResultSource instance")
097d3227 560 unless $self->can('result_source_instance');
aeb1bf75 561 my $attrs = @_ > 1 && ref $_[$#_] eq 'HASH' ? { %{pop(@_)} } : {};
562 my $query = ref $_[0] eq 'HASH' ? $_[0] : {@_};
097d3227 563 $self->result_source_instance->resultset->search(@_)->delete;
7624b19f 564 }
565 return $self;
566}
567
8091aa91 568=head2 get_column
7624b19f 569
a2531bf2 570 my $val = $row->get_column($col);
571
572=over
573
574=item Arguments: $columnname
575
576=item Returns: The value of the column
577
578=back
579
580Throws an exception if the column name given doesn't exist according
581to L</has_column>.
7624b19f 582
e91e756c 583Returns a raw column value from the row object, if it has already
584been fetched from the database or set by an accessor.
585
586If an L<inflated value|DBIx::Class::InflateColumn> has been set, it
587will be deflated and returned.
7624b19f 588
ea36f4e4 589Note that if you used the C<columns> or the C<select/as>
590L<search attributes|DBIx::Class::ResultSet/ATTRIBUTES> on the resultset from
591which C<$row> was derived, and B<did not include> C<$columnname> in the list,
592this method will return C<undef> even if the database contains some value.
593
a2531bf2 594To retrieve all loaded column values as a hash, use L</get_columns>.
595
7624b19f 596=cut
597
598sub get_column {
599 my ($self, $column) = @_;
701da8c4 600 $self->throw_exception( "Can't fetch data as class method" ) unless ref $self;
aeb1bf75 601 return $self->{_column_data}{$column} if exists $self->{_column_data}{$column};
61a622ee 602 if (exists $self->{_inflated_column}{$column}) {
603 return $self->store_column($column,
604 $self->_deflated_column($column, $self->{_inflated_column}{$column}));
605 }
701da8c4 606 $self->throw_exception( "No such column '${column}'" ) unless $self->has_column($column);
7624b19f 607 return undef;
608}
609
9b83fccd 610=head2 has_column_loaded
611
a2531bf2 612 if ( $row->has_column_loaded($col) ) {
9b83fccd 613 print "$col has been loaded from db";
614 }
615
a2531bf2 616=over
617
618=item Arguments: $columnname
619
620=item Returns: 0|1
621
622=back
623
9b83fccd 624Returns a true value if the column value has been loaded from the
625database (or set locally).
626
627=cut
628
def81720 629sub has_column_loaded {
630 my ($self, $column) = @_;
631 $self->throw_exception( "Can't call has_column data as class method" ) unless ref $self;
61a622ee 632 return 1 if exists $self->{_inflated_column}{$column};
aeb1bf75 633 return exists $self->{_column_data}{$column};
def81720 634}
635
8091aa91 636=head2 get_columns
076a6864 637
a2531bf2 638 my %data = $row->get_columns;
639
640=over
641
642=item Arguments: none
076a6864 643
a2531bf2 644=item Returns: A hash of columnname, value pairs.
645
646=back
647
648Returns all loaded column data as a hash, containing raw values. To
649get just one value for a particular column, use L</get_column>.
076a6864 650
651=cut
652
653sub get_columns {
654 my $self = shift;
61a622ee 655 if (exists $self->{_inflated_column}) {
656 foreach my $col (keys %{$self->{_inflated_column}}) {
657 $self->store_column($col, $self->_deflated_column($col, $self->{_inflated_column}{$col}))
c4a30d56 658 unless exists $self->{_column_data}{$col};
61a622ee 659 }
660 }
cb5f2eea 661 return %{$self->{_column_data}};
d7156e50 662}
663
664=head2 get_dirty_columns
665
a2531bf2 666 my %data = $row->get_dirty_columns;
667
668=over
669
670=item Arguments: none
d7156e50 671
a2531bf2 672=item Returns: A hash of column, value pairs
673
674=back
675
676Only returns the column, value pairs for those columns that have been
677changed on this object since the last L</update> or L</insert> call.
678
679See L</get_columns> to fetch all column/value pairs.
d7156e50 680
681=cut
682
683sub get_dirty_columns {
684 my $self = shift;
685 return map { $_ => $self->{_column_data}{$_} }
686 keys %{$self->{_dirty_columns}};
076a6864 687}
688
6dbea98e 689=head2 make_column_dirty
690
a2531bf2 691 $row->make_column_dirty($col)
692
693=over
694
695=item Arguments: $columnname
696
697=item Returns: undefined
698
699=back
700
701Throws an exception if the column does not exist.
702
703Marks a column as having been changed regardless of whether it has
704really changed.
6dbea98e 705
706=cut
707sub make_column_dirty {
708 my ($self, $column) = @_;
709
710 $self->throw_exception( "No such column '${column}'" )
711 unless exists $self->{_column_data}{$column} || $self->has_column($column);
712 $self->{_dirty_columns}{$column} = 1;
713}
714
ba4a6453 715=head2 get_inflated_columns
716
e91e756c 717 my %inflated_data = $obj->get_inflated_columns;
ba4a6453 718
a2531bf2 719=over
720
721=item Arguments: none
722
723=item Returns: A hash of column, object|value pairs
724
725=back
726
727Returns a hash of all column keys and associated values. Values for any
728columns set to use inflation will be inflated and returns as objects.
729
730See L</get_columns> to get the uninflated values.
731
732See L<DBIx::Class::InflateColumn> for how to setup inflation.
ba4a6453 733
734=cut
735
736sub get_inflated_columns {
737 my $self = shift;
738 return map {
739 my $accessor = $self->column_info($_)->{'accessor'} || $_;
740 ($_ => $self->$accessor);
de404241 741 } grep $self->has_column_loaded($_), $self->columns;
ba4a6453 742}
743
8091aa91 744=head2 set_column
7624b19f 745
a2531bf2 746 $row->set_column($col => $val);
747
748=over
749
750=item Arguments: $columnname, $value
751
752=item Returns: $value
753
754=back
7624b19f 755
e91e756c 756Sets a raw column value. If the new value is different from the old one,
a2531bf2 757the column is marked as dirty for when you next call L</update>.
7624b19f 758
ea36f4e4 759If passed an object or reference as a value, this method will happily
760attempt to store it, and a later L</insert> or L</update> will try and
a2531bf2 761stringify/numify as appropriate. To set an object to be deflated
762instead, see L</set_inflated_columns>.
e91e756c 763
7624b19f 764=cut
765
766sub set_column {
1d0057bd 767 my ($self, $column, $new_value) = @_;
768
729b29ae 769 $self->{_orig_ident} ||= $self->ident_condition;
1d0057bd 770 my $old_value = $self->get_column($column);
771
772 $self->store_column($column, $new_value);
87772e46 773 $self->{_dirty_columns}{$column} = 1
1d0057bd 774 if (defined $old_value xor defined $new_value) || (defined $old_value && $old_value ne $new_value);
e60dc79f 775
776 # XXX clear out the relation cache for this column
777 delete $self->{related_resultsets}{$column};
778
1d0057bd 779 return $new_value;
7624b19f 780}
781
8091aa91 782=head2 set_columns
076a6864 783
a2531bf2 784 $row->set_columns({ $col => $val, ... });
785
786=over
076a6864 787
a2531bf2 788=item Arguments: \%columndata
789
790=item Returns: The Row object
791
792=back
793
794Sets multiple column, raw value pairs at once.
795
796Works as L</set_column>.
076a6864 797
798=cut
799
800sub set_columns {
801 my ($self,$data) = @_;
a2ca474b 802 foreach my $col (keys %$data) {
803 $self->set_column($col,$data->{$col});
076a6864 804 }
c01ab172 805 return $self;
076a6864 806}
807
bacf6f12 808=head2 set_inflated_columns
809
a2531bf2 810 $row->set_inflated_columns({ $col => $val, $relname => $obj, ... });
811
812=over
813
814=item Arguments: \%columndata
815
816=item Returns: The Row object
817
818=back
819
820Sets more than one column value at once. Any inflated values are
821deflated and the raw values stored.
bacf6f12 822
a2531bf2 823Any related values passed as Row objects, using the relation name as a
824key, are reduced to the appropriate foreign key values and stored. If
825instead of related row objects, a hashref of column, value data is
826passed, will create the related object first then store.
827
828Will even accept arrayrefs of data as a value to a
829L<DBIx::Class::Relationship/has_many> key, and create the related
830objects if necessary.
831
832Be aware that the input hashref might be edited in place, so dont rely
833on it being the same after a call to C<set_inflated_columns>. If you
834need to preserve the hashref, it is sufficient to pass a shallow copy
835to C<set_inflated_columns>, e.g. ( { %{ $href } } )
836
837See also L<DBIx::Class::Relationship::Base/set_from_related>.
bacf6f12 838
839=cut
840
841sub set_inflated_columns {
842 my ( $self, $upd ) = @_;
843 foreach my $key (keys %$upd) {
844 if (ref $upd->{$key}) {
845 my $info = $self->relationship_info($key);
846 if ($info && $info->{attrs}{accessor}
847 && $info->{attrs}{accessor} eq 'single')
848 {
849 my $rel = delete $upd->{$key};
850 $self->set_from_related($key => $rel);
a7be8807 851 $self->{_relationship_data}{$key} = $rel;
bacf6f12 852 } elsif ($info && $info->{attrs}{accessor}
a7be8807 853 && $info->{attrs}{accessor} eq 'multi') {
854 $self->throw_exception(
855 "Recursive update is not supported over relationships of type multi ($key)"
856 );
bacf6f12 857 }
858 elsif ($self->has_column($key)
859 && exists $self->column_info($key)->{_inflate_info})
860 {
a7be8807 861 $self->set_inflated_column($key, delete $upd->{$key});
bacf6f12 862 }
863 }
864 }
865 $self->set_columns($upd);
866}
867
8091aa91 868=head2 copy
076a6864 869
870 my $copy = $orig->copy({ change => $to, ... });
871
a2531bf2 872=over
873
874=item Arguments: \%replacementdata
875
876=item Returns: The Row object copy
877
878=back
879
880Inserts a new row into the database, as a copy of the original
881object. If a hashref of replacement data is supplied, these will take
882precedence over data in the original.
883
884If the row has related objects in a
885L<DBIx::Class::Relationship/has_many> then those objects may be copied
886too depending on the L<cascade_copy|DBIx::Class::Relationship>
887relationship attribute.
076a6864 888
889=cut
890
c01ab172 891sub copy {
892 my ($self, $changes) = @_;
333cce60 893 $changes ||= {};
fde6e28e 894 my $col_data = { %{$self->{_column_data}} };
895 foreach my $col (keys %$col_data) {
896 delete $col_data->{$col}
897 if $self->result_source->column_info($col)->{is_auto_increment};
898 }
04786a4c 899
900 my $new = { _column_data => $col_data };
901 bless $new, ref $self;
902
83419ec6 903 $new->result_source($self->result_source);
bacf6f12 904 $new->set_inflated_columns($changes);
333cce60 905 $new->insert;
35688220 906
907 # Its possible we'll have 2 relations to the same Source. We need to make
908 # sure we don't try to insert the same row twice esle we'll violate unique
909 # constraints
910 my $rels_copied = {};
911
333cce60 912 foreach my $rel ($self->result_source->relationships) {
913 my $rel_info = $self->result_source->relationship_info($rel);
35688220 914
915 next unless $rel_info->{attrs}{cascade_copy};
916
917 my $resolved = $self->result_source->resolve_condition(
918 $rel_info->{cond}, $rel, $new
919 );
920
921 my $copied = $rels_copied->{ $rel_info->{source} } ||= {};
922 foreach my $related ($self->search_related($rel)) {
923 my $id_str = join("\0", $related->id);
924 next if $copied->{$id_str};
925 $copied->{$id_str} = 1;
926 my $rel_copy = $related->copy($resolved);
333cce60 927 }
35688220 928
333cce60 929 }
2c4c67b6 930 return $new;
c01ab172 931}
932
8091aa91 933=head2 store_column
7624b19f 934
a2531bf2 935 $row->store_column($col => $val);
7624b19f 936
a2531bf2 937=over
938
939=item Arguments: $columnname, $value
940
ea36f4e4 941=item Returns: The value sent to storage
a2531bf2 942
943=back
944
945Set a raw value for a column without marking it as changed. This
946method is used internally by L</set_column> which you should probably
947be using.
948
949This is the lowest level at which data is set on a row object,
950extend this method to catch all data setting methods.
7624b19f 951
952=cut
953
954sub store_column {
955 my ($self, $column, $value) = @_;
75d07914 956 $self->throw_exception( "No such column '${column}'" )
d7156e50 957 unless exists $self->{_column_data}{$column} || $self->has_column($column);
75d07914 958 $self->throw_exception( "set_column called for ${column} without value" )
7624b19f 959 if @_ < 3;
960 return $self->{_column_data}{$column} = $value;
961}
962
b52e9bf8 963=head2 inflate_result
964
c01ab172 965 Class->inflate_result($result_source, \%me, \%prefetch?)
b52e9bf8 966
a2531bf2 967=over
968
969=item Arguments: $result_source, \%columndata, \%prefetcheddata
970
971=item Returns: A Row object
972
973=back
974
975All L<DBIx::Class::ResultSet> methods that retrieve data from the
976database and turn it into row objects call this method.
977
978Extend this method in your Result classes to hook into this process,
979for example to rebless the result into a different class.
980
981Reblessing can also be done more easily by setting C<result_class> in
982your Result class. See L<DBIx::Class::ResultSource/result_class>.
b52e9bf8 983
db2b2eb6 984Different types of results can also be created from a particular
985L<DBIx::Class::ResultSet>, see L<DBIx::Class::ResultSet/result_class>.
986
b52e9bf8 987=cut
988
989sub inflate_result {
c01ab172 990 my ($class, $source, $me, $prefetch) = @_;
aec3eff1 991
992 my ($source_handle) = $source;
993
994 if ($source->isa('DBIx::Class::ResultSourceHandle')) {
995 $source = $source_handle->resolve
996 } else {
997 $source_handle = $source->handle
998 }
999
04786a4c 1000 my $new = {
aec3eff1 1001 _source_handle => $source_handle,
04786a4c 1002 _column_data => $me,
1003 _in_storage => 1
1004 };
1005 bless $new, (ref $class || $class);
1006
7fb16f1a 1007 my $schema;
64acc2bc 1008 foreach my $pre (keys %{$prefetch||{}}) {
1009 my $pre_val = $prefetch->{$pre};
f9cc31dd 1010 my $pre_source = $source->related_source($pre);
a86b1efe 1011 $class->throw_exception("Can't prefetch non-existent relationship ${pre}")
1012 unless $pre_source;
0f66a01b 1013 if (ref($pre_val->[0]) eq 'ARRAY') { # multi
a86b1efe 1014 my @pre_objects;
1015 foreach my $pre_rec (@$pre_val) {
75d07914 1016 unless ($pre_source->primary_columns == grep { exists $pre_rec->[0]{$_}
5a5bec6c 1017 and defined $pre_rec->[0]{$_} } $pre_source->primary_columns) {
a86b1efe 1018 next;
1019 }
1020 push(@pre_objects, $pre_source->result_class->inflate_result(
1021 $pre_source, @{$pre_rec}));
1022 }
1023 $new->related_resultset($pre)->set_cache(\@pre_objects);
62e87ea8 1024 } elsif (defined $pre_val->[0]) {
a86b1efe 1025 my $fetched;
75d07914 1026 unless ($pre_source->primary_columns == grep { exists $pre_val->[0]{$_}
a86b1efe 1027 and !defined $pre_val->[0]{$_} } $pre_source->primary_columns)
1028 {
1029 $fetched = $pre_source->result_class->inflate_result(
75d07914 1030 $pre_source, @{$pre_val});
a86b1efe 1031 }
9809a6df 1032 $new->related_resultset($pre)->set_cache([ $fetched ]);
a86b1efe 1033 my $accessor = $source->relationship_info($pre)->{attrs}{accessor};
1034 $class->throw_exception("No accessor for prefetched $pre")
1035 unless defined $accessor;
1036 if ($accessor eq 'single') {
1037 $new->{_relationship_data}{$pre} = $fetched;
1038 } elsif ($accessor eq 'filter') {
1039 $new->{_inflated_column}{$pre} = $fetched;
1040 } else {
1041 $class->throw_exception("Prefetch not supported with accessor '$accessor'");
1042 }
b52e9bf8 1043 }
1044 }
7624b19f 1045 return $new;
1046}
1047
9b465d00 1048=head2 update_or_insert
7624b19f 1049
a2531bf2 1050 $row->update_or_insert
1051
1052=over
7624b19f 1053
a2531bf2 1054=item Arguments: none
1055
1056=item Returns: Result of update or insert operation
1057
1058=back
1059
1060L</Update>s the object if it's already in the database, according to
1061L</in_storage>, else L</insert>s it.
7624b19f 1062
9b83fccd 1063=head2 insert_or_update
1064
1065 $obj->insert_or_update
1066
1067Alias for L</update_or_insert>
1068
7624b19f 1069=cut
1070
370f2ba2 1071sub insert_or_update { shift->update_or_insert(@_) }
1072
9b465d00 1073sub update_or_insert {
7624b19f 1074 my $self = shift;
1075 return ($self->in_storage ? $self->update : $self->insert);
1076}
1077
8091aa91 1078=head2 is_changed
7624b19f 1079
a2531bf2 1080 my @changed_col_names = $row->is_changed();
1081 if ($row->is_changed()) { ... }
1082
1083=over
7624b19f 1084
a2531bf2 1085=item Arguments: none
1086
1087=item Returns: 0|1 or @columnnames
1088
1089=back
1090
1091In list context returns a list of columns with uncommited changes, or
9b83fccd 1092in scalar context returns a true value if there are uncommitted
1093changes.
1094
7624b19f 1095=cut
1096
1097sub is_changed {
1098 return keys %{shift->{_dirty_columns} || {}};
1099}
228dbcb4 1100
1101=head2 is_column_changed
1102
a2531bf2 1103 if ($row->is_column_changed('col')) { ... }
1104
1105=over
1106
1107=item Arguments: $columname
1108
1109=item Returns: 0|1
1110
1111=back
228dbcb4 1112
9b83fccd 1113Returns a true value if the column has uncommitted changes.
1114
228dbcb4 1115=cut
1116
1117sub is_column_changed {
1118 my( $self, $col ) = @_;
1119 return exists $self->{_dirty_columns}->{$col};
1120}
7624b19f 1121
097d3227 1122=head2 result_source
1123
a2531bf2 1124 my $resultsource = $row->result_source;
1125
1126=over
1127
1128=item Arguments: none
097d3227 1129
a2531bf2 1130=item Returns: a ResultSource instance
1131
1132=back
1133
1134Accessor to the L<DBIx::Class::ResultSource> this object was created from.
87c4e602 1135
aec3eff1 1136=cut
1137
1138sub result_source {
1139 my $self = shift;
1140
1141 if (@_) {
1142 $self->_source_handle($_[0]->handle);
1143 } else {
1144 $self->_source_handle->resolve;
1145 }
1146}
1147
9b83fccd 1148=head2 register_column
27f01d1f 1149
9b83fccd 1150 $column_info = { .... };
1151 $class->register_column($column_name, $column_info);
27f01d1f 1152
a2531bf2 1153=over
1154
1155=item Arguments: $columnname, \%columninfo
1156
1157=item Returns: undefined
1158
1159=back
1160
9b83fccd 1161Registers a column on the class. If the column_info has an 'accessor'
1162key, creates an accessor named after the value if defined; if there is
1163no such key, creates an accessor with the same name as the column
1f23a877 1164
9b83fccd 1165The column_info attributes are described in
1166L<DBIx::Class::ResultSource/add_columns>
1f23a877 1167
097d3227 1168=cut
1169
1f23a877 1170sub register_column {
1171 my ($class, $col, $info) = @_;
91b0fbd7 1172 my $acc = $col;
1173 if (exists $info->{accessor}) {
1174 return unless defined $info->{accessor};
1175 $acc = [ $info->{accessor}, $col ];
1176 }
1177 $class->mk_group_accessors('column' => $acc);
1f23a877 1178}
1179
a2531bf2 1180=head2 get_from_storage
1181
1182 my $copy = $row->get_from_storage($attrs)
1183
1184=over
b9b4e52f 1185
a2531bf2 1186=item Arguments: \%attrs
b9b4e52f 1187
a2531bf2 1188=item Returns: A Row object
1189
1190=back
1191
1192Fetches a fresh copy of the Row object from the database and returns it.
1193
1194If passed the \%attrs argument, will first apply these attributes to
1195the resultset used to find the row.
1196
1197This copy can then be used to compare to an existing row object, to
1198determine if any changes have been made in the database since it was
1199created.
1200
1201To just update your Row object with any latest changes from the
1202database, use L</discard_changes> instead.
1203
1204The \%attrs argument should be compatible with
1205L<DBIx::Class::ResultSet/ATTRIBUTES>.
7e38d850 1206
b9b4e52f 1207=cut
1208
a737512c 1209sub get_from_storage {
b9b4e52f 1210 my $self = shift @_;
7e38d850 1211 my $attrs = shift @_;
7e38d850 1212 my $resultset = $self->result_source->resultset;
1213
1214 if(defined $attrs) {
1215 $resultset = $resultset->search(undef, $attrs);
1216 }
1217
728e60a3 1218 return $resultset->find($self->{_orig_ident} || $self->ident_condition);
b9b4e52f 1219}
701da8c4 1220
5160b401 1221=head2 throw_exception
701da8c4 1222
a2531bf2 1223See L<DBIx::Class::Schema/throw_exception>.
701da8c4 1224
1225=cut
1226
1227sub throw_exception {
1228 my $self=shift;
66cab05c 1229 if (ref $self && ref $self->result_source && $self->result_source->schema) {
701da8c4 1230 $self->result_source->schema->throw_exception(@_);
1231 } else {
1232 croak(@_);
1233 }
1234}
1235
33cf6616 1236=head2 id
1237
a2531bf2 1238 my @pk = $row->id;
1239
1240=over
1241
1242=item Arguments: none
1243
1244=item Returns: A list of primary key values
1245
1246=back
1247
33cf6616 1248Returns the primary key(s) for a row. Can't be called as a class method.
f7043881 1249Actually implemented in L<DBIx::Class::PK>
33cf6616 1250
1251=head2 discard_changes
1252
a2531bf2 1253 $row->discard_changes
1254
1255=over
1256
1257=item Arguments: none
1258
1259=item Returns: nothing (updates object in-place)
1260
1261=back
1262
1263Retrieves and sets the row object data from the database, losing any
1264local changes made.
33cf6616 1265
1266This method can also be used to refresh from storage, retrieving any
1267changes made since the row was last read from storage. Actually
f7043881 1268implemented in L<DBIx::Class::PK>
33cf6616 1269
1270=cut
1271
7624b19f 12721;
1273
7624b19f 1274=head1 AUTHORS
1275
daec44b8 1276Matt S. Trout <mst@shadowcatsystems.co.uk>
7624b19f 1277
1278=head1 LICENSE
1279
1280You may distribute this code under the same terms as Perl itself.
1281
1282=cut