Fix $rs->next when using HRI with right-join-side data injected into main obj
Alexander Kuznetsov [Thu, 10 Mar 2011 16:37:59 +0000 (11:37 -0500)]
Changes
lib/DBIx/Class.pm
lib/DBIx/Class/ResultClass/HashRefInflator.pm
t/76select.t

diff --git a/Changes b/Changes
index 32559b7..b063ea9 100644 (file)
--- a/Changes
+++ b/Changes
@@ -58,6 +58,8 @@ Revision history for DBIx::Class
         - Fix populate() with \[], arrays (datatype) and other exotic values
         - Fix complex limits (RNO/RowNum/FetchFirst/Top/GenSubq) with
           sub-selects in the selectors list (correlated subqueries)
+        - Fix inconsistency between $rs->next with and without HRI when all
+          the "root" columns are in fact injected from the right rs side
 
     * Misc
         - Rewire all warnings to a new Carp-like implementation internal
index 75d97fc..cc63fab 100644 (file)
@@ -272,6 +272,8 @@ is traditional :)
 
 abraxxa: Alexander Hartmaier <abraxxa@cpan.org>
 
+acca: Alexander Kuznetsov <acca@cpan.org>
+
 aherzog: Adam Herzog <adam@herzogdesigns.com>
 
 Alexander Keusch <cpan@keusch.at>
index dd56130..ca5e0ea 100644 (file)
@@ -63,7 +63,7 @@ recommended.
 #
 
 # This coderef is a simple recursive function
-# Arguments: ($me, $prefetch) from inflate_result() below
+# Arguments: ($me, $prefetch, $is_root) from inflate_result() below
 my $mk_hash;
 $mk_hash = sub {
     if (ref $_[0] eq 'ARRAY') {     # multi relationship
@@ -80,10 +80,13 @@ $mk_hash = sub {
                 ( $_[1] ? (keys %{$_[1]}) : () )
         };
 
-        # if there is at least one defined column consider the resultset real
-        # (and not an emtpy has_many rel containing one empty hashref)
+        # if there is at least one defined column *OR* we are at the root of
+        # the resultset - consider the result real (and not an emtpy has_many
+        # rel containing one empty hashref)
         # an empty arrayref is an empty multi-sub-prefetch - don't consider
         # those either
+        return $hash if $_[2];
+
         for (values %$hash) {
             if (ref $_ eq 'ARRAY') {
               return $hash if @$_;
@@ -109,7 +112,8 @@ Inflates the result and prefetched data into a hash-ref (invoked by L<DBIx::Clas
 # inflate_result is invoked as:
 # HRI->inflate_result ($resultsource_instance, $main_data_hashref, $prefetch_data_hashref)
 sub inflate_result {
-    return $mk_hash->($_[2], $_[3]);
+    return $mk_hash->($_[2], $_[3], 'is_root');
+
 }
 
 
index d2cc72e..dca5654 100644 (file)
@@ -165,4 +165,68 @@ is_deeply(
   'columns/select/as fold properly on sub-searches',
 );
 
+# *very* esoteric use-case, yet valid (the "empty" object should not be undef):
+$rs = $schema->resultset('Artist');
+$rs->create({ artistid => 69, name => 'Ranetki' });
+
+my $relations_or_1_count =
+  $rs->search_related('cds')->count
+    +
+  $rs->search({ 'cds.cdid' => undef }, { join => 'cds' })->count
+;
+
+my $weird_rs = $rs->search({}, {
+  order_by => { -desc => [ 'me.artistid', 'cds.cdid' ] },
+  columns => [{ cd_title => 'cds.title', cd_year => 'cds.year' }],
+  join => 'cds',
+});
+
+my $weird_rs_hri = $weird_rs->search({}, { result_class => 'DBIx::Class::ResultClass::HashRefInflator' });
+
+for my $rs ($weird_rs, $weird_rs_hri) {
+  is ($rs->count, $relations_or_1_count, 'count on rhs data injection matches');
+
+  my @all;
+  while (my $r = $rs->next) {
+    push @all, $r;
+  }
+
+  is (scalar @all, $relations_or_1_count, 'object count on rhs data injection matches');
+  is_deeply (
+    ( $rs->result_class eq 'DBIx::Class::ResultClass::HashRefInflator'
+        ? \@all
+        : [ map { +{$_->get_columns} } @all ]
+    ),
+    [
+      {
+        cd_title => undef,
+        cd_year => undef,
+      },
+      {
+        cd_title => "Come Be Depressed With Us",
+        cd_year => 1998,
+      },
+      {
+        cd_title => "Generic Manufactured Singles",
+        cd_year => 2001,
+      },
+      {
+        cd_title => "Caterwaulin' Blues",
+        cd_year => 1997,
+      },
+      {
+        cd_title => "Forkful of bees",
+        cd_year => 2001,
+      },
+      {
+        cd_title => "Spoonful of bees",
+        cd_year => 1999,
+      },
+    ],
+    'Correct data retrieved'
+  );
+
+  is_deeply( [ $rs->all ], \@all, '->all matches' );
+}
+
 done_testing;