Merge 'trunk' into 'DBIx-Class-current'
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSet.pm
index 4ab3389..532e8b2 100644 (file)
@@ -55,7 +55,7 @@ In the examples below, the following table classes are used:
 =head3 Arguments: ($source, \%$attrs)
 
 The resultset constructor. Takes a source object (usually a
-L<DBIx::Class::ResultSourceProxy::Table>) and an attribute hash (see L</ATRRIBUTES>
+L<DBIx::Class::ResultSourceProxy::Table>) and an attribute hash (see L</ATTRIBUTES>
 below).  Does not perform any queries -- these are executed as needed by the
 other methods.
 
@@ -102,6 +102,10 @@ sub new {
   }
   $attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct};
 
+  $attrs->{order_by} = [ $attrs->{order_by} ]
+    if $attrs->{order_by} && !ref($attrs->{order_by});
+  $attrs->{order_by} ||= [];
+
   if (my $prefetch = delete $attrs->{prefetch}) {
     foreach my $p (ref $prefetch eq 'ARRAY'
               ? (@{$prefetch}) : ($prefetch)) {
@@ -115,7 +119,8 @@ sub new {
         push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
             unless $seen{$p};
       }
-      my @prefetch = $source->resolve_prefetch($p, $attrs->{alias});
+      my @prefetch = $source->resolve_prefetch(
+           $p, $attrs->{alias}, {}, $attrs->{order_by});
       #die Dumper \@cols;
       push(@{$attrs->{select}}, map { $_->[0] } @prefetch);
       push(@{$attrs->{as}}, map { $_->[1] } @prefetch);
@@ -155,7 +160,6 @@ call it as C<search({}, \%attrs);>.
 sub search {
   my $self = shift;
 
-  #use Data::Dumper;warn Dumper(@_);
   my $rs;
   if( @_ ) {
     
@@ -165,7 +169,14 @@ sub search {
      $attrs = { %$attrs, %{ pop(@_) } };
     }
 
-    my $where = (@_ ? ((@_ == 1 || ref $_[0] eq "HASH") ? shift : {@_}) : undef());
+    my $where = (@_
+                  ? ((@_ == 1 || ref $_[0] eq "HASH")
+                      ? shift
+                      : ((@_ % 2)
+                          ? $self->throw_exception(
+                              "Odd number of arguments to search")
+                          : {@_}))
+                  : undef());
     if (defined $where) {
       $where = (defined $attrs->{where}
                 ? { '-and' =>
@@ -202,7 +213,7 @@ Pass a literal chunk of SQL to be added to the conditional part of the
 resultset.
 
 =cut
-                                                         
+
 sub search_literal {
   my ($self, $cond, @vals) = @_;
   my $attrs = (ref $vals[$#vals] eq 'HASH' ? { %{ pop(@vals) } } : {});
@@ -221,7 +232,7 @@ Finds a row based on its primary key or unique constraint. For example:
 Also takes an optional C<key> attribute, to search by a specific key or unique
 constraint. For example:
 
-  my $cd = $schema->resultset('CD')->find_or_create(
+  my $cd = $schema->resultset('CD')->find(
     {
       artist => 'Massive Attack',
       title  => 'Mezzanine',
@@ -377,14 +388,18 @@ Can be used to efficiently iterate over records in the resultset:
 
 sub next {
   my ($self) = @_;
-  my $cache = $self->get_cache;
-  if( @$cache ) {
+  my $cache;
+  if( @{$cache = $self->{all_cache} || []}) {
     $self->{all_cache_position} ||= 0;
     my $obj = $cache->[$self->{all_cache_position}];
     $self->{all_cache_position}++;
     return $obj;
   }
-  my @row = $self->cursor->next;
+  if ($self->{attrs}{cache}) {
+    $self->{all_cache_position} = 0;
+    return ($self->all)[0];
+  }
+  my @row = delete $self->{stashed_row} || $self->cursor->next;
 #  warn Dumper(\@row); use Data::Dumper;
   return unless (@row);
   return $self->_construct_object(@row);
@@ -417,54 +432,8 @@ sub _construct_object {
   $new = $self->{attrs}{record_filter}->($new)
     if exists $self->{attrs}{record_filter};
  
-  if( $self->{attrs}->{cache} ) {
-    while( my( $rel, $rs ) = each( %{$self->{related_resultsets}} ) ) {
-      $rs->all;
-      #warn "$rel:", @{$rs->get_cache};
-    }
-    $self->build_rr( $self, $new );
-  }
   return $new;
 }
-  
-sub build_rr {
-  # build related resultsets for supplied object
-  my ( $self, $context, $obj ) = @_;
-  
-  my $re = qr/^\w+\./;
-  while( my ($rel, $rs) = each( %{$context->{related_resultsets}} ) ) {  
-    #warn "context:", $context->result_source->name, ", rel:$rel, rs:", $rs->result_source->name;
-    my @objs = ();
-    my $map = {};
-    my $cond = $context->result_source->relationship_info($rel)->{cond};
-    keys %$cond;
-    while( my( $rel_key, $pk ) = each(%$cond) ) {
-      $rel_key =~ s/$re//;
-      $pk =~ s/$re//;
-      $map->{$rel_key} = $pk;
-    }
-    
-    $rs->reset();
-    while( my $rel_obj = $rs->next ) {
-      while( my( $rel_key, $pk ) = each(%$map) ) {
-        if( $rel_obj->get_column($rel_key) eq $obj->get_column($pk) ) {
-          push @objs, $rel_obj;
-        }
-      }
-    }
-
-    my $rel_rs = $obj->related_resultset($rel);
-    $rel_rs->{attrs}->{cache} = 1;
-    $rel_rs->set_cache( \@objs );
-    
-    while( my $rel_obj = $rel_rs->next ) {
-      $self->build_rr( $rs, $rel_obj );
-    }
-    
-  }
-  
-}
 
 =head2 result_source
 
@@ -555,7 +524,7 @@ sub all {
     my @obj = map { $self->_construct_object(@$_); }
             $self->cursor->all;
     $self->set_cache( \@obj );
-    return @{ $self->get_cache };
+    return @obj;
   }
   return map { $self->_construct_object(@$_); }
            $self->cursor->all;
@@ -741,8 +710,8 @@ sub create {
 
   $class->find_or_create({ key => $val, ... });
 
-Searches for a record matching the search condition; if it doesn't find one,    
-creates one and returns that instead.                                       
+Searches for a record matching the search condition; if it doesn't find one,
+creates one and returns that instead.
 
   my $cd = $schema->resultset('CD')->find_or_create({
     cdid   => 5,
@@ -903,13 +872,12 @@ sub related_resultset {
       "search_related: result source '" . $self->result_source->name .
       "' has no such relationship ${rel}")
       unless $rel_obj; #die Dumper $self->{attrs};
-    my $rs;
-    if( $self->{attrs}->{cache} ) {
-      $rs = $self->search(undef);
-    }
-    else {
-      $rs = $self->search(undef, { join => $rel });
-    }
+    my $rs = $self->search(undef, { join => $rel });
+    #if( $self->{attrs}->{cache} ) {
+    #  $rs = $self->search(undef);
+    #}
+    #else {
+    #}
     #use Data::Dumper; die Dumper $rs->{attrs};#$rs = $self->search( undef );
     #use Data::Dumper; warn Dumper $self->{attrs}, Dumper $rs->{attrs};
     my $alias = (defined $rs->{attrs}{seen_join}{$rel}
@@ -1161,7 +1129,7 @@ then search against all mothers of those children:
                       ]
                   ],
                   { 'mother.person_id' => 'child.mother_id' }
-              ],                
+              ],
           ]
       },
   );