Radically rethink complex prefetch - make most useful cases just work (tm)
[dbsrgits/DBIx-Class.git] / t / prefetch / grouped.t
index c8c3e87..b7ec8eb 100644 (file)
@@ -2,11 +2,13 @@ use strict;
 use warnings;
 
 use Test::More;
-use Test::Exception;
 
 use lib qw(t/lib);
 use DBICTest;
 use DBIC::SqlMakerTest;
+use DBIx::Class::SQLMaker::LimitDialects;
+
+my $ROWS = DBIx::Class::SQLMaker::LimitDialects->__rows_bindtype;
 
 my $schema = DBICTest->init_schema();
 my $sdebug = $schema->storage->debug;
@@ -152,10 +154,10 @@ for ($cd_rs->all) {
             FROM cd me
           WHERE ( me.cdid IS NOT NULL )
           GROUP BY me.cdid
-          LIMIT 2
+          LIMIT ?
         ) me
     )',
-    [],
+    [[$ROWS => 2]],
     'count() query generated expected SQL',
   );
 
@@ -172,19 +174,19 @@ for ($cd_rs->all) {
           WHERE ( me.cdid IS NOT NULL )
           GROUP BY me.cdid
           ORDER BY track_count DESC, maxtr ASC
-          LIMIT 2
+          LIMIT ?
         ) me
         LEFT JOIN track tracks ON tracks.cd = me.cdid
         LEFT JOIN liner_notes liner_notes ON liner_notes.liner_id = me.cdid
       WHERE ( me.cdid IS NOT NULL )
-      ORDER BY track_count DESC, maxtr ASC, tracks.cd
+      ORDER BY track_count DESC, maxtr ASC
     )',
-    [],
+    [[$ROWS => 2]],
     'next() query generated expected SQL',
   );
 
   is ($most_tracks_rs->count, 2, 'Limit works');
-  my $top_cd = $most_tracks_rs->first;
+  my ($top_cd) = $most_tracks_rs->all;
   is ($top_cd->id, 2, 'Correct cd fetched on top'); # 2 because of the slice(1,1) earlier
 
   my $query_cnt = 0;
@@ -205,6 +207,71 @@ for ($cd_rs->all) {
   $schema->storage->debug ($sdebug);
 }
 
+{
+  # test lifted from soulchild
+
+  my $most_tracks_rs = $schema->resultset ('CD')->search (
+    {
+      'me.cdid' => { '!=' => undef },  # this is just to test WHERE
+      'tracks.trackid' => { '!=' => undef },
+    },
+    {
+      join => 'tracks',
+      prefetch => 'liner_notes',
+      select => ['me.cdid', 'liner_notes.notes', { count => 'tracks.trackid', -as => 'tr_count' }, { max => 'tracks.trackid', -as => 'tr_maxid'} ],
+      as => [qw/cdid notes track_count max_track_id/],
+      order_by => [ { -desc => 'tr_count' }, { -asc => 'tr_maxid' } ],
+      group_by => 'me.cdid',
+      rows => 2,
+    }
+  );
+
+  is_same_sql_bind(
+    $most_tracks_rs->as_query,
+    '(SELECT  me.cdid, liner_notes.notes, me.tr_count, me.tr_maxid,
+              liner_notes.liner_id, liner_notes.notes
+        FROM (
+          SELECT me.cdid, COUNT(tracks.trackid) AS tr_count, MAX(tracks.trackid) AS tr_maxid
+            FROM cd me
+            LEFT JOIN track tracks
+              ON tracks.cd = me.cdid
+          WHERE me.cdid IS NOT NULL AND tracks.trackid IS NOT NULL
+          GROUP BY me.cdid
+          ORDER BY tr_count DESC, tr_maxid ASC
+          LIMIT ?
+        ) me
+        LEFT JOIN track tracks
+          ON tracks.cd = me.cdid
+        LEFT JOIN liner_notes liner_notes
+          ON liner_notes.liner_id = me.cdid
+      WHERE me.cdid IS NOT NULL AND tracks.trackid IS NOT NULL
+      ORDER BY tr_count DESC, tr_maxid ASC
+    )',
+    [[$ROWS => 2]],
+    'Oddball mysql-ish group_by usage yields valid SQL',
+  );
+
+  is ($most_tracks_rs->count, 2, 'Limit works');
+  my ($top_cd) = $most_tracks_rs->all;
+  is ($top_cd->id, 2, 'Correct cd fetched on top'); # 2 because of the slice(1,1) earlier
+
+  my $query_cnt = 0;
+  $schema->storage->debugcb ( sub { $query_cnt++ } );
+  $schema->storage->debug (1);
+
+  is ($top_cd->get_column ('track_count'), 4, 'Track count fetched correctly');
+  is (
+    $top_cd->liner_notes->notes,
+    'Buy Whiskey!',
+    'Correct liner pre-fetched with top cd',
+  );
+
+  is ($query_cnt, 0, 'No queries executed during prefetched data access');
+  $schema->storage->debugcb (undef);
+  $schema->storage->debug ($sdebug);
+}
+
+
 # make sure that distinct still works
 {
   my $rs = $schema->resultset("CD")->search({}, {
@@ -222,10 +289,9 @@ for ($cd_rs->all) {
           SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track
             FROM cd me
           GROUP BY me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track
-          ORDER BY cdid
         ) me
         LEFT JOIN tags tags ON tags.cd = me.cdid
-      ORDER BY cdid, tags.cd, tags.tag
+      ORDER BY cdid
     )',
     [],
     'Prefetch + distinct resulted in correct group_by',
@@ -348,12 +414,12 @@ for ($cd_rs->all) {
           FROM (SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track, COUNT( tags.tag ) AS test_count
                 FROM cd me LEFT JOIN tags tags ON tags.cd = me.cdid
             GROUP BY me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track, tags.tag
-            ORDER BY tags.tag ASC LIMIT 1)
+            ORDER BY tags.tag ASC LIMIT ?)
             me
           LEFT JOIN tags tags ON tags.cd = me.cdid
-         ORDER BY tags.tag ASC, tags.cd, tags.tag
+         ORDER BY tags.tag ASC
         )
-    }, []);
+    }, [[$ROWS => 1]]);
 }
 
 done_testing;