我有一张成对的物品表.我想自己加入,所以我可以在单个查询中检索对的双方.它是有效的sql(我认为),sqlite引擎实际上接受它,但我无法获取DBIx :: Class咬住项目符号.
最小的例子
package Schema::Half; use parent 'DBIx::Class'; __PACKAGE__->load_components('Core'); __PACKAGE__->table('half'); __PACKAGE__->add_columns( whole_id => { data_type => 'INTEGER' },half_id => { data_type => 'CHAR' },data => { data_type => 'TEXT' },); __PACKAGE__->has_one(dual => 'Schema::Half',{ 'foreign.whole_id' => 'self.whole_id','foreign.half_id' => 'self.half_id',# prevIoUs line results in a '=' # I'd like a '<>' }); package Schema; use parent 'DBIx::Class::Schema'; __PACKAGE__->register_class( 'Half','Schema::Half' ); package main; unlink 'join.db'; my $s = Schema->connect('dbi:sqlite:join.db'); $s->deploy; my $h = $s->resultset('Half'); $h->populate([ [qw/whole_id half_id data /],[qw/1 L Bonnie/],[qw/1 R Clyde /],[qw/2 L Tom /],[qw/2 R Jerry /],[qw/3 L Batman/],[qw/3 R Robin /],]); $h->search({ 'me.whole_id' => 42 },{ join => 'dual' })->first;
SELECT me.whole_id,me.half_id,me.data FROM half me JOIN half dual ON ( dual.half_id = me.half_id AND dual.whole_id = me.whole_id ) WHERE ( me.whole_id = ? )
我试图使用DBIx :: Class join语法来获取<>操作符在dual.half_id和me.half_id之间,但尚未到目前为止.
我试过的东西
我试着写这个has_one的关系:
__PACKAGE__->has_one(dual => 'Schema::Half','foreign.half_id' => { '<>' => 'self.half_id' },}); # Invalid rel cond val HASH(0x959cc28)
stringref后面的直sql不会使它成为:
__PACKAGE__->has_one(dual => 'Schema::Half','foreign.half_id' => \'<> self.half_id',}); # Invalid rel cond val SCALAR(0x96c10b8)
解决办法以及为什么他们对我来说不够
我可以通过复杂的search()调用获得正确的sql,并且没有定义的关系.这是非常难看的,(也)很多硬编码的sql.对于关系遍历的每个具体情况,它必须以不必要的方式模仿.
我可以通过添加一个other_half_id列并加入=来解决问题.显然是冗余数据.
我甚至试图通过专用视图添加它来避免所述冗余(CREATE VIEW AS SELECT *,opposite_of(side)AS dual FROM half …)而不是数据库模式,它的代码是冗余和丑陋的,moreso比基于search()的解决方法.最后我没有勇气让它工作.
希望sql
这是我正在寻找的那种sql.请注意,这只是一个例子:我真的希望通过关系完成,所以我可以使用它作为Half ResultSet访问器,除了一个search()的连接子句.
sqlite> SELECT * FROM half l JOIN half r ON l.whole_id=r.whole_id AND l.half_id<>r.half_id WHERE l.half_id='L'; 1|L|Bonnie|1|R|Clyde 2|L|Tom|2|R|Jerry 3|L|Batman|3|R|Robin
旁注
我真的很自信,在我的全面扩大的情况下,但我很确定这不是问题.我以这种方式保留这个简单的例子,因为它也有助于保持代码大小小.
我坚持加入/关系路径,而不是复杂的搜索(),因为我有多个用途的关联,我没有找到任何“一刀切”的搜索表达式.
迟到更新
解决方法
一个正确的语法是:
__PACKAGE__->has_one(dual => 'Schema::Half',sub { my $args = shift; my ($foreign,$self) = @$args{qw(foreign_alias self_alias)}; return { "$foreign.whole_id" => { -ident => "$self.whole_id" },"$foreign.half_id" => { '<>' => { -ident => "$self.half_id" } },} });
引用:DBIx::Class Extended Relationships on fREW Schmidt’s blog在哪里我首先阅读它.