[Dbix-class] DBIC_TRACE query OK but code throws an exception
(many-to-many relationship)
Denis BAURAIN
denis.baurain at ulg.ac.be
Fri Oct 22 15:41:09 GMT 2010
Hi,
I am new to DBIC and to this list. Thus, I apologise in advance if my
first question has already been asked a thousand times.
I am struggling to convert an existing SQL query into DBIC parlance...
Oddly, DBIC_TRACE shows that the expected query is indeed built but my
Perl code throws an error. I would appreciate any enlightenment about
what I am necessarily doing wrong... I provide the minimal context below.
The query uses four tables with the following relevant relationships:
1. miRNA table
__PACKAGE__->belongs_to(
"species",
"Bio::DB::miRBase::Result::species",
{ auto_id => "auto_species" },
);
__PACKAGE__->has_many(
"miRNA_matures",
"Bio::DB::miRBase::Result::miRNA_mature",
{ "foreign.auto_mirna" => "self.auto_mirna" },
);
2. species table
__PACKAGE__->has_many(
"miRNAs",
"Bio::DB::miRBase::Result::miRNA",
{ "foreign.auto_species" => "self.auto_id" },
);
3. miRNA_mature (many-to-many bridging table)
__PACKAGE__->belongs_to(
"mature",
"Bio::DB::miRBase::Result::mature",
{ auto_mature => "auto_mature" },
);
__PACKAGE__->belongs_to(
"miRNA",
"Bio::DB::miRBase::Result::miRNA",
{ auto_mirna => "auto_mirna" },
);
4. mature table
__PACKAGE__->has_many(
"miRNA_matures",
"Bio::DB::miRBase::Result::miRNA_mature",
{ "foreign.auto_mature" => "self.auto_mature" },
);
I want to start from miRNA table, then filter rows based on a column in
species table, and finally return two columns from mature table (through
the miRNA_mature bridging table). I also want to avoid duplicate rows
arising from the many-to-many relationship. My code is as follows:
my @matures = $schema->resultset('miRNA')
->search( {'species.name' => 'Homo sapiens'}, {
'join' => ['species', {'miRNA_matures' => 'mature'}],
'distinct' => 1,
'columns' => [qw/mature.mature_acc mature.mature_name/]
})->all
;
Here's the output with the error. If I fill the '?' placeholder and run
the traced query against the database, it gives me what I want (see below).
DBIC_TRACE=1 time perl -Ilib t/scratchpad.t
ok 1 - database connection
SELECT mature.mature_acc, mature.mature_name FROM mirna me JOIN
mirna_species species ON species.auto_id = me.auto_species LEFT JOIN
mirna_pre_mature miRNA_matures ON miRNA_matures.auto_mirna =
me.auto_mirna LEFT JOIN mirna_mature mature ON mature.auto_mature =
miRNA_matures.auto_mature WHERE ( species.name = ? ) GROUP BY
mature.mature_acc, mature.mature_name: 'Homo sapiens'
No such relationship 'mature' on miRNA at /Users/denis/perl5/perlbrew/
perls/perl-5.10.1/lib/site_perl/5.10.1/DBIx/Class/Schema.pm line 1037
DBIx::Class::Schema::throw_exception('Bio::DB::miRBase=HASH(0x8f3350)',
'No such relationship \'mature\' on miRNA') called at /Users/denis/perl5/
perlbrew/perls/perl-5.10.1/lib/site_perl/5.10.1/DBIx/Class/
ResultSource.pm line 1562
DBIx::Class::ResultSource::throw_exc
eption('DBIx::Class::ResultSource::Table=HASH(0x8137f0)', 'No such
relationship \'mature\' on miRNA') called at /Users/denis/perl5/perlbrew/
perls/perl-5.10.1/lib/site_perl/5.10.1/DBIx/Class/ResultSource.pm line 1511
DBIx::Class::ResultSource::related_s
ource('DBIx::Class::ResultSource::Table=HASH(0x8137f0)', 'mature')
called at /Users/denis/perl5/perlbrew/perls/perl-5.10.1/lib/site_perl/
5.10.1/DBIx/Class/Row.pm line 1142
DBIx::Class::Row::inflate_result('Bio::DB::miRBase::Result::miRNA',
'DBIx::Class::ResultSource::Table=HASH(0x8137f0)', undef,
'HASH(0xf40a70)') called at /Users/denis/perl5/perlbrew/perls/
perl-5.10.1/lib/site_perl/5.10.1/DBIx/Class/ResultSet.pm line 976
DBIx::Class::ResultSet::_construct_o
bject('Bio::DB::miRBase::ResultSet::miRNA=HASH(0xba2a50)',
'MIMAT0000062', 'hsa-let-7a') called at /Users/denis/perl5/perlbrew/
perls/perl-5.10.1/lib/site_perl/5.10.1/DBIx/Class/ResultSet.pm line 1372
DBIx::Class::ResultSet::all('Bio::DB
::miRBase::ResultSet::miRNA=HASH(0xba2a50)') called at t/scratchpad.t line 15
1..1
# Looks like your test exited with 2 just after 1.
0.90 real 0.81 user 0.07 sys
leela:Bio-DB-miRBase denis$
leela:Bio-DB-miRBase denis$ sqlite3 database/database.sqlite
SQLite version 3.4.0
Enter ".help" for instructions
sqlite> SELECT mature.mature_acc, mature.mature_name FROM mirna me JOIN
mirna_species species ON species.auto_id = me.auto_species LEFT JOIN
mirna_pre_mature miRNA_matures ON miRNA_matures.auto_mirna =
me.auto_mirna LEFT JOIN mirna_mature mature ON mature.auto_mature =
miRNA_matures.auto_mature WHERE ( species.name = 'Homo sapiens' ) GROUP
BY mature.mature_acc, mature.mature_name;
MIMAT0000062|hsa-let-7a
MIMAT0000063|hsa-let-7b
MIMAT0000064|hsa-let-7c
MIMAT0000065|hsa-let-7d
MIMAT0000066|hsa-let-7e
MIMAT0000067|hsa-let-7f
MIMAT0000068|hsa-miR-15a
MIMAT0000069|hsa-miR-16
MIMAT0000070|hsa-miR-17
MIMAT0000071|hsa-miR-17*
MIMAT0000072|hsa-miR-18a
MIMAT0000073|hsa-miR-19a
MIMAT0000074|hsa-miR-19b
MIMAT0000075|hsa-miR-20a
MIMAT0000076|hsa-miR-21
[SNIP]
Bonus question: I also have accessors for computed attributes in
Result::mature. Is it possible to use them on a variant of the previous
resultset without re-finding each row using the primary key?
Thanks,
Denis
A+
Denis
More information about the DBIx-Class
mailing list