Passes all tests
[dbsrgits/DBIx-Class-Historic.git] / lib / DBIx / Class / ResultSet.pm
index 7764436..59d7d06 100644 (file)
@@ -2070,147 +2070,133 @@ sub _resolve_from {
 }
 
 sub _resolved_attrs {
-    my $self = shift;
-    return $self->{_attrs} if $self->{_attrs};
-
-    my $attrs  = { %{ $self->{attrs} || {} } };
-    my $source = $self->result_source;
-    my $alias  = $attrs->{alias};
-
-    $attrs->{columns} ||= delete $attrs->{cols} if exists $attrs->{cols};
-    $attrs->{columns} ||= [ $source->columns ] unless ( $attrs->{select} );
-    if ( $attrs->{columns} ) {
-
-        # if columns is set we overwrite select & as
-        $attrs->{select} = [];
-        $attrs->{as}     = [];
-        foreach my $colbit ( @{ $attrs->{columns} } ) {
-            if ( ref($_) eq 'HASH' ) {
-                push(
-                    @{ $attrs->{select} },
-                    map { ref($_) ? $_ : m/\./ ? $_ : "${alias}.$_" }
-                      values( %{$colbit} )
-                );
-                push(
-                    @{ $attrs->{as} },
-                    map { m/^\Q${alias}.\E(.+)$/ ? $1 : $_ } keys( %{$colbit} )
-                );
-            }
-            else {
-                push(
-                    @{ $attrs->{select} },
-                    ( $colbit =~ m/\./ ) ? $colbit : "${alias}.${colbit}"
-                );
-                push(
-                    @{ $attrs->{as} },
-                    ( $colbit =~ m/^\Q${alias}.\E(.+)$/ ) ? $1 : $colbit
-                );
+  my $self = shift;
+  return $self->{_attrs} if $self->{_attrs};
+
+  my $attrs  = { %{ $self->{attrs} || {} } };
+  my $source = $self->result_source;
+  my $alias  = $attrs->{alias};
+
+  $attrs->{columns} ||= delete $attrs->{cols} if exists $attrs->{cols};
+  my @colbits;
+
+  # build columns (as long as select isn't set) into a set of as/select hashes
+  unless ( $attrs->{select} ) {
+      @colbits = map {
+          ( ref($_) eq 'HASH' ) ? $_
+            : {
+              (
+                  /^\Q${alias}.\E(.+)$/ ? $1
+                  : $_
+                ) => ( /\./ ? $_ : "${alias}.$_" )
             }
-        }
-        delete $attrs->{columns};
-    }
-    else {
-        $attrs->{select} =
-            ( ref $attrs->{select} eq 'ARRAY' )
-          ? [ @{ $attrs->{select} } ]
-          : [ $attrs->{select} ];
-        $attrs->{as} = (
-            $attrs->{as}
-            ? (
-                ref $attrs->{as} eq 'ARRAY'
-                ? [ @{ $attrs->{as} } ]
-                : [ $attrs->{as} ]
-              )
-            : [
-                map { m/^\Q${alias}.\E(.+)$/ ? $1 : $_ } @{ $attrs->{select} }
-            ]
-        );
-    }
-    my $adds;
-    if ( $adds = delete $attrs->{include_columns} ) {
-        $adds = [$adds] unless ref $adds eq 'ARRAY';
-        push( @{ $attrs->{select} }, @$adds );
-        push( @{ $attrs->{as} }, map { m/([^.]+)$/; $1 } @$adds );
-    }
-    if ( $adds = delete $attrs->{'+columns'} ) {
-        $adds = [$adds] unless ref $adds eq 'ARRAY';
-        push(
-            @{ $attrs->{select} },
-            map { ref($_) eq 'HASH' ? values( %{$_} ) : $_ } @$adds
-        );
-        push(
-            @{ $attrs->{as} },
-            map { ref($_) eq 'HASH' ? keys( %{$_} ) : $_ } @$adds
-        );
-    }
-    if ( $adds = delete $attrs->{'+select'} ) {
-        $adds = [$adds] unless ref $adds eq 'ARRAY';
-        push(
-            @{ $attrs->{select} },
-            map { /\./ || ref $_ ? $_ : "${alias}.$_" } @$adds
-        );
-    }
-    if ( $adds = delete $attrs->{'+as'} ) {
-        $adds = [$adds] unless ref $adds eq 'ARRAY';
-        push( @{ $attrs->{as} }, @$adds );
-    }
+      } @{ delete $attrs->{columns} || [ $source->columns ] };
+  }
+  # add the additional columns on
+  foreach ( 'include_columns', '+columns' ) {
+      push @colbits, map {
+          ( ref($_) eq 'HASH' )
+            ? $_
+            : { ( split( /\./, $_ ) )[-1] => ( /\./ ? $_ : "${alias}.$_" ) }
+      } @{ delete $attrs->{$_} } if ( $attrs->{$_} );
+  }
+
+  # start with initial select items
+  if ( $attrs->{select} ) {
+    $attrs->{select} =
+        ( ref $attrs->{select} eq 'ARRAY' )
+      ? [ @{ $attrs->{select} } ]
+      : [ $attrs->{select} ];
+    $attrs->{as} = (
+      $attrs->{as}
+      ? (
+        ref $attrs->{as} eq 'ARRAY'
+        ? [ @{ $attrs->{as} } ]
+        : [ $attrs->{as} ]
+        )
+      : [ map { m/^\Q${alias}.\E(.+)$/ ? $1 : $_ } @{ $attrs->{select} } ]
+    );
+  }
+  else {
 
-    $attrs->{from} ||= [ { 'me' => $source->from } ];
+    # otherwise we intialise select & as to empty
+    $attrs->{select} = [];
+    $attrs->{as}     = [];
+  }
 
-    if ( exists $attrs->{join} || exists $attrs->{prefetch} ) {
-        my $join = delete $attrs->{join} || {};
+  # now add colbits to select/as
+  push( @{ $attrs->{select} }, map { values( %{$_} ) } @colbits );
+  push( @{ $attrs->{as} },     map { keys( %{$_} ) } @colbits );
 
-        if ( defined $attrs->{prefetch} ) {
-            $join = $self->_merge_attr( $join, $attrs->{prefetch} );
+  my $adds;
+  if ( $adds = delete $attrs->{'+select'} ) {
+    $adds = [$adds] unless ref $adds eq 'ARRAY';
+    push(
+      @{ $attrs->{select} },
+      map { /\./ || ref $_ ? $_ : "${alias}.$_" } @$adds
+    );
+  }
+  if ( $adds = delete $attrs->{'+as'} ) {
+    $adds = [$adds] unless ref $adds eq 'ARRAY';
+    push( @{ $attrs->{as} }, @$adds );
+  }
 
-        }
+  $attrs->{from} ||= [ { 'me' => $source->from } ];
 
-        $attrs->{from} =    # have to copy here to avoid corrupting the original
-          [
-            @{ $attrs->{from} },
-            $source->resolve_join(
-                $join, $alias, { %{ $attrs->{seen_join} || {} } }
-            )
-          ];
+  if ( exists $attrs->{join} || exists $attrs->{prefetch} ) {
+    my $join = delete $attrs->{join} || {};
 
-    }
+    if ( defined $attrs->{prefetch} ) {
+      $join = $self->_merge_attr( $join, $attrs->{prefetch} );
 
-    $attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct};
-    if ( $attrs->{order_by} ) {
-        $attrs->{order_by} = (
-            ref( $attrs->{order_by} ) eq 'ARRAY'
-            ? [ @{ $attrs->{order_by} } ]
-            : [ $attrs->{order_by} ]
-        );
-    }
-    else {
-        $attrs->{order_by} = [];
     }
 
-    my $collapse = $attrs->{collapse} || {};
-    if ( my $prefetch = delete $attrs->{prefetch} ) {
-        $prefetch = $self->_merge_attr( {}, $prefetch );
-        my @pre_order;
-        my $seen = $attrs->{seen_join} || {};
-        foreach my $p ( ref $prefetch eq 'ARRAY' ? @$prefetch : ($prefetch) ) {
-
-            # bring joins back to level of current class
-            my @prefetch =
-              $source->resolve_prefetch( $p, $alias, $seen, \@pre_order,
-                $collapse );
-            push( @{ $attrs->{select} }, map { $_->[0] } @prefetch );
-            push( @{ $attrs->{as} },     map { $_->[1] } @prefetch );
-        }
-        push( @{ $attrs->{order_by} }, @pre_order );
-    }
-    $attrs->{collapse} = $collapse;
+    $attrs->{from} =    # have to copy here to avoid corrupting the original
+      [
+      @{ $attrs->{from} },
+      $source->resolve_join(
+        $join, $alias, { %{ $attrs->{seen_join} || {} } }
+      )
+      ];
+
+  }
 
-    if ( $attrs->{page} ) {
-        $attrs->{offset} ||= 0;
-        $attrs->{offset} += ( $attrs->{rows} * ( $attrs->{page} - 1 ) );
+  $attrs->{group_by} ||= $attrs->{select}
+    if delete $attrs->{distinct};
+  if ( $attrs->{order_by} ) {
+    $attrs->{order_by} = (
+      ref( $attrs->{order_by} ) eq 'ARRAY'
+      ? [ @{ $attrs->{order_by} } ]
+      : [ $attrs->{order_by} ]
+    );
+  }
+  else {
+    $attrs->{order_by} = [];
+  }
+
+  my $collapse = $attrs->{collapse} || {};
+  if ( my $prefetch = delete $attrs->{prefetch} ) {
+    $prefetch = $self->_merge_attr( {}, $prefetch );
+    my @pre_order;
+    my $seen = $attrs->{seen_join} || {};
+    foreach my $p ( ref $prefetch eq 'ARRAY' ? @$prefetch : ($prefetch) ) {
+
+      # bring joins back to level of current class
+      my @prefetch =
+        $source->resolve_prefetch( $p, $alias, $seen, \@pre_order, $collapse );
+      push( @{ $attrs->{select} }, map { $_->[0] } @prefetch );
+      push( @{ $attrs->{as} },     map { $_->[1] } @prefetch );
     }
+    push( @{ $attrs->{order_by} }, @pre_order );
+  }
+  $attrs->{collapse} = $collapse;
+
+  if ( $attrs->{page} ) {
+    $attrs->{offset} ||= 0;
+    $attrs->{offset} += ( $attrs->{rows} * ( $attrs->{page} - 1 ) );
+  }
 
-    return $self->{_attrs} = $attrs;
+  return $self->{_attrs} = $attrs;
 }
 
 sub _rollout_attr {
@@ -2376,12 +2362,15 @@ so you will need to manually quote things as appropriate.)
 
 =back
 
-Shortcut to request a particular set of columns to be retrieved.  Adds
-C<me.> onto the start of any column without a C<.> in it and sets C<select>
-from that, then auto-populates C<as> from C<select> as normal. (You may also
-use the C<cols> attribute, as in earlier versions of DBIC.)
+Shortcut to request a particular set of columns to be retrieved. Each
+column spec may be a string (a table column name), or a hash (in which
+case the key is the C<as> value, and the value is used as the C<select>
+expression). Adds C<me.> onto the start of any column without a C<.> in
+it and sets C<select> from that, then auto-populates C<as> from
+C<select> as normal. (You may also use the C<cols> attribute, as in
+earlier versions of DBIC.)
 
-=head2 include_columns
+=head2 +columns
 
 =over 4
 
@@ -2389,10 +2378,13 @@ use the C<cols> attribute, as in earlier versions of DBIC.)
 
 =back
 
-Shortcut to include additional columns in the returned results - for example
+Indicates additional columns to be selected from storage. Works the same
+as L</columns> but adds columns to the selection. (You may also use the
+C<include_columns> attribute, as in earlier versions of DBIC). For
+example:-
 
   $schema->resultset('CD')->search(undef, {
-    include_columns => ['artist.name'],
+    '+columns' => ['artist.name'],
     join => ['artist']
   });