[Dbix-class] complex relationships I

Matt S Trout dbix-class at trout.me.uk
Fri Sep 21 17:37:08 GMT 2007


On Thu, Sep 20, 2007 at 11:32:20AM -0700, Benjamin Hitz wrote:
> 
> Hi, we are in the process of replacing an old, hand-rolled API (and  
> bags-o-sql) with DBIc.  Our Oracle database is pretty large (~110  
> tables) with some complicated relationships.  We have used  
> DBIx::Class::Schema::Loader::Oracle to generate some table classes,  
> but of course they don't find all the many-to-manys.
> 
> Looking for some advice on how to implement a couple types of  
> relationships (This is long, so I will put the next one in another  
> email)
> 
> "Trees" e.g.:
> CREATE TABLE CV_TERM
> (CV_TERM_NO NUMBER(10) NOT NULL
> ,CV_NO NUMBER(10) NOT NULL
> ,TERM_NAME VARCHAR2(1024) NOT NULL
> ,DBXREF_ID VARCHAR2(40)
> ,DATE_CREATED DATE DEFAULT SYSDATE NOT NULL
> ,CREATED_BY VARCHAR2(12) DEFAULT SUBSTR(USER,1,12) NOT NULL
> ,CVTERM_DEFINITION VARCHAR2(4000)
> )
> CREATE TABLE CVTERM_RELATIONSHIP
> (CVTERM_RELATIONSHIP_NO NUMBER(10) NOT NULL
> ,CHILD_CV_TERM_NO NUMBER(10) NOT NULL
> ,PARENT_CV_TERM_NO NUMBER(10) NOT NULL
> ,RELATIONSHIP_TYPE VARCHAR2(40) NOT NULL
> ,DATE_CREATED DATE DEFAULT SYSDATE NOT NULL
> ,CREATED_BY VARCHAR2(12) DEFAULT SUBSTR(USER,1,12) NOT NULL
> )
> So CVTERM_RELATIONSHIP has two foreign keys to the CV_TERM table.

Shouldn't the parent id be the PK if multiple parents are disallowed?
 
> This comes out from Schema::Loader as:
> 
> In the Cv_term.pm module:
> 
> __PACKAGE__->has_many(
>   "cvterm_relationship_child_cv_term_noes",
>   "DB::Mod::Cvterm_relationship",
>   { "foreign.child_cv_term_no" => "self.cv_term_no" },
> );
> __PACKAGE__->has_many(
>   "cvterm_relationship_parent_cv_term_noes",
>   "DB::Mod::Cvterm_relationship",
>   { "foreign.parent_cv_term_no" => "self.cv_term_no" },
> );

and then this could be a belongs_to

> In the Cvterm_relationship.pm module:
> __PACKAGE__->belongs_to(
>   "child_cv_term_no",
>   "DB::Mod::Cv_term",
>   { cv_term_no => "child_cv_term_no" },
> );
> __PACKAGE__->belongs_to(
>   "parent_cv_term_no",
>   "DB::Mod::Cv_term",
>   { cv_term_no => "parent_cv_term_no" },
> );
> 
> So, I would guess I want to add:
> 
> __PACKAGE__->many_to_many (children =>  
> 'cvterm_relationship_child_cv_term_noes', 'child_cv_term_no');
> and
> __PACKAGE__->many_to_many (parents =>  
> 'cvterm_relationship_parent_cv_term_noes', 'parent_cv_term_no');
> 
> to Cv_term.pm
> 
> Of course, this is kinda silly because we don't really have multiple  
> parents (but it is technically allowed in the schema).

Well, a many-many is really a bridge across two relationships. They don't
technically have to include a one-many one.

> So if I did something like:
> 
> my $CvTermObj = DBIx::Class::Schema::Subclass->schema->resultset 
> ('CV_TERM')->find({term_name => 'physical interactions'});
> (actually not sure if find returns a single object in scalar context,  
> but that's a detail)

find() always returns either a single object or undef.

You might find writing the parent method by hand best so that it enforces
what your schema doesn't.

> my @arrayOfChildrenWhichAreAlsoCvTermObjs = $cvTermObj->children();
> 
> That didn't seem so bad... maybe the next one is tougher?

I've done pretty much exactly this one before except a multi-parent DAG.

So no, it's not so bad :)

-- 
      Matt S Trout       Need help with your Catalyst or DBIx::Class project?
   Technical Director                    http://www.shadowcat.co.uk/catalyst/
 Shadowcat Systems Ltd.  Want a managed development or deployment platform?
http://chainsawblues.vox.com/            http://www.shadowcat.co.uk/servers/



More information about the DBIx-Class mailing list