Added more notes to the bottom of the failing testcase
Rob Kinyon [Sun, 1 Mar 2009 05:13:38 +0000 (05:13 +0000)]
t/98rows_prefetch.t

index 10bc2a9..d7ec720 100644 (file)
@@ -12,16 +12,16 @@ plan $@ ? (skip_all => 'needs DBD::SQLite for testing') : (tests => 2);
 my $schema = DBICTest->init_schema();
 $schema->storage->debug(1);
 my $no_prefetch = $schema->resultset('Artist')->search(
-       undef,
-       { rows => 3 }
+  undef,
+  { rows => 3 }
 );
 
 my $use_prefetch = $schema->resultset('Artist')->search(
-       undef,
-       {
-               prefetch => 'cds',
-               rows     => 3
-       }
+  undef,
+  {
+    prefetch => 'cds',
+    rows     => 3
+  }
 );
 
 my $no_prefetch_count  = 0;
@@ -29,21 +29,76 @@ my $use_prefetch_count = 0;
 
 is($no_prefetch->count, $use_prefetch->count, '$no_prefetch->count == $use_prefetch->count');
 
-# The fix is to, when using prefetch, take the query and put it into a subquery
-# joined to the tables we're prefetching from. This might result in the same
-# table being joined once in the main subquery and once in the main query. This
-# may actually resolve other, unknown edgecase bugs. It is also the right way
-# to do prefetching. Optimizations can come later.
-
 TODO: {
-       local $TODO = "This is a difficult bug to fix, workaround is not to use prefetch with rows";
-       $no_prefetch_count++  while $no_prefetch->next;
-       $use_prefetch_count++ while $use_prefetch->next;
-       is(
-               $no_prefetch_count,
-               $use_prefetch_count,
-               "manual row count confirms consistency"
-               . " (\$no_prefetch_count == $no_prefetch_count, "
-               . " \$use_prefetch_count == $use_prefetch_count)"
-       );
+  local $TODO = "This is a difficult bug to fix, workaround is not to use prefetch with rows";
+  $no_prefetch_count++  while $no_prefetch->next;
+  $use_prefetch_count++ while $use_prefetch->next;
+  is(
+    $no_prefetch_count,
+    $use_prefetch_count,
+    "manual row count confirms consistency"
+    . " (\$no_prefetch_count == $no_prefetch_count, "
+    . " \$use_prefetch_count == $use_prefetch_count)"
+  );
 }
+__END__
+my $rs1 = $schema->resultset('Artist')->search(
+    undef, {
+#        join => 'cds',
+    },
+);
+warn ${$rs1->as_query}->[0], $/;
+{ my @x = $rs1->all; warn "$#x\n"; }
+
+my $rs2 = $schema->resultset('Artist')->search(
+    undef, {
+        from => [{
+            me => $rs1->as_query,
+        }],
+        prefetch => 'cds',
+    },
+);
+
+warn ${$rs2->as_query}->[0], $/;
+{ my @x = $rs2->all; warn "$#x\n"; }
+
+__END__
+The fix is to, when using prefetch, take the query and put it into a subquery
+joined to the tables we're prefetching from. This might result in the same
+table being joined once in the main subquery and once in the main query. This
+may actually resolve other, unknown edgecase bugs. It is also the right way
+to do prefetching. Optimizations can come later.
+
+This means that:
+  $foo_rs->search(
+    { ... },
+    {
+      prefetch => 'bar',
+      ...
+    },
+  );
+
+becomes:
+  my $temp = $foo_rs->search(
+    { ... },
+    {
+      join => 'bar',
+      ...
+    },
+  );
+  $foo_rs->storage->schema->resultset('foo')->search(
+    undef,
+    {
+      from => [
+        { me => $temp->as_query },
+      ],
+      prefetch => 'bar',
+    },
+  );
+
+Problem:
+  * The prefetch->join change needs to happen ONLY IF there are conditions
+    that depend on bar being joined.
+  * How will this work when the $rs is further searched on? Those clauses
+    need to be added to the subquery, not the outer one. This is particularly
+    true if rows is added in the attribute later per the Pager.