Complicated joins with DBIx::Class

DBIx::Class is a great way to hide database interactions in your Perl classes. However, something that you might find easy in normal DBI queries can seem hard in DBIx::Class, because you lack direct access to the SQL. Take for example the following query:

select dayparts.name from eventtyperooms 
  join slots on (eventtyperooms.room_id=slots.room_id) 
  join dayparts on (slots.daypart_id = dayparts.id) 
  where slots.is_reserved=0 and eventtyperooms.eventtype_id='E375219C-CDBB-11E5-8739-AFC57843E904' 
  group by slots.daypart_id 
  order by dayparts.start_date asc;

There are lots of joins going on here and not all of them are on primary keys. Plus we’ve got some other qualifiers in there. This is where search_related() can come to the rescue.

$eventtype->search_related('eventtyperooms')
  ->search_related('slots', {'slots.is_reserved' => 0})
  ->search_related('daypart')
  ->search(undef, {
    group_by => 'slots.daypart_id', 
    order_by => 'daypart.start_date'
  });

The above code will generate the following query:

SELECT `daypart`.`id`, `daypart`.`name`, `daypart`.`is_locked`, `daypart`.`start_date`
  FROM `eventtyperooms` `me` 
  JOIN `slots` `slots` 
    ON `slots`.`room_id` = `me`.`room_id` 
  JOIN `dayparts` `daypart` 
    ON `daypart`.`id` = `slots`.`daypart_id` 
WHERE `me`.`eventtype_id` = 'E375219C-CDBB-11E5-8739-AFC57843E904' AND `slots`.`is_reserved` = '0' 
GROUP BY `slots`.`daypart_id` 
ORDER BY `daypart`.`start_date`

This allows you to use all the existing relationships you’ve set up in your schema to do complex joins.

[From my blog.]

1 Comment

Another option if you need to run ad-hoc SQL and get back a DBIx::Class resultset is the module DBIx::Class::Report. However, according to the author it is Experimental ALPHA code.

Leave a comment

About JT Smith

user-pic My little part in the greater Perl world.