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