BUMP!
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
DB::Mod::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 the second of two emails, and I think is
where it starts to get ugly
"Triple Linking Tables"
e.g.
CREATE TABLE GO_ANNOTATION
(GO_ANNOTATION_NO NUMBER(10) NOT NULL
,GO_NO NUMBER(10) NOT NULL
,FEATURE_NO NUMBER(10) NOT NULL
,GO_EVIDENCE VARCHAR2(40) NOT NULL
,ANNOTATION_TYPE VARCHAR2(40) NOT NULL
,SOURCE VARCHAR2(40) NOT NULL
,DATE_LAST_REVIEWED DATE DEFAULT SYSDATE NOT NULL
,DATE_CREATED DATE DEFAULT SYSDATE NOT NULL
,CREATED_BY VARCHAR2(12) DEFAULT SUBSTR(USER,1,12) NOT NULL
)
ALTER TABLE GO_ANNOTATION
ADD (CONSTRAINT GO_ANNOTATION_UK UNIQUE
(GO_NO
,FEATURE_NO
,GO_EVIDENCE
,ANNOTATION_TYPE
,SOURCE)
ALTER TABLE GO_ANNOTATION ADD (CONSTRAINT
GOANN_GO_FK FOREIGN KEY
(GO_NO) REFERENCES GO
(GO_NO))
/
ALTER TABLE GO_ANNOTATION ADD (CONSTRAINT
GOANN_FEAT_FK FOREIGN KEY
(FEATURE_NO) REFERENCES FEATURE
(FEATURE_NO) ON DELETE CASCADE)
/
CREATE TABLE GO
(GO_NO NUMBER(10) NOT NULL
,GOID NUMERIC(10) NOT NULL
,GO_TERM VARCHAR2(240) NOT NULL
,GO_ASPECT VARCHAR2(40) NOT NULL
,GO_DEFINITION VARCHAR2(2000)
,DATE_CREATED DATE DEFAULT SYSDATE NOT NULL
,CREATED_BY VARCHAR2(12) DEFAULT SUBSTR(USER,1,12) NOT NULL
)
ALTER TABLE GO
ADD (CONSTRAINT GO_PK PRIMARY KEY
(GO_NO)
ALTER TABLE GO
ADD (CONSTRAINT GO_TERM_UK UNIQUE
(GO_TERM
,GO_ASPECT)
ALTER TABLE GO
ADD (CONSTRAINT GO_GOID_UK UNIQUE
(GOID)
CREATE TABLE FEATURE
(FEATURE_NO NUMBER(10) NOT NULL
,FEATURE_NAME VARCHAR2(40) NOT NULL
,DBXREF_ID VARCHAR2(40) NOT NULL
,FEATURE_TYPE VARCHAR2(40) NOT NULL
,SOURCE VARCHAR2(40) NOT NULL
,COORD_VERSION DATE
,STOP_COORD NUMBER(10)
,START_COORD NUMBER(10)
,STRAND VARCHAR2(1)
,GENE_NAME VARCHAR2(10)
,NAME_DESCRIPTION VARCHAR2(100)
,GENETIC_POSITION NUMBER(5,2)
,HEADLINE VARCHAR2(960)
,DATE_CREATED DATE DEFAULT SYSDATE NOT NULL
,CREATED_BY VARCHAR2(12) DEFAULT SUBSTR(USER,1,12) NOT NULL
)
ALTER TABLE FEATURE
ADD (CONSTRAINT FEATURE_PK PRIMARY KEY
(FEATURE_NO)
ALTER TABLE FEATURE
ADD (CONSTRAINT FEAT_DBXREF_ID_UK UNIQUE
(DBXREF_ID)
CREATE TABLE GO_REF
(GO_REF_NO NUMBER(10) NOT NULL
,REFERENCE_NO NUMBER(10) NOT NULL
,GO_ANNOTATION_NO NUMBER(10) NOT NULL
,HAS_QUALIFIER VARCHAR2(1) NOT NULL
,HAS_SUPPORTING_EVIDENCE VARCHAR2(1) NOT NULL
,DATE_CREATED DATE DEFAULT SYSDATE NOT NULL
,CREATED_BY VARCHAR2(12) DEFAULT SUBSTR(USER,1,12) NOT NULL
)
ALTER TABLE GO_REF
ADD (CONSTRAINT GO_REF_UK UNIQUE
(REFERENCE_NO
,GO_ANNOTATION_NO)
ALTER TABLE GO_REF ADD (CONSTRAINT
GOREF_REF_FK FOREIGN KEY
(REFERENCE_NO) REFERENCES REFERENCE
(REFERENCE_NO) ON DELETE CASCADE)
/
ALTER TABLE GO_REF ADD (CONSTRAINT
GOREF_GOANN_FK FOREIGN KEY
(GO_ANNOTATION_NO) REFERENCES GO_ANNOTATION
(GO_ANNOTATION_NO) ON DELETE CASCADE)
/
CREATE TABLE REFERENCE
(REFERENCE_NO NUMBER(10) NOT NULL
,SOURCE VARCHAR2(40) NOT NULL
,STATUS VARCHAR2(40) NOT NULL
,PDF_STATUS VARCHAR2(40) NOT NULL
,DBXREF_ID VARCHAR2(40) NOT NULL
,CITATION VARCHAR2(480) NOT NULL
,YEAR NUMBER(4) NOT NULL
,PUBMED NUMBER(10)
,DATE_PUBLISHED VARCHAR2(40)
,DATE_REVISED NUMBER(8)
,ISSUE VARCHAR2(40)
,PAGE VARCHAR2(40)
,VOLUME VARCHAR2(40)
,TITLE VARCHAR2(400)
,JOURNAL_NO NUMBER(10)
,BOOK_NO NUMBER(10)
,DATE_CREATED DATE DEFAULT SYSDATE NOT NULL
,CREATED_BY VARCHAR2(12) DEFAULT SUBSTR(USER,1,12) NOT NULL
)
ALTER TABLE REFERENCE
ADD (CONSTRAINT REFERENCE_PK PRIMARY KEY
(REFERENCE_NO)
ALTER TABLE REFERENCE ADD (CONSTRAINT
REF_BOOK_FK FOREIGN KEY
(BOOK_NO) REFERENCES BOOK
(BOOK_NO))
/
ALTER TABLE REFERENCE ADD (CONSTRAINT
REF_JOUR_FK FOREIGN KEY
(JOURNAL_NO) REFERENCES JOURNAL
(JOURNAL_NO))
I didn't get a reply to this, so I am rephrasing it:
DB::Mod.pm is a subclass of DBIx::Class::Schema, the DB::Mod::Table
classes are subclasses of DBIx::Class
And some relationships:
DB::Mod::Feature->has_many(
"go_annotations",
"DB::Mod::Go_annotation",
{ "foreign.feature_no" => "self.feature_no" },
);
DB::Mod::Go_annotation->belongs_to("go_no", "DB::Mod::Go", { go_no =>
"go_no" });
DB::Mod::Go_annotation->belongs_to(
"feature_no",
"DB::Mod::Feature",
{ feature_no => "feature_no" },
);
DB::Mod::Go_annotation->has_many(
"go_refs",
"DB::Mod::Go_ref",
{ "foreign.go_annotation_no" => "self.go_annotation_no" },
);
DB::Mod::Go_ref->belongs_to(
"go_annotation_no",
"DB::Mod::Go_annotation",
{ go_annotation_no => "go_annotation_no" },
);
DB::Mod::Go_ref->belongs_to(
"reference_no",
"DB::Mod::Reference",
{ reference_no => "reference_no" },
);
So we can say:
DB::Mod::Feature->many_to_many(goes => 'go_annotations', 'go_no');
as well as the reverse (obverse?)
DB::Mod::Go->many_to_many(features => 'go_annotations', 'feature_no');
and
DB::Mod::Go_annotation->many_to_many(references=>'go_refs',
'reference_no');
and the reverse
DB::Mod::Reference->many_to_many(go_annotations=>'go_refs',
'go_annotation_no');
BUT say I want the following method:
DB::Mod::Feature->go_references (which returns an array of
DB::Mod::Reference objects)
We cannot make a many_to_many between Feature and Go_ref, because
go_annotation does not belong_to go_ref (it has many)
What is the preferred way of setting this up?
Just make a method in DB::Mod::Feature:
sub go_references {
@refs = ();
for $goAn ($self->go_annotations) {
@refs = (@refs, @{$goAn->refs});
}
# actually we should probably put them in a hash to uniquify them...
return [EMAIL PROTECTED];
}
I have a few other cases in the schema where I want to span a
has_many -> many_to_many... should I my own relationship, or just
write specific methods (yes, I realize this is a style question)
Thanks,
Ben
--
Ben Hitz
Senior Scientific Programmer ** Saccharomyces Genome Database ** GO
Consortium
Stanford University ** [EMAIL PROTECTED]
_______________________________________________
List: http://lists.rawmode.org/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/[EMAIL PROTECTED]