Protect DBIC as best we can from the failure mode in 7cb35852
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Row.pm
index 45ade30..daf5885 100644 (file)
@@ -7,9 +7,9 @@ use base qw/DBIx::Class/;
 
 use Scalar::Util 'blessed';
 use List::Util 'first';
-use Try::Tiny;
+use DBIx::Class::_Util 'dbic_internal_try';
 use DBIx::Class::Carp;
-use SQL::Abstract 'is_literal_value';
+use SQL::Abstract qw( is_literal_value is_plain_value );
 
 ###
 ### Internal method
@@ -621,7 +621,7 @@ sub delete {
     $self->in_storage(0);
   }
   else {
-    my $rsrc = try { $self->result_source_instance }
+    my $rsrc = dbic_internal_try { $self->result_source_instance }
       or $self->throw_exception("Can't do class delete without a ResultSource instance");
 
     my $attrs = @_ > 1 && ref $_[$#_] eq 'HASH' ? { %{pop(@_)} } : {};
@@ -900,7 +900,7 @@ sub _is_column_numeric {
     if (
       ! defined $colinfo->{is_numeric}
         and
-      my $storage = try { $self->result_source->schema->storage }
+      my $storage = dbic_internal_try { $self->result_source->schema->storage }
     ) {
       $colinfo->{is_numeric} =
         $storage->is_datatype_numeric ($colinfo->{data_type})
@@ -1174,16 +1174,21 @@ sub copy {
 
     next unless $rel_info->{attrs}{cascade_copy};
 
-    my $resolved = $rsrc->_resolve_condition(
-      $rel_info->{cond}, $rel_name, $new, $rel_name
-    );
-
+    my $foreign_vals;
     my $copied = $rel_names_copied->{ $rel_info->{source} } ||= {};
-    foreach my $related ($self->search_related($rel_name)->all) {
-      $related->copy($resolved)
-        unless $copied->{$related->ID}++;
-    }
 
+    $copied->{$_->ID}++ or $_->copy(
+
+      $foreign_vals ||= $rsrc->_resolve_relationship_condition(
+        infer_values_based_on => {},
+        rel_name => $rel_name,
+        self_result_object => $new,
+
+        self_alias => "\xFE", # irrelevant
+        foreign_alias => "\xFF", # irrelevant,
+      )->{inferred_values}
+
+    ) for $self->search_related($rel_name)->all;
   }
   return $new;
 }
@@ -1215,7 +1220,18 @@ sub store_column {
     unless exists $self->{_column_data}{$column} || $self->result_source->has_column($column);
   $self->throw_exception( "set_column called for ${column} without value" )
     if @_ < 3;
-  return $self->{_column_data}{$column} = $value;
+
+  return $self->{_column_data}{$column} = $value
+    unless length ref $value and my $vref = is_plain_value( $value );
+
+  # if we are dealing with a value/ref - there are a couple possibilities
+  # unpack the underlying piece of data and stringify all objects explicitly
+  # ( to accomodate { -value => ... } and guard against overloaded objects
+  # with defined stringification AND fallback => 0 (ugh!)
+  $self->{_column_data}{$column} = defined blessed $$vref
+    ? "$$vref"
+    : $$vref
+  ;
 }
 
 =head2 inflate_result
@@ -1564,8 +1580,12 @@ See L<DBIx::Class::Schema/throw_exception>.
 sub throw_exception {
   my $self=shift;
 
-  if (ref $self && ref $self->result_source ) {
-    $self->result_source->throw_exception(@_)
+  if (
+    ref $self
+      and
+    my $rsrc = dbic_internal_try { $self->result_source_instance }
+  ) {
+    $rsrc->throw_exception(@_)
   }
   else {
     DBIx::Class::Exception->throw(@_);