default stacktrace on if $ENV{DBIC_TRACE} is on
[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
168 my ($pri, $too_many) = grep { !defined $self->get_column($_) ||
169 ref($self->get_column($_)) eq 'SCALAR'} $self->primary_columns;
170 if(defined $pri) {
171 $self->throw_exception( "More than one possible key found for auto-inc on ".ref $self )
172 if defined $too_many;
173
174 my $storage = $self->result_source->storage;
175 $self->throw_exception( "Missing primary key but Storage doesn't support last_insert_id" )
176 unless $storage->can('last_insert_id');
177 my $id = $storage->last_insert_id($self->result_source,$pri);
178 $self->throw_exception( "Can't get last insert id" ) unless $id;
179 $self->store_column($pri => $id);
180 }
33dd4e80 181
8222f722 182 if(!$self->{_rel_in_storage})
183 {
184 ## Now do the has_many rels, that need $selfs ID.
185 foreach my $relname (keys %related_stuff) {
186 my $relobj = $related_stuff{$relname};
187 if(ref $relobj eq 'ARRAY') {
188 foreach my $obj (@$relobj) {
189 my $info = $self->relationship_info($relname);
190 ## What about multi-col FKs ?
191 my $key = $1 if($info && (keys %{$info->{cond}})[0] =~ /^foreign\.(\w+)/);
192 $obj->set_from_related($key, $self);
193 $obj->insert() if(!$obj->in_storage);
194 }
33dd4e80 195 }
196 }
8222f722 197 $source->storage->txn_commit;
33dd4e80 198 }
33dd4e80 199
7624b19f 200 $self->in_storage(1);
201 $self->{_dirty_columns} = {};
64acc2bc 202 $self->{related_resultsets} = {};
729b29ae 203 undef $self->{_orig_ident};
7624b19f 204 return $self;
205}
206
8091aa91 207=head2 in_storage
7624b19f 208
209 $obj->in_storage; # Get value
210 $obj->in_storage(1); # Set value
211
212Indicated whether the object exists as a row in the database or not
213
214=cut
215
216sub in_storage {
217 my ($self, $val) = @_;
218 $self->{_in_storage} = $val if @_ > 1;
219 return $self->{_in_storage};
220}
221
8091aa91 222=head2 update
7624b19f 223
d5d833d9 224 $obj->update \%columns?;
7624b19f 225
226Must be run on an object that is already in the database; issues an SQL
d3b0e369 227UPDATE query to commit any changes to the object to the database if
228required.
7624b19f 229
d5d833d9 230Also takes an options hashref of C<< column_name => value> pairs >> to update
231first. But be aware that this hashref might be edited in place, so dont rely on
8b621a87 232it being the same after a call to C<update>. If you need to preserve the hashref,
233it is sufficient to pass a shallow copy to C<update>, e.g. ( { %{ $href } } )
d5d833d9 234
7624b19f 235=cut
236
237sub update {
238 my ($self, $upd) = @_;
701da8c4 239 $self->throw_exception( "Not in database" ) unless $self->in_storage;
4b12b3c2 240 my $ident_cond = $self->ident_condition;
241 $self->throw_exception("Cannot safely update a row in a PK-less table")
242 if ! keys %$ident_cond;
6e399b4f 243
61a622ee 244 if ($upd) {
245 foreach my $key (keys %$upd) {
246 if (ref $upd->{$key}) {
247 my $info = $self->relationship_info($key);
248 if ($info && $info->{attrs}{accessor}
249 && $info->{attrs}{accessor} eq 'single')
250 {
251 my $rel = delete $upd->{$key};
252 $self->set_from_related($key => $rel);
253 $self->{_relationship_data}{$key} = $rel;
af2d42c0 254 } elsif ($info && $info->{attrs}{accessor}
255 && $info->{attrs}{accessor} eq 'multi'
256 && ref $upd->{$key} eq 'ARRAY') {
257 my $others = delete $upd->{$key};
258 foreach my $rel_obj (@$others) {
259 if(!Scalar::Util::blessed($rel_obj)) {
260 $rel_obj = $self->create_related($key, $rel_obj);
261 }
262 }
263 $self->{_relationship_data}{$key} = $others;
264# $related->{$key} = $others;
265 next;
266 }
61a622ee 267 elsif ($self->has_column($key)
268 && exists $self->column_info($key)->{_inflate_info})
269 {
270 $self->set_inflated_column($key, delete $upd->{$key});
271 }
272 }
273 }
274 $self->set_columns($upd);
275 }
5a9e0e60 276 my %to_update = $self->get_dirty_columns;
277 return $self unless keys %to_update;
88cb6a1d 278 my $rows = $self->result_source->storage->update(
f4afcd5d 279 $self->result_source, \%to_update,
280 $self->{_orig_ident} || $ident_cond
281 );
7624b19f 282 if ($rows == 0) {
701da8c4 283 $self->throw_exception( "Can't update ${self}: row not found" );
7624b19f 284 } elsif ($rows > 1) {
701da8c4 285 $self->throw_exception("Can't update ${self}: updated more than one row");
7624b19f 286 }
287 $self->{_dirty_columns} = {};
64acc2bc 288 $self->{related_resultsets} = {};
729b29ae 289 undef $self->{_orig_ident};
7624b19f 290 return $self;
291}
292
8091aa91 293=head2 delete
7624b19f 294
295 $obj->delete
296
b8810cc5 297Deletes the object from the database. The object is still perfectly
61a622ee 298usable, but C<< ->in_storage() >> will now return 0 and the object must
299reinserted using C<< ->insert() >> before C<< ->update() >> can be used
b8810cc5 300on it. If you delete an object in a class with a C<has_many>
301relationship, all the related objects will be deleted as well. To turn
302this behavior off, pass C<cascade_delete => 0> in the C<$attr>
303hashref. Any database-level cascade or restrict will take precedence
304over a DBIx-Class-based cascading delete. See also L<DBIx::Class::ResultSet/delete>.
7624b19f 305
306=cut
307
308sub delete {
309 my $self = shift;
310 if (ref $self) {
701da8c4 311 $self->throw_exception( "Not in database" ) unless $self->in_storage;
4b12b3c2 312 my $ident_cond = $self->ident_condition;
313 $self->throw_exception("Cannot safely delete a row in a PK-less table")
314 if ! keys %$ident_cond;
e0f56292 315 foreach my $column (keys %$ident_cond) {
75d07914 316 $self->throw_exception("Can't delete the object unless it has loaded the primary keys")
317 unless exists $self->{_column_data}{$column};
e0f56292 318 }
88cb6a1d 319 $self->result_source->storage->delete(
7af8b477 320 $self->result_source, $ident_cond);
7624b19f 321 $self->in_storage(undef);
7624b19f 322 } else {
701da8c4 323 $self->throw_exception("Can't do class delete without a ResultSource instance")
097d3227 324 unless $self->can('result_source_instance');
aeb1bf75 325 my $attrs = @_ > 1 && ref $_[$#_] eq 'HASH' ? { %{pop(@_)} } : {};
326 my $query = ref $_[0] eq 'HASH' ? $_[0] : {@_};
097d3227 327 $self->result_source_instance->resultset->search(@_)->delete;
7624b19f 328 }
329 return $self;
330}
331
8091aa91 332=head2 get_column
7624b19f 333
334 my $val = $obj->get_column($col);
335
61a622ee 336Gets a column value from a row object. Does not do any queries; the column
337must have already been fetched from the database and stored in the object. If
338there is an inflated value stored that has not yet been deflated, it is deflated
339when the method is invoked.
7624b19f 340
341=cut
342
343sub get_column {
344 my ($self, $column) = @_;
701da8c4 345 $self->throw_exception( "Can't fetch data as class method" ) unless ref $self;
aeb1bf75 346 return $self->{_column_data}{$column} if exists $self->{_column_data}{$column};
61a622ee 347 if (exists $self->{_inflated_column}{$column}) {
348 return $self->store_column($column,
349 $self->_deflated_column($column, $self->{_inflated_column}{$column}));
350 }
701da8c4 351 $self->throw_exception( "No such column '${column}'" ) unless $self->has_column($column);
7624b19f 352 return undef;
353}
354
9b83fccd 355=head2 has_column_loaded
356
357 if ( $obj->has_column_loaded($col) ) {
358 print "$col has been loaded from db";
359 }
360
361Returns a true value if the column value has been loaded from the
362database (or set locally).
363
364=cut
365
def81720 366sub has_column_loaded {
367 my ($self, $column) = @_;
368 $self->throw_exception( "Can't call has_column data as class method" ) unless ref $self;
61a622ee 369 return 1 if exists $self->{_inflated_column}{$column};
aeb1bf75 370 return exists $self->{_column_data}{$column};
def81720 371}
372
8091aa91 373=head2 get_columns
076a6864 374
375 my %data = $obj->get_columns;
376
8091aa91 377Does C<get_column>, for all column values at once.
076a6864 378
379=cut
380
381sub get_columns {
382 my $self = shift;
61a622ee 383 if (exists $self->{_inflated_column}) {
384 foreach my $col (keys %{$self->{_inflated_column}}) {
385 $self->store_column($col, $self->_deflated_column($col, $self->{_inflated_column}{$col}))
c4a30d56 386 unless exists $self->{_column_data}{$col};
61a622ee 387 }
388 }
cb5f2eea 389 return %{$self->{_column_data}};
d7156e50 390}
391
392=head2 get_dirty_columns
393
394 my %data = $obj->get_dirty_columns;
395
396Identical to get_columns but only returns those that have been changed.
397
398=cut
399
400sub get_dirty_columns {
401 my $self = shift;
402 return map { $_ => $self->{_column_data}{$_} }
403 keys %{$self->{_dirty_columns}};
076a6864 404}
405
ba4a6453 406=head2 get_inflated_columns
407
408 my $inflated_data = $obj->get_inflated_columns;
409
410Similar to get_columns but objects are returned for inflated columns instead of their raw non-inflated values.
411
412=cut
413
414sub get_inflated_columns {
415 my $self = shift;
416 return map {
417 my $accessor = $self->column_info($_)->{'accessor'} || $_;
418 ($_ => $self->$accessor);
419 } $self->columns;
420}
421
8091aa91 422=head2 set_column
7624b19f 423
424 $obj->set_column($col => $val);
425
8091aa91 426Sets a column value. If the new value is different from the old one,
427the column is marked as dirty for when you next call $obj->update.
7624b19f 428
429=cut
430
431sub set_column {
432 my $self = shift;
433 my ($column) = @_;
729b29ae 434 $self->{_orig_ident} ||= $self->ident_condition;
7624b19f 435 my $old = $self->get_column($column);
436 my $ret = $self->store_column(@_);
87772e46 437 $self->{_dirty_columns}{$column} = 1
438 if (defined $old ^ defined $ret) || (defined $old && $old ne $ret);
7624b19f 439 return $ret;
440}
441
8091aa91 442=head2 set_columns
076a6864 443
dc818523 444 my $copy = $orig->set_columns({ $col => $val, ... });
076a6864 445
8091aa91 446Sets more than one column value at once.
076a6864 447
448=cut
449
450sub set_columns {
451 my ($self,$data) = @_;
a2ca474b 452 foreach my $col (keys %$data) {
453 $self->set_column($col,$data->{$col});
076a6864 454 }
c01ab172 455 return $self;
076a6864 456}
457
8091aa91 458=head2 copy
076a6864 459
460 my $copy = $orig->copy({ change => $to, ... });
461
8091aa91 462Inserts a new row with the specified changes.
076a6864 463
464=cut
465
c01ab172 466sub copy {
467 my ($self, $changes) = @_;
333cce60 468 $changes ||= {};
fde6e28e 469 my $col_data = { %{$self->{_column_data}} };
470 foreach my $col (keys %$col_data) {
471 delete $col_data->{$col}
472 if $self->result_source->column_info($col)->{is_auto_increment};
473 }
04786a4c 474
475 my $new = { _column_data => $col_data };
476 bless $new, ref $self;
477
83419ec6 478 $new->result_source($self->result_source);
ecd1f408 479 $new->set_columns($changes);
333cce60 480 $new->insert;
481 foreach my $rel ($self->result_source->relationships) {
482 my $rel_info = $self->result_source->relationship_info($rel);
483 if ($rel_info->{attrs}{cascade_copy}) {
484 my $resolved = $self->result_source->resolve_condition(
485 $rel_info->{cond}, $rel, $new);
486 foreach my $related ($self->search_related($rel)) {
487 $related->copy($resolved);
488 }
489 }
490 }
2c4c67b6 491 return $new;
c01ab172 492}
493
8091aa91 494=head2 store_column
7624b19f 495
496 $obj->store_column($col => $val);
497
8091aa91 498Sets a column value without marking it as dirty.
7624b19f 499
500=cut
501
502sub store_column {
503 my ($self, $column, $value) = @_;
75d07914 504 $self->throw_exception( "No such column '${column}'" )
d7156e50 505 unless exists $self->{_column_data}{$column} || $self->has_column($column);
75d07914 506 $self->throw_exception( "set_column called for ${column} without value" )
7624b19f 507 if @_ < 3;
508 return $self->{_column_data}{$column} = $value;
509}
510
b52e9bf8 511=head2 inflate_result
512
c01ab172 513 Class->inflate_result($result_source, \%me, \%prefetch?)
b52e9bf8 514
515Called by ResultSet to inflate a result from storage
516
517=cut
518
519sub inflate_result {
c01ab172 520 my ($class, $source, $me, $prefetch) = @_;
aec3eff1 521
522 my ($source_handle) = $source;
523
524 if ($source->isa('DBIx::Class::ResultSourceHandle')) {
525 $source = $source_handle->resolve
526 } else {
527 $source_handle = $source->handle
528 }
529
04786a4c 530 my $new = {
aec3eff1 531 _source_handle => $source_handle,
04786a4c 532 _column_data => $me,
533 _in_storage => 1
534 };
535 bless $new, (ref $class || $class);
536
7fb16f1a 537 my $schema;
64acc2bc 538 foreach my $pre (keys %{$prefetch||{}}) {
539 my $pre_val = $prefetch->{$pre};
f9cc31dd 540 my $pre_source = $source->related_source($pre);
a86b1efe 541 $class->throw_exception("Can't prefetch non-existent relationship ${pre}")
542 unless $pre_source;
0f66a01b 543 if (ref($pre_val->[0]) eq 'ARRAY') { # multi
a86b1efe 544 my @pre_objects;
545 foreach my $pre_rec (@$pre_val) {
75d07914 546 unless ($pre_source->primary_columns == grep { exists $pre_rec->[0]{$_}
5a5bec6c 547 and defined $pre_rec->[0]{$_} } $pre_source->primary_columns) {
a86b1efe 548 next;
549 }
550 push(@pre_objects, $pre_source->result_class->inflate_result(
551 $pre_source, @{$pre_rec}));
552 }
553 $new->related_resultset($pre)->set_cache(\@pre_objects);
62e87ea8 554 } elsif (defined $pre_val->[0]) {
a86b1efe 555 my $fetched;
75d07914 556 unless ($pre_source->primary_columns == grep { exists $pre_val->[0]{$_}
a86b1efe 557 and !defined $pre_val->[0]{$_} } $pre_source->primary_columns)
558 {
559 $fetched = $pre_source->result_class->inflate_result(
75d07914 560 $pre_source, @{$pre_val});
a86b1efe 561 }
9809a6df 562 $new->related_resultset($pre)->set_cache([ $fetched ]);
a86b1efe 563 my $accessor = $source->relationship_info($pre)->{attrs}{accessor};
564 $class->throw_exception("No accessor for prefetched $pre")
565 unless defined $accessor;
566 if ($accessor eq 'single') {
567 $new->{_relationship_data}{$pre} = $fetched;
568 } elsif ($accessor eq 'filter') {
569 $new->{_inflated_column}{$pre} = $fetched;
570 } else {
571 $class->throw_exception("Prefetch not supported with accessor '$accessor'");
572 }
b52e9bf8 573 }
574 }
7624b19f 575 return $new;
576}
577
9b465d00 578=head2 update_or_insert
7624b19f 579
9b465d00 580 $obj->update_or_insert
7624b19f 581
8091aa91 582Updates the object if it's already in the db, else inserts it.
7624b19f 583
9b83fccd 584=head2 insert_or_update
585
586 $obj->insert_or_update
587
588Alias for L</update_or_insert>
589
7624b19f 590=cut
591
9b465d00 592*insert_or_update = \&update_or_insert;
593sub update_or_insert {
7624b19f 594 my $self = shift;
595 return ($self->in_storage ? $self->update : $self->insert);
596}
597
8091aa91 598=head2 is_changed
7624b19f 599
228dbcb4 600 my @changed_col_names = $obj->is_changed();
601 if ($obj->is_changed()) { ... }
7624b19f 602
9b83fccd 603In array context returns a list of columns with uncommited changes, or
604in scalar context returns a true value if there are uncommitted
605changes.
606
7624b19f 607=cut
608
609sub is_changed {
610 return keys %{shift->{_dirty_columns} || {}};
611}
228dbcb4 612
613=head2 is_column_changed
614
615 if ($obj->is_column_changed('col')) { ... }
616
9b83fccd 617Returns a true value if the column has uncommitted changes.
618
228dbcb4 619=cut
620
621sub is_column_changed {
622 my( $self, $col ) = @_;
623 return exists $self->{_dirty_columns}->{$col};
624}
7624b19f 625
097d3227 626=head2 result_source
627
9b83fccd 628 my $resultsource = $object->result_source;
097d3227 629
9b83fccd 630Accessor to the ResultSource this object was created from
87c4e602 631
aec3eff1 632=cut
633
634sub result_source {
635 my $self = shift;
636
637 if (@_) {
638 $self->_source_handle($_[0]->handle);
639 } else {
640 $self->_source_handle->resolve;
641 }
642}
643
9b83fccd 644=head2 register_column
27f01d1f 645
9b83fccd 646 $column_info = { .... };
647 $class->register_column($column_name, $column_info);
27f01d1f 648
9b83fccd 649Registers a column on the class. If the column_info has an 'accessor'
650key, creates an accessor named after the value if defined; if there is
651no such key, creates an accessor with the same name as the column
1f23a877 652
9b83fccd 653The column_info attributes are described in
654L<DBIx::Class::ResultSource/add_columns>
1f23a877 655
097d3227 656=cut
657
1f23a877 658sub register_column {
659 my ($class, $col, $info) = @_;
91b0fbd7 660 my $acc = $col;
661 if (exists $info->{accessor}) {
662 return unless defined $info->{accessor};
663 $acc = [ $info->{accessor}, $col ];
664 }
665 $class->mk_group_accessors('column' => $acc);
1f23a877 666}
667
701da8c4 668
5160b401 669=head2 throw_exception
701da8c4 670
671See Schema's throw_exception.
672
673=cut
674
675sub throw_exception {
676 my $self=shift;
66cab05c 677 if (ref $self && ref $self->result_source && $self->result_source->schema) {
701da8c4 678 $self->result_source->schema->throw_exception(@_);
679 } else {
680 croak(@_);
681 }
682}
683
7624b19f 6841;
685
7624b19f 686=head1 AUTHORS
687
daec44b8 688Matt S. Trout <mst@shadowcatsystems.co.uk>
7624b19f 689
690=head1 LICENSE
691
692You may distribute this code under the same terms as Perl itself.
693
694=cut