[Dbix-class] is joining a table twice with nesting possible?
James Marca
jmarca at translab.its.uci.edu
Wed Oct 22 19:16:33 BST 2008
On Tue, Oct 21, 2008 at 09:05:52AM +0100, Howe, Tom (IT) wrote:
> I'm not sure if this works but I would try something like...
>
> join => [ { cds=>ripped }, { cds=>ripped } ]
Ha! Awesome advice. I guess in my late-night hacking I didn't try
that combination.
To sum up problem and solution, reverting to my actual case of images
and dimensions, not the artists, cds, and albums trivial example.
I have a table with image data called images (time stamp, id, etc), a
three-way join table called images_transforms_blobs that stores the
record of up to 4 transforms per image. Transform.id=1 is no op,
transform.id=2 is thumbnail, transform.id=3 is a pixie (smaller,
square thumbnail), tr.id=4 is a display image to fit the screen, and
anything greater than 4 is a custom rotation/brightening/etc/
transform done per image.
I want to pull down in one record the rotated/transformed image's
dimensions, and the thumbnail image's dimensions. I can do it in two
records with stock dbic, but that requires post processing using a
hash, and then re-sorting the list back in to temporal order---a waste
of cpu cycles.
In sql, I would just say (simple case)
mysql> select images.id, images.create_timestamp, tb.width as thumbw,
tb.height as thumbh, ob.width as origw, ob.height as origh
from images
join images_transforms_blobs ttb on (images.id=ttb.image_id)
join images_transforms_blobs tob on (images.id=tob.image_id)
join blobs tb on (tb.id=ttb.blob_id)
join blobs ob on (ob.id=tob.blob_id)
where tob.transform_id > 4
and ttb.transform_id=2
and images.id = 48029;
+-------+---------------------+--------+--------+-------+-------+
| id | create_timestamp | thumbw | thumbh | origw | origh |
+-------+---------------------+--------+--------+-------+-------+
| 48029 | 2008-10-14 14:07:48 | 192 | 128 | 3008 | 2000 |
+-------+---------------------+--------+--------+-------+-------+
1 row in set (0.00 sec)
So to get this nested duplicate join in my real application, my perl is
my $biglist = [
$c->model('GraceDBIC::Images')->search(
{
'upload_group_id' => $group,
'images_transforms_blobs.transform_id' => 2,
'images_transforms_blobs_2.transform_id' => { '>', '4' },
},
{
'join' => [
{ 'images_transforms_blobs' => 'blobs', },
{ 'images_transforms_blobs' => 'blobs', },
],
'order_by' => 'create_timestamp',
'+select' => [
'blobs.width', 'blobs.height',
'blobs_2.width', 'blobs_2.height',
'images_transforms_blobs.transform_id',
],
'+as' => [ 'thumbwidth', 'thumbheight','iwidth', 'iheight', 'tid' ],
'prefetch' =>
[ { 'imageaoi' => 'aoi', }, { 'note' => 'gracenote', }, ],
}
)
];
And the generated sql is (slightly formatted from the debug dump)
SELECT me.id, me.filename, me.upload_group_id, me.create_timestamp, me.del,
blobs.width, blobs.height,
blobs_2.width, blobs_2.height,
images_transforms_blobs.transform_id,
imageaoi.image_id, imageaoi.aoi_id,
aoi.aoi_id, aoi.aleft, aoi.atop, aoi.awidth, aoi.aheight,
note.note_id, note.image_id,
gracenote.id, gracenote.image_id, gracenote.title, gracenote.comment, gracenote.del
FROM images me
LEFT JOIN images_transforms_blobs images_transforms_blobs
ON ( images_transforms_blobs.image_id = me.id )
LEFT JOIN blobs blobs
ON ( blobs.id = images_transforms_blobs.blob_id )
LEFT JOIN images_transforms_blobs images_transforms_blobs_2
ON ( images_transforms_blobs_2.image_id = me.id )
LEFT JOIN blobs blobs_2
ON ( blobs_2.id = images_transforms_blobs_2.blob_id )
LEFT JOIN image_aoi imageaoi
ON ( imageaoi.image_id = me.id )
LEFT JOIN aoi aoi
ON ( aoi.aoi_id = imageaoi.aoi_id )
LEFT JOIN image_note note
ON ( note.image_id = me.id )
LEFT JOIN grace_notes gracenote
ON ( gracenote.id = note.note_id )
WHERE ( images_transforms_blobs.transform_id = ?
AND images_transforms_blobs_2.transform_id > ?
AND upload_group_id = ? )
ORDER BY create_timestamp
: '2', '4', '1163'
Very cool, and no need to hack the 'from' parameter option.
Cheers,
James
--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
More information about the DBIx-Class
mailing list