[Dbix-class] design issues : about database joins and multiple inheritance

Matt S Trout dbix-class at trout.me.uk
Fri Feb 2 09:50:27 GMT 2007


On 1 Feb 2007, at 07:23, Dami Laurent ((PJ)) wrote:

>> -----Message d'origine-----
>> De : Matt S Trout [mailto:dbix-class at trout.me.uk]
>> Envoyé : jeudi, 25. janvier 2007 11:59
>> À : dbix-class at lists.rawmode.org
>> Objet : Re: [Dbix-class] plat-form contest starting soon
>>
>>
>> Which reminds me, you and I still need to sit down and chat
>> about synergies.
>>
>> I reckon I could re-implement the documented interface of
>> DBIx::DataModel atop DBIx::Class in ~3 days and it would
>> actually be quite natural to do so, so I'm more and more
>> suspecting the differences between the projects are largely
>> in terms of how we conceptualise the interface rather than
>> how we actually see the underlying domain.
>
>
> Okay, now that plat-forms is over, let's start investigating some  
> architectural points. For the discussion I will assume a database  
> schema similar to the one in DBIx::Class::Manual::Example. In  
> DBIx::DataModel, this would be written more or less as
>
>   # Create a schema class
>   DBIx::DataModel->Schema('Music');
>
>   # Create table classes
>   #               Perl_class  DB_table  Primary_key
>   #               ----------  --------  -----------
>   Music->Table(qw/Artist      artist    artist_id    /);
>   Music->Table(qw/Cd          cd        cd_id        /);
>   Music->Table(qw/Track       track     track_id     /);
>
>   # Declare UML associations
>   #                      Class   role_name  multiplicity
>   #                      -----   ---------  ------------
>   Music->Association([qw/Artist  artist         1        /],
>                      [qw/Cd      cds            *        /]);
>
>   Music->Composition([qw/Cd      cd             1        /],
>                      [qw/Track   tracks         1..*     /]);
>
>
> Now if I want information about all recent cds and tracks of some  
> artist, I could write
>
>   my $rows = $someArtist->selectFromRoles(qw/cds tracks/)
> 	                  ->(-columns => \@some_column_list,
>                            -where   => {year => {">" => 2004}},
> 	                     -orderBy => 'year');
>
> The equivalent SQL is
>
>   SELECT @some_column_list FROM cd INNER JOIN track ON  
> cd.cd_id=track.cd_id
>                            WHERE artist_id = $someArtist->{artist_id}
>                              AND year > 2004
> 	                     ORDER BY year

my $rs = $artist->search_related('cds',
   { year => { '>' => 2004 } },
   { join => 'tracks', columns => \@columns, order_by => 'year',  
result_class => $class }
);

(see below for discussion of auto-generating $class)

>
> and each row returned by that query will be blessed into a new class
> Music::AutoView::Cd_INNER_Track, created on the fly (if not already  
> there),
> and which inherits from both classes Cd and Track. Multiple  
> inheritance
> makes sense here because a row from that result set contains data  
> from both
> tables (Cd and Track).
>
> Now I have two questions :
>
> 1) would such an idea (creating classes on the fly and using  
> multiple inheritance) be compatible with the architecture of  
> DBIx::Class ? beneficial ? disastrous ?

Well, in the example you give above I'd most likely just search  
across to cds, prefetch back and call $obj->cd->$attr.

However, for more complex virtual views (e.g. cd + track + count 
(times track listened to)) I've always been thinking about creating  
classes on the fly - the resultset just calls

$rs->result_class->inflate_result

and doesn't care what's in there; I've used on-the-fly classes and  
objects for that before now and DBIx::Class really doesn't care. As  
for multiple inheritance, the entire package is built on it, so sure,  
not a problem :)

I think you'd probably hook search_rs or the attr resolution process  
to generate classes on the fly, though I kinda wonder if you mightn't  
be better with some sort of AUTOLOAD hack than MI ... probably  
depends on the use case.

> 2) as far as I understand, DBIx::Class also manipulates the  
> namespace dynamically (loading classes and methods). Did you ever  
> get in trouble when serializing/deserializing such classes through  
> Catalyst sessions, as it just happened to me with DBIx::DataModel ?  
> And if so, how did you solve it ?

So long as the class names are regular it's not really a -major-  
problem, you just have to provide Storable hooks. Our big problem is  
reconnecting to the $schema, which we still don't have a perfect  
solution to.

-- 
Matt S Trout, Technical Director, Shadowcat Systems Ltd.
Offering custom development, consultancy and support contracts for  
Catalyst,
DBIx::Class and BAST. Contact mst (at) shadowcatsystems.co.uk for  
details.
+ Help us build a better perl ORM: http://dbix- 
class.shadowcatsystems.co.uk/ +





More information about the Dbix-class mailing list