[Dbix-class] Looking for the DBIC way.

Mike Earley mike.earley at verizon.net
Mon Nov 6 14:56:28 GMT 2006


I'm playing around with the example Artist/Cd/Tracks SQLite database
in order to learn DBIC.  I've defined a left outer join relationship
between the artist and cd tables like this:

     package MyDatabase::Main::Artist.pm;

     __PACKAGE__->has_many( 'cds_left_outer',
                            'MyDatabase::Main::Cd',
                            { 'foreign.artist' => 'self.artistid' },
                            { 'join_type'      => 'LEFT OUTER'    } );

When I trace the query I get this (reformated) SQL statement:

     SELECT me.artistid, me.name,
            cds_left_outer.cdid, cds_left_outer.artist, cds_left_outer.title
     FROM   artist me
     LEFT OUTER JOIN cd cds_left_outer ON ( cds_left_outer.artist = me.artistid )
     ORDER BY cds_left_outer.artist

Running this query through SQLite I get these correct results:

     2|Pink Floyd|||
     1|Michael Jackson|1|1|Thriller
     1|Michael Jackson|2|1|Bad
     3|Eminem|3|3|The Marshall Mathers LP

Running this Perl code gives me exactly the same results:

     my $artist_rs = $dbh->resultset( 'Artist' )->search( undef, { prefetch => 'cds_left_outer' } );
     while ( my $artist = $artist_rs->next )
     {
         my $cd_rs = $artist->cds_left_outer;
         if ( $cd_rs->count == 0 )
         {
             print join( '|', $artist->artistid, $artist->name, '', '', '' ), "\n";
         }
         else
         {
             while ( my $cd = $cd_rs->next )
             {
                 print join( '|', $artist->artistid, $artist->name, $cd->cdid, $cd->artist, $cd->title ), "\n";
             }
         }
     }

I also created similar DBI code:

     my $dbh = DBI->connect( 'dbi:SQLite:example.db' );
     my $sth = $dbh->prepare( "
         SELECT me.artistid, me.name,
                cds_left_outer.cdid, cds_left_outer.artist, cds_left_outer.title
         FROM   artist me
         LEFT OUTER JOIN cd cds_left_outer ON ( cds_left_outer.artist = me.artistid )
         ORDER BY cds_left_outer.artist
     " );
     $sth->execute() || die $!;
     while ( my $row = $sth->fetchrow_arrayref() )
     {
         print join( '|', map { $_ || '' } @{$row} ), "\n";
     }

In the DBI version I did not need to program nested loops to access the child
data.  I'm wondering if I'm not seeing some basic DBIC accessor trick? Is
there a different, more DBIC, way to code this or does the has_many nature of
the relationship force me to use nested loops to access the data?

Thanks for any insight or example code.

Mike



More information about the Dbix-class mailing list