prefetch docs: prefetch works on all rel types
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Row.pm
index a34a1d8..44374f1 100644 (file)
@@ -8,7 +8,6 @@ use base qw/DBIx::Class/;
 use DBIx::Class::Exception;
 use Scalar::Util 'blessed';
 use Try::Tiny;
-use namespace::clean;
 
 ###
 ### Internal method
@@ -21,7 +20,7 @@ BEGIN {
       : sub () { 0 };
 }
 
-__PACKAGE__->mk_group_accessors('simple' => [result_source => '_result_source']);
+use namespace::clean;
 
 =head1 NAME
 
@@ -268,10 +267,8 @@ sub new {
 =back
 
 Inserts an object previously created by L</new> into the database if
-it isn't already in there. Returns the object itself. Requires the
-object's result source to be set, or the class to have a
-result_source_instance method. To insert an entirely new row into
-the database, use C<create> (see L<DBIx::Class::ResultSet/create>).
+it isn't already in there. Returns the object itself. To insert an
+entirely new row into the database, use L<DBIx::Class::ResultSet/create>.
 
 To fetch an uninserted row object, call
 L<new|DBIx::Class::ResultSet/new> on a resultset.
@@ -285,8 +282,6 @@ sub insert {
   my ($self) = @_;
   return $self if $self->in_storage;
   my $source = $self->result_source;
-  $source ||=  $self->result_source($self->result_source_instance)
-    if $self->can('result_source_instance');
   $self->throw_exception("No result_source set on this object; can't insert")
     unless $source;
 
@@ -348,40 +343,23 @@ sub insert {
     warn "MC $self inserting (".join(', ', $self->get_columns).")\n";
   };
 
+  # perform the insert - the storage will return everything it is asked to
+  # (autoinc primary columns and any retrieve_on_insert columns)
   my %current_rowdata = $self->get_columns;
-
-  # perform the insert - the storage may return some stuff for us right there
-  #
   my $returned_cols = $storage->insert(
     $source,
-    \%current_rowdata,
+    { %current_rowdata }, # what to insert, copy because the storage *will* change it
   );
 
   for (keys %$returned_cols) {
-    $self->store_column(
-      $_,
-      ( $current_rowdata{$_} = $returned_cols->{$_} )
-    );
-  }
-
-  # see if any of the pcols still need filling (or re-querying in case of scalarrefs)
-  my @missing_pri = grep
-    { ! defined $current_rowdata{$_} or ref $current_rowdata{$_} eq 'SCALAR' }
-    $self->primary_columns
-  ;
-
-  if (@missing_pri) {
-    MULTICREATE_DEBUG and warn "MC $self fetching missing PKs ".join(', ', @missing_pri )."\n";
-
-    $self->throw_exception( "Missing primary key but Storage doesn't support last_insert_id" )
-      unless $storage->can('last_insert_id');
-
-    my @pri_values = $storage->last_insert_id($self->result_source, @missing_pri);
-
-    $self->throw_exception( "Can't get last insert id" )
-      unless (@pri_values == @missing_pri);
-
-    $self->store_column($missing_pri[$_] => $pri_values[$_]) for 0 .. $#missing_pri;
+    $self->store_column($_, $returned_cols->{$_})
+      # this ensures we fire store_column only once
+      # (some asshats like overriding it)
+      if (
+        (! defined $current_rowdata{$_})
+          or
+        ( $current_rowdata{$_} ne $returned_cols->{$_})
+      );
   }
 
   $self->{_dirty_columns} = {};
@@ -596,11 +574,12 @@ sub delete {
     $self->in_storage(undef);
   }
   else {
-    $self->throw_exception("Can't do class delete without a ResultSource instance")
-      unless $self->can('result_source_instance');
+    my $rsrc = 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 $query = ref $_[0] eq 'HASH' ? $_[0] : {@_};
-    $self->result_source_instance->resultset->search(@_)->delete;
+    $rsrc->resultset->search(@_)->delete;
   }
   return $self;
 }
@@ -1067,7 +1046,7 @@ sub copy {
     next unless $rel_info->{attrs}{cascade_copy};
 
     my $resolved = $self->result_source->_resolve_condition(
-      $rel_info->{cond}, $rel, $new
+      $rel_info->{cond}, $rel, $new, $rel
     );
 
     my $copied = $rels_copied->{ $rel_info->{source} } ||= {};
@@ -1290,6 +1269,27 @@ sub is_column_changed {
 
 Accessor to the L<DBIx::Class::ResultSource> this object was created from.
 
+=cut
+
+sub result_source {
+  $_[0]->throw_exception( 'result_source can be called on instances only' )
+    unless ref $_[0];
+
+  @_ > 1
+    ? $_[0]->{_result_source} = $_[1]
+
+    # note this is a || not a ||=, the difference is important
+    : $_[0]->{_result_source} || do {
+        my $class = ref $_[0];
+        $_[0]->can('result_source_instance')
+          ? $_[0]->result_source_instance
+          : $_[0]->throw_exception(
+            "No result source instance registered for $class, did you forget to call $class->table(...) ?"
+          )
+      }
+  ;
+}
+
 =head2 register_column
 
   $column_info = { .... };