eleiminate vestigial code in PK::Auto
[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 ();
1edd1722 9
aec3eff1 10__PACKAGE__->mk_group_accessors('simple' => qw/_source_handle/);
8c49f629 11
75d07914 12=head1 NAME
7624b19f 13
14DBIx::Class::Row - Basic row methods
15
16=head1 SYNOPSIS
17
18=head1 DESCRIPTION
19
20This class is responsible for defining and doing basic operations on rows
1ea77c14 21derived from L<DBIx::Class::ResultSource> objects.
7624b19f 22
23=head1 METHODS
24
8091aa91 25=head2 new
7624b19f 26
27 my $obj = My::Class->new($attrs);
28
29Creates a new row object from column => value mappings passed as a hash ref
30
33dd4e80 31Passing an object, or an arrayref of objects as a value will call
32L<DBIx::Class::Relationship::Base/set_from_related> for you. When
33passed a hashref or an arrayref of hashrefs as the value, these will
34be turned into objects via new_related, and treated as if you had
35passed objects.
36
7624b19f 37=cut
38
33dd4e80 39## 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().
40## This only works because DBIC doesnt yet care to check whether the new_related objects have been passed all their mandatory columns
41## When doing the later insert, we need to make sure the PKs are set.
42## using _relationship_data in new and funky ways..
43## check Relationship::CascadeActions and Relationship::Accessor for compat
44## tests!
45
7624b19f 46sub new {
448f820f 47 my ($class, $attrs) = @_;
7624b19f 48 $class = ref $class if ref $class;
04786a4c 49
50 my $new = { _column_data => {} };
51 bless $new, $class;
52
448f820f 53 if (my $handle = delete $attrs->{-source_handle}) {
54 $new->_source_handle($handle);
55 }
e9fe476b 56 if (my $source = delete $attrs->{-result_source}) {
57 $new->result_source($source);
58 }
a6a280b9 59
7624b19f 60 if ($attrs) {
27f01d1f 61 $new->throw_exception("attrs must be a hashref")
62 unless ref($attrs) eq 'HASH';
61a622ee 63
64 my ($related,$inflated);
de7c7c53 65 ## Pretend all the rels are actual objects, unset below if not, for insert() to fix
66 $new->{_rel_in_storage} = 1;
8222f722 67
61a622ee 68 foreach my $key (keys %$attrs) {
69 if (ref $attrs->{$key}) {
af2d42c0 70 ## Can we extract this lot to use with update(_or .. ) ?
61a622ee 71 my $info = $class->relationship_info($key);
72 if ($info && $info->{attrs}{accessor}
c4a30d56 73 && $info->{attrs}{accessor} eq 'single')
61a622ee 74 {
de7c7c53 75 my $rel_obj = delete $attrs->{$key};
33dd4e80 76 if(!Scalar::Util::blessed($rel_obj)) {
2ec8e594 77 $rel_obj = $new->find_or_new_related($key, $rel_obj);
78 $new->{_rel_in_storage} = 0 unless ($rel_obj->in_storage);
33dd4e80 79 }
de7c7c53 80 $new->set_from_related($key, $rel_obj);
81 $related->{$key} = $rel_obj;
61a622ee 82 next;
33dd4e80 83 } elsif ($info && $info->{attrs}{accessor}
84 && $info->{attrs}{accessor} eq 'multi'
85 && ref $attrs->{$key} eq 'ARRAY') {
2ec8e594 86 my $others = delete $attrs->{$key};
87 foreach my $rel_obj (@$others) {
88 if(!Scalar::Util::blessed($rel_obj)) {
89 $rel_obj = $new->new_related($key, $rel_obj);
90 $new->{_rel_in_storage} = 0;
33dd4e80 91 }
2ec8e594 92 }
93 $related->{$key} = $others;
94 next;
95 } elsif ($info && $info->{attrs}{accessor}
96 && $info->{attrs}{accessor} eq 'filter')
61a622ee 97 {
33dd4e80 98 ## 'filter' should disappear and get merged in with 'single' above!
2ec8e594 99 my $rel_obj = delete $attrs->{$key};
33dd4e80 100 if(!Scalar::Util::blessed($rel_obj)) {
df78aeb1 101 $rel_obj = $new->find_or_new_related($key, $rel_obj);
102 $new->{_rel_in_storage} = 0 unless ($rel_obj->in_storage);
33dd4e80 103 }
104 $inflated->{$key} = $rel_obj;
61a622ee 105 next;
2ec8e594 106 } elsif ($class->has_column($key)
107 && $class->column_info($key)->{_inflate_info}) {
61a622ee 108 $inflated->{$key} = $attrs->{$key};
109 next;
110 }
111 }
de7c7c53 112 use Data::Dumper;
61a622ee 113 $new->throw_exception("No such column $key on $class")
114 unless $class->has_column($key);
115 $new->store_column($key => $attrs->{$key});
7624b19f 116 }
f90375dd 117
61a622ee 118 $new->{_relationship_data} = $related if $related;
119 $new->{_inflated_column} = $inflated if $inflated;
7624b19f 120 }
04786a4c 121
7624b19f 122 return $new;
123}
124
8091aa91 125=head2 insert
7624b19f 126
127 $obj->insert;
128
b8810cc5 129Inserts an object into the database if it isn't already in
130there. Returns the object itself. Requires the object's result source to
131be set, or the class to have a result_source_instance method. To insert
132an entirely new object into the database, use C<create> (see
133L<DBIx::Class::ResultSet/create>).
7624b19f 134
135=cut
136
137sub insert {
138 my ($self) = @_;
139 return $self if $self->in_storage;
6aba697f 140 my $source = $self->result_source;
141 $source ||= $self->result_source($self->result_source_instance)
097d3227 142 if $self->can('result_source_instance');
aeb1bf75 143 $self->throw_exception("No result_source set on this object; can't insert")
144 unless $source;
6e399b4f 145
33dd4e80 146 # Check if we stored uninserted relobjs here in new()
33dd4e80 147 my %related_stuff = (%{$self->{_relationship_data} || {}},
148 %{$self->{_inflated_column} || {}});
8222f722 149 if(!$self->{_rel_in_storage})
150 {
151 $source->storage->txn_begin;
152
153 ## Should all be in relationship_data, but we need to get rid of the
154 ## 'filter' reltype..
155 ## These are the FK rels, need their IDs for the insert.
156 foreach my $relname (keys %related_stuff) {
157 my $rel_obj = $related_stuff{$relname};
158 if(Scalar::Util::blessed($rel_obj) && $rel_obj->isa('DBIx::Class::Row')) {
159 $rel_obj->insert();
160 $self->set_from_related($relname, $rel_obj);
161 }
33dd4e80 162 }
163 }
6e399b4f 164
7af8b477 165 $source->storage->insert($source, { $self->get_columns });
ac8e89d7 166
167 ## PK::Auto
3fda409f 168 my @auto_pri = grep {
169 !defined $self->get_column($_) ||
170 ref($self->get_column($_)) eq 'SCALAR'
171 } $self->primary_columns;
172
173 if (@auto_pri) {
174 #$self->throw_exception( "More than one possible key found for auto-inc on ".ref $self )
175 # if defined $too_many;
ac8e89d7 176
177 my $storage = $self->result_source->storage;
178 $self->throw_exception( "Missing primary key but Storage doesn't support last_insert_id" )
179 unless $storage->can('last_insert_id');
3fda409f 180 my @ids = $storage->last_insert_id($self->result_source,@auto_pri);
181 $self->throw_exception( "Can't get last insert id" )
182 unless (@ids == @auto_pri);
183 $self->store_column($auto_pri[$_] => $ids[$_]) for 0 .. $#ids;
ac8e89d7 184 }
33dd4e80 185
8222f722 186 if(!$self->{_rel_in_storage})
187 {
188 ## Now do the has_many rels, that need $selfs ID.
189 foreach my $relname (keys %related_stuff) {
190 my $relobj = $related_stuff{$relname};
191 if(ref $relobj eq 'ARRAY') {
192 foreach my $obj (@$relobj) {
193 my $info = $self->relationship_info($relname);
194 ## What about multi-col FKs ?
195 my $key = $1 if($info && (keys %{$info->{cond}})[0] =~ /^foreign\.(\w+)/);
196 $obj->set_from_related($key, $self);
197 $obj->insert() if(!$obj->in_storage);
198 }
33dd4e80 199 }
200 }
8222f722 201 $source->storage->txn_commit;
33dd4e80 202 }
33dd4e80 203
7624b19f 204 $self->in_storage(1);
205 $self->{_dirty_columns} = {};
64acc2bc 206 $self->{related_resultsets} = {};
729b29ae 207 undef $self->{_orig_ident};
7624b19f 208 return $self;
209}
210
8091aa91 211=head2 in_storage
7624b19f 212
213 $obj->in_storage; # Get value
214 $obj->in_storage(1); # Set value
215
216Indicated whether the object exists as a row in the database or not
217
218=cut
219
220sub in_storage {
221 my ($self, $val) = @_;
222 $self->{_in_storage} = $val if @_ > 1;
223 return $self->{_in_storage};
224}
225
8091aa91 226=head2 update
7624b19f 227
d5d833d9 228 $obj->update \%columns?;
7624b19f 229
230Must be run on an object that is already in the database; issues an SQL
d3b0e369 231UPDATE query to commit any changes to the object to the database if
232required.
7624b19f 233
d5d833d9 234Also takes an options hashref of C<< column_name => value> pairs >> to update
235first. But be aware that this hashref might be edited in place, so dont rely on
8b621a87 236it being the same after a call to C<update>. If you need to preserve the hashref,
237it is sufficient to pass a shallow copy to C<update>, e.g. ( { %{ $href } } )
d5d833d9 238
7624b19f 239=cut
240
241sub update {
242 my ($self, $upd) = @_;
701da8c4 243 $self->throw_exception( "Not in database" ) unless $self->in_storage;
4b12b3c2 244 my $ident_cond = $self->ident_condition;
245 $self->throw_exception("Cannot safely update a row in a PK-less table")
246 if ! keys %$ident_cond;
6e399b4f 247
61a622ee 248 if ($upd) {
249 foreach my $key (keys %$upd) {
250 if (ref $upd->{$key}) {
251 my $info = $self->relationship_info($key);
252 if ($info && $info->{attrs}{accessor}
253 && $info->{attrs}{accessor} eq 'single')
254 {
255 my $rel = delete $upd->{$key};
256 $self->set_from_related($key => $rel);
257 $self->{_relationship_data}{$key} = $rel;
af2d42c0 258 } elsif ($info && $info->{attrs}{accessor}
259 && $info->{attrs}{accessor} eq 'multi'
260 && ref $upd->{$key} eq 'ARRAY') {
261 my $others = delete $upd->{$key};
262 foreach my $rel_obj (@$others) {
263 if(!Scalar::Util::blessed($rel_obj)) {
264 $rel_obj = $self->create_related($key, $rel_obj);
265 }
266 }
267 $self->{_relationship_data}{$key} = $others;
268# $related->{$key} = $others;
269 next;
270 }
61a622ee 271 elsif ($self->has_column($key)
272 && exists $self->column_info($key)->{_inflate_info})
273 {
274 $self->set_inflated_column($key, delete $upd->{$key});
275 }
276 }
277 }
278 $self->set_columns($upd);
279 }
5a9e0e60 280 my %to_update = $self->get_dirty_columns;
281 return $self unless keys %to_update;
88cb6a1d 282 my $rows = $self->result_source->storage->update(
f4afcd5d 283 $self->result_source, \%to_update,
284 $self->{_orig_ident} || $ident_cond
285 );
7624b19f 286 if ($rows == 0) {
701da8c4 287 $self->throw_exception( "Can't update ${self}: row not found" );
7624b19f 288 } elsif ($rows > 1) {
701da8c4 289 $self->throw_exception("Can't update ${self}: updated more than one row");
7624b19f 290 }
291 $self->{_dirty_columns} = {};
64acc2bc 292 $self->{related_resultsets} = {};
729b29ae 293 undef $self->{_orig_ident};
7624b19f 294 return $self;
295}
296
8091aa91 297=head2 delete
7624b19f 298
299 $obj->delete
300
b8810cc5 301Deletes the object from the database. The object is still perfectly
61a622ee 302usable, but C<< ->in_storage() >> will now return 0 and the object must
303reinserted using C<< ->insert() >> before C<< ->update() >> can be used
b8810cc5 304on it. If you delete an object in a class with a C<has_many>
305relationship, all the related objects will be deleted as well. To turn
306this behavior off, pass C<cascade_delete => 0> in the C<$attr>
307hashref. Any database-level cascade or restrict will take precedence
308over a DBIx-Class-based cascading delete. See also L<DBIx::Class::ResultSet/delete>.
7624b19f 309
310=cut
311
312sub delete {
313 my $self = shift;
314 if (ref $self) {
701da8c4 315 $self->throw_exception( "Not in database" ) unless $self->in_storage;
4b12b3c2 316 my $ident_cond = $self->ident_condition;
317 $self->throw_exception("Cannot safely delete a row in a PK-less table")
318 if ! keys %$ident_cond;
e0f56292 319 foreach my $column (keys %$ident_cond) {
75d07914 320 $self->throw_exception("Can't delete the object unless it has loaded the primary keys")
321 unless exists $self->{_column_data}{$column};
e0f56292 322 }
88cb6a1d 323 $self->result_source->storage->delete(
7af8b477 324 $self->result_source, $ident_cond);
7624b19f 325 $self->in_storage(undef);
7624b19f 326 } else {
701da8c4 327 $self->throw_exception("Can't do class delete without a ResultSource instance")
097d3227 328 unless $self->can('result_source_instance');
aeb1bf75 329 my $attrs = @_ > 1 && ref $_[$#_] eq 'HASH' ? { %{pop(@_)} } : {};
330 my $query = ref $_[0] eq 'HASH' ? $_[0] : {@_};
097d3227 331 $self->result_source_instance->resultset->search(@_)->delete;
7624b19f 332 }
333 return $self;
334}
335
8091aa91 336=head2 get_column
7624b19f 337
338 my $val = $obj->get_column($col);
339
61a622ee 340Gets a column value from a row object. Does not do any queries; the column
341must have already been fetched from the database and stored in the object. If
342there is an inflated value stored that has not yet been deflated, it is deflated
343when the method is invoked.
7624b19f 344
345=cut
346
347sub get_column {
348 my ($self, $column) = @_;
701da8c4 349 $self->throw_exception( "Can't fetch data as class method" ) unless ref $self;
aeb1bf75 350 return $self->{_column_data}{$column} if exists $self->{_column_data}{$column};
61a622ee 351 if (exists $self->{_inflated_column}{$column}) {
352 return $self->store_column($column,
353 $self->_deflated_column($column, $self->{_inflated_column}{$column}));
354 }
701da8c4 355 $self->throw_exception( "No such column '${column}'" ) unless $self->has_column($column);
7624b19f 356 return undef;
357}
358
9b83fccd 359=head2 has_column_loaded
360
361 if ( $obj->has_column_loaded($col) ) {
362 print "$col has been loaded from db";
363 }
364
365Returns a true value if the column value has been loaded from the
366database (or set locally).
367
368=cut
369
def81720 370sub has_column_loaded {
371 my ($self, $column) = @_;
372 $self->throw_exception( "Can't call has_column data as class method" ) unless ref $self;
61a622ee 373 return 1 if exists $self->{_inflated_column}{$column};
aeb1bf75 374 return exists $self->{_column_data}{$column};
def81720 375}
376
8091aa91 377=head2 get_columns
076a6864 378
379 my %data = $obj->get_columns;
380
8091aa91 381Does C<get_column>, for all column values at once.
076a6864 382
383=cut
384
385sub get_columns {
386 my $self = shift;
61a622ee 387 if (exists $self->{_inflated_column}) {
388 foreach my $col (keys %{$self->{_inflated_column}}) {
389 $self->store_column($col, $self->_deflated_column($col, $self->{_inflated_column}{$col}))
c4a30d56 390 unless exists $self->{_column_data}{$col};
61a622ee 391 }
392 }
cb5f2eea 393 return %{$self->{_column_data}};
d7156e50 394}
395
396=head2 get_dirty_columns
397
398 my %data = $obj->get_dirty_columns;
399
400Identical to get_columns but only returns those that have been changed.
401
402=cut
403
404sub get_dirty_columns {
405 my $self = shift;
406 return map { $_ => $self->{_column_data}{$_} }
407 keys %{$self->{_dirty_columns}};
076a6864 408}
409
ba4a6453 410=head2 get_inflated_columns
411
412 my $inflated_data = $obj->get_inflated_columns;
413
414Similar to get_columns but objects are returned for inflated columns instead of their raw non-inflated values.
415
416=cut
417
418sub get_inflated_columns {
419 my $self = shift;
420 return map {
421 my $accessor = $self->column_info($_)->{'accessor'} || $_;
422 ($_ => $self->$accessor);
423 } $self->columns;
424}
425
8091aa91 426=head2 set_column
7624b19f 427
428 $obj->set_column($col => $val);
429
8091aa91 430Sets a column value. If the new value is different from the old one,
431the column is marked as dirty for when you next call $obj->update.
7624b19f 432
433=cut
434
435sub set_column {
436 my $self = shift;
437 my ($column) = @_;
729b29ae 438 $self->{_orig_ident} ||= $self->ident_condition;
7624b19f 439 my $old = $self->get_column($column);
440 my $ret = $self->store_column(@_);
87772e46 441 $self->{_dirty_columns}{$column} = 1
442 if (defined $old ^ defined $ret) || (defined $old && $old ne $ret);
7624b19f 443 return $ret;
444}
445
8091aa91 446=head2 set_columns
076a6864 447
dc818523 448 my $copy = $orig->set_columns({ $col => $val, ... });
076a6864 449
8091aa91 450Sets more than one column value at once.
076a6864 451
452=cut
453
454sub set_columns {
455 my ($self,$data) = @_;
a2ca474b 456 foreach my $col (keys %$data) {
457 $self->set_column($col,$data->{$col});
076a6864 458 }
c01ab172 459 return $self;
076a6864 460}
461
8091aa91 462=head2 copy
076a6864 463
464 my $copy = $orig->copy({ change => $to, ... });
465
8091aa91 466Inserts a new row with the specified changes.
076a6864 467
468=cut
469
c01ab172 470sub copy {
471 my ($self, $changes) = @_;
333cce60 472 $changes ||= {};
fde6e28e 473 my $col_data = { %{$self->{_column_data}} };
474 foreach my $col (keys %$col_data) {
475 delete $col_data->{$col}
476 if $self->result_source->column_info($col)->{is_auto_increment};
477 }
04786a4c 478
479 my $new = { _column_data => $col_data };
480 bless $new, ref $self;
481
83419ec6 482 $new->result_source($self->result_source);
ecd1f408 483 $new->set_columns($changes);
333cce60 484 $new->insert;
485 foreach my $rel ($self->result_source->relationships) {
486 my $rel_info = $self->result_source->relationship_info($rel);
487 if ($rel_info->{attrs}{cascade_copy}) {
488 my $resolved = $self->result_source->resolve_condition(
489 $rel_info->{cond}, $rel, $new);
490 foreach my $related ($self->search_related($rel)) {
491 $related->copy($resolved);
492 }
493 }
494 }
2c4c67b6 495 return $new;
c01ab172 496}
497
8091aa91 498=head2 store_column
7624b19f 499
500 $obj->store_column($col => $val);
501
8091aa91 502Sets a column value without marking it as dirty.
7624b19f 503
504=cut
505
506sub store_column {
507 my ($self, $column, $value) = @_;
75d07914 508 $self->throw_exception( "No such column '${column}'" )
d7156e50 509 unless exists $self->{_column_data}{$column} || $self->has_column($column);
75d07914 510 $self->throw_exception( "set_column called for ${column} without value" )
7624b19f 511 if @_ < 3;
512 return $self->{_column_data}{$column} = $value;
513}
514
b52e9bf8 515=head2 inflate_result
516
c01ab172 517 Class->inflate_result($result_source, \%me, \%prefetch?)
b52e9bf8 518
519Called by ResultSet to inflate a result from storage
520
521=cut
522
523sub inflate_result {
c01ab172 524 my ($class, $source, $me, $prefetch) = @_;
aec3eff1 525
526 my ($source_handle) = $source;
527
528 if ($source->isa('DBIx::Class::ResultSourceHandle')) {
529 $source = $source_handle->resolve
530 } else {
531 $source_handle = $source->handle
532 }
533
04786a4c 534 my $new = {
aec3eff1 535 _source_handle => $source_handle,
04786a4c 536 _column_data => $me,
537 _in_storage => 1
538 };
539 bless $new, (ref $class || $class);
540
7fb16f1a 541 my $schema;
64acc2bc 542 foreach my $pre (keys %{$prefetch||{}}) {
543 my $pre_val = $prefetch->{$pre};
f9cc31dd 544 my $pre_source = $source->related_source($pre);
a86b1efe 545 $class->throw_exception("Can't prefetch non-existent relationship ${pre}")
546 unless $pre_source;
0f66a01b 547 if (ref($pre_val->[0]) eq 'ARRAY') { # multi
a86b1efe 548 my @pre_objects;
549 foreach my $pre_rec (@$pre_val) {
75d07914 550 unless ($pre_source->primary_columns == grep { exists $pre_rec->[0]{$_}
5a5bec6c 551 and defined $pre_rec->[0]{$_} } $pre_source->primary_columns) {
a86b1efe 552 next;
553 }
554 push(@pre_objects, $pre_source->result_class->inflate_result(
555 $pre_source, @{$pre_rec}));
556 }
557 $new->related_resultset($pre)->set_cache(\@pre_objects);
62e87ea8 558 } elsif (defined $pre_val->[0]) {
a86b1efe 559 my $fetched;
75d07914 560 unless ($pre_source->primary_columns == grep { exists $pre_val->[0]{$_}
a86b1efe 561 and !defined $pre_val->[0]{$_} } $pre_source->primary_columns)
562 {
563 $fetched = $pre_source->result_class->inflate_result(
75d07914 564 $pre_source, @{$pre_val});
a86b1efe 565 }
9809a6df 566 $new->related_resultset($pre)->set_cache([ $fetched ]);
a86b1efe 567 my $accessor = $source->relationship_info($pre)->{attrs}{accessor};
568 $class->throw_exception("No accessor for prefetched $pre")
569 unless defined $accessor;
570 if ($accessor eq 'single') {
571 $new->{_relationship_data}{$pre} = $fetched;
572 } elsif ($accessor eq 'filter') {
573 $new->{_inflated_column}{$pre} = $fetched;
574 } else {
575 $class->throw_exception("Prefetch not supported with accessor '$accessor'");
576 }
b52e9bf8 577 }
578 }
7624b19f 579 return $new;
580}
581
9b465d00 582=head2 update_or_insert
7624b19f 583
9b465d00 584 $obj->update_or_insert
7624b19f 585
8091aa91 586Updates the object if it's already in the db, else inserts it.
7624b19f 587
9b83fccd 588=head2 insert_or_update
589
590 $obj->insert_or_update
591
592Alias for L</update_or_insert>
593
7624b19f 594=cut
595
9b465d00 596*insert_or_update = \&update_or_insert;
597sub update_or_insert {
7624b19f 598 my $self = shift;
599 return ($self->in_storage ? $self->update : $self->insert);
600}
601
8091aa91 602=head2 is_changed
7624b19f 603
228dbcb4 604 my @changed_col_names = $obj->is_changed();
605 if ($obj->is_changed()) { ... }
7624b19f 606
9b83fccd 607In array context returns a list of columns with uncommited changes, or
608in scalar context returns a true value if there are uncommitted
609changes.
610
7624b19f 611=cut
612
613sub is_changed {
614 return keys %{shift->{_dirty_columns} || {}};
615}
228dbcb4 616
617=head2 is_column_changed
618
619 if ($obj->is_column_changed('col')) { ... }
620
9b83fccd 621Returns a true value if the column has uncommitted changes.
622
228dbcb4 623=cut
624
625sub is_column_changed {
626 my( $self, $col ) = @_;
627 return exists $self->{_dirty_columns}->{$col};
628}
7624b19f 629
097d3227 630=head2 result_source
631
9b83fccd 632 my $resultsource = $object->result_source;
097d3227 633
9b83fccd 634Accessor to the ResultSource this object was created from
87c4e602 635
aec3eff1 636=cut
637
638sub result_source {
639 my $self = shift;
640
641 if (@_) {
642 $self->_source_handle($_[0]->handle);
643 } else {
644 $self->_source_handle->resolve;
645 }
646}
647
9b83fccd 648=head2 register_column
27f01d1f 649
9b83fccd 650 $column_info = { .... };
651 $class->register_column($column_name, $column_info);
27f01d1f 652
9b83fccd 653Registers a column on the class. If the column_info has an 'accessor'
654key, creates an accessor named after the value if defined; if there is
655no such key, creates an accessor with the same name as the column
1f23a877 656
9b83fccd 657The column_info attributes are described in
658L<DBIx::Class::ResultSource/add_columns>
1f23a877 659
097d3227 660=cut
661
1f23a877 662sub register_column {
663 my ($class, $col, $info) = @_;
91b0fbd7 664 my $acc = $col;
665 if (exists $info->{accessor}) {
666 return unless defined $info->{accessor};
667 $acc = [ $info->{accessor}, $col ];
668 }
669 $class->mk_group_accessors('column' => $acc);
1f23a877 670}
671
701da8c4 672
5160b401 673=head2 throw_exception
701da8c4 674
675See Schema's throw_exception.
676
677=cut
678
679sub throw_exception {
680 my $self=shift;
66cab05c 681 if (ref $self && ref $self->result_source && $self->result_source->schema) {
701da8c4 682 $self->result_source->schema->throw_exception(@_);
683 } else {
684 croak(@_);
685 }
686}
687
7624b19f 6881;
689
7624b19f 690=head1 AUTHORS
691
daec44b8 692Matt S. Trout <mst@shadowcatsystems.co.uk>
7624b19f 693
694=head1 LICENSE
695
696You may distribute this code under the same terms as Perl itself.
697
698=cut