Merge 'trunk' into 'mssql_top_fixes'
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSet.pm
index 8ad1f7d..74940eb 100644 (file)
@@ -698,10 +698,14 @@ a warning:
 
   Query returned more than one row
 
-In this case, you should be using L</first> or L</find> instead, or if you really
+In this case, you should be using L</next> or L</find> instead, or if you really
 know what you are doing, use the L</rows> attribute to explicitly limit the size
 of the resultset.
 
+This method will also throw an exception if it is called on a resultset prefetching
+has_many, as such a prefetch implies fetching multiple rows from the database in
+order to assemble the resulting object.
+
 =back
 
 =cut
@@ -714,6 +718,12 @@ sub single {
 
   my $attrs = $self->_resolved_attrs_copy;
 
+  if (keys %{$attrs->{collapse}}) {
+    $self->throw_exception(
+      'single() can not be used on resultsets prefetching has_many. Use find( \%cond ) or next() instead'
+    );
+  }
+
   if ($where) {
     if (defined $attrs->{where}) {
       $attrs->{where} = {
@@ -2595,11 +2605,12 @@ sub _resolved_attrs {
   # Although this is needed only if the order_by is not defined, it is
   # actually cheaper to just populate this rather than properly examining
   # order_by (stuf like [ {} ] and the like)
-  $attrs->{_virtual_order_by} = [ $self->result_source->primary_columns ];
-
-
-  my $collapse = $attrs->{collapse} || {};
+  my $prefix = $alias . ($source->schema->storage->_sql_maker_opts->{name_sep} || '.');
+  $attrs->{_virtual_order_by} = [
+    map { $prefix . $_ } ($source->primary_columns)
+  ];
 
+  $attrs->{collapse} ||= {};
   if ( my $prefetch = delete $attrs->{prefetch} ) {
     $prefetch = $self->_merge_attr( {}, $prefetch );
 
@@ -2608,20 +2619,20 @@ sub _resolved_attrs {
     my $join_map = $self->_joinpath_aliases ($attrs->{from}, $attrs->{seen_join});
 
     my @prefetch =
-      $source->_resolve_prefetch( $prefetch, $alias, $join_map, $prefetch_ordering, $collapse );
+      $source->_resolve_prefetch( $prefetch, $alias, $join_map, $prefetch_ordering, $attrs->{collapse} );
 
     push( @{ $attrs->{select} }, map { $_->[0] } @prefetch );
     push( @{ $attrs->{as} },     map { $_->[1] } @prefetch );
 
     push( @{ $attrs->{order_by} }, @$prefetch_ordering );
+    $attrs->{_collapse_order_by} = \@$prefetch_ordering;
   }
 
+
   if (delete $attrs->{distinct}) {
     $attrs->{group_by} ||= [ grep { !ref($_) || (ref($_) ne 'HASH') } @{$attrs->{select}} ];
   }
 
-  $attrs->{collapse} = $collapse;
-
   # if both page and offset are specified, produce a combined offset
   # even though it doesn't make much sense, this is what pre 081xx has
   # been doing