Audit and minimize use of last major indirect method: search()
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Row.pm
index b0542cb..8b8f5fb 100644 (file)
@@ -6,7 +6,10 @@ use warnings;
 use base qw/DBIx::Class/;
 
 use Scalar::Util 'blessed';
-use DBIx::Class::_Util qw( dbic_internal_try fail_on_internal_call );
+use DBIx::Class::_Util qw(
+  dbic_internal_try fail_on_internal_call
+  DUMMY_ALIASPAIR
+);
 use DBIx::Class::Carp;
 use SQL::Abstract qw( is_literal_value is_plain_value );
 
@@ -190,7 +193,7 @@ sub new {
       $rsrc ||= $h->resolve;
     }
 
-    $new->result_source($rsrc) if $rsrc;
+    $new->result_source_instance($rsrc) if $rsrc;
 
     if (my $col_from_rel = delete $attrs->{-cols_from_relations}) {
       @{$new->{_ignore_at_insert}={}}{@$col_from_rel} = ();
@@ -356,7 +359,7 @@ sub insert {
     my $rel_obj = $related_stuff{$rel_name};
 
     if (! $self->{_rel_in_storage}{$rel_name}) {
-      next unless (blessed $rel_obj && $rel_obj->isa('DBIx::Class::Row'));
+      next unless (blessed $rel_obj && $rel_obj->isa(__PACKAGE__));
 
       next unless $rsrc->_pk_depends_on(
                     $rel_name, { $rel_obj->get_columns }
@@ -441,7 +444,7 @@ sub insert {
       : $related_stuff{$rel_name}
     ;
 
-    if (@cands && blessed $cands[0] && $cands[0]->isa('DBIx::Class::Row')
+    if (@cands && blessed $cands[0] && $cands[0]->isa(__PACKAGE__)
     ) {
       my $reverse = $rsrc->reverse_relationship_info($rel_name);
       foreach my $obj (@cands) {
@@ -553,7 +556,9 @@ sub update {
   my %to_update = $self->get_dirty_columns
     or return $self;
 
-  $self->throw_exception( "Not in database" ) unless $self->in_storage;
+  $self->throw_exception(
+    'Result object not marked in_storage: an update() operation is not possible'
+  ) unless $self->in_storage;
 
   my $rows = $self->result_source->schema->storage->update(
     $self->result_source, \%to_update, $self->_storage_ident_condition
@@ -615,7 +620,9 @@ See also L<DBIx::Class::ResultSet/delete>.
 sub delete {
   my $self = shift;
   if (ref $self) {
-    $self->throw_exception( "Not in database" ) unless $self->in_storage;
+    $self->throw_exception(
+      'Result object not marked in_storage: a delete() operation is not possible'
+    ) unless $self->in_storage;
 
     $self->result_source->schema->storage->delete(
       $self->result_source, $self->_storage_ident_condition
@@ -625,12 +632,9 @@ sub delete {
     $self->in_storage(0);
   }
   else {
-    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(@_)} } : {};
+    my $attrs = @_ > 1 && ref $_[-1] eq 'HASH' ? { %{pop(@_)} } : {};
     my $query = ref $_[0] eq 'HASH' ? $_[0] : {@_};
-    $rsrc->resultset->search(@_)->delete;
+    $self->result_source->resultset->search_rs(@_)->delete;
   }
   return $self;
 }
@@ -1174,7 +1178,7 @@ sub copy {
   my $new = { _column_data => $col_data };
   bless $new, ref $self;
 
-  $new->result_source($rsrc);
+  $new->result_source_instance($rsrc);
   $new->set_inflated_columns($changes);
   $new->insert;
 
@@ -1193,14 +1197,15 @@ sub copy {
 
     $copied->{$_->ID}++ or $_->copy(
 
-      $foreign_vals ||= $rsrc->_resolve_relationship_condition(
-        infer_values_based_on => {},
+      $foreign_vals ||= $rsrc->resolve_relationship_condition(
+        require_join_free_values => 1,
         rel_name => $rel_name,
         self_result_object => $new,
 
-        self_alias => "\xFE", # irrelevant
-        foreign_alias => "\xFF", # irrelevant,
-      )->{inferred_values}
+        # an API where these are optional would be too cumbersome,
+        # instead always pass in some dummy values
+        DUMMY_ALIASPAIR,
+      )->{join_free_values}
 
     ) for $self->related_resultset($rel_name)->all;
   }
@@ -1362,7 +1367,7 @@ Alias for L</update_or_insert>
 
 =cut
 
-sub insert_or_update {
+sub insert_or_update :DBIC_method_is_indirect_sugar {
   DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS and fail_on_internal_call;
   shift->update_or_insert(@_);
 }
@@ -1432,13 +1437,21 @@ Accessor to the L<DBIx::Class::ResultSource> this object was created from.
 
 =cut
 
-sub result_source {
+sub result_source :DBIC_method_is_indirect_sugar {
+  # While getter calls are routed through here for sensible exception text
+  # it makes no sense to have setters do the same thing
+  DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS
+    and
+  @_ > 1
+    and
+  fail_on_internal_call;
+
   # this is essentially a `shift->result_source_instance(@_)` with handholding
   &{
     $_[0]->can('result_source_instance')
       ||
     $_[0]->throw_exception(
-      "No result source instance registered for '@{[ $_[0] ]}', did you forget to call @{[ ref $_[0] || $_[0] ]}->table(...) ?"
+      "No ResultSource instance registered for '@{[ $_[0] ]}', did you forget to call @{[ ref $_[0] || $_[0] ]}->table(...) ?"
     )
   };
 }
@@ -1508,15 +1521,16 @@ L<DBIx::Class::ResultSet/ATTRIBUTES>.
 =cut
 
 sub get_from_storage {
-    my $self = shift @_;
-    my $attrs = shift @_;
-    my $resultset = $self->result_source->resultset;
-
-    if(defined $attrs) {
-      $resultset = $resultset->search(undef, $attrs);
-    }
+    my $self = shift;
 
-    return $resultset->find($self->_storage_ident_condition);
+    # with or without attrs?
+    (
+      defined( $_[0] )
+        ? $self->result_source->resultset->search_rs( undef, $_[0] )
+        : $self->result_source->resultset
+    )->find(
+      $self->_storage_ident_condition
+    );
 }
 
 =head2 discard_changes
@@ -1589,7 +1603,8 @@ sub throw_exception {
   if (
     ! DBIx::Class::_Util::in_internal_try
       and
-    my $rsrc = dbic_internal_try { $self->result_source }
+    # FIXME - the try is 99% superfluous, but just in case
+    my $rsrc = dbic_internal_try { $self->result_source_instance }
   ) {
     $rsrc->throw_exception(@_)
   }