я не мог найти правильный способ сделать это, но я был в состоянии жюри установки патча:
diff -rupN DBIx-Class-0.082820/lib/DBIx/Class/ResultSource.pm DBIx-Class-0.082820.new/lib/DBIx/Class/ResultSource.pm
--- DBIx-Class-0.082820/lib/DBIx/Class/ResultSource.pm 2015-03-20 12:31:00.000000000 -0400
+++ DBIx-Class-0.082820.new/lib/DBIx/Class/ResultSource.pm 2015-05-05 17:40:07.646500380 -0400
@@ -1700,6 +1700,12 @@ sub _resolve_join {
or $self->throw_exception("No such relationship $join on " . $self->source_name);
my $rel_src = $self->related_source($join);
+
+ my @grouped_joins;
+ if ($rel_info->{attrs}{join}){
+ @grouped_joins = $rel_src->_resolve_join($rel_info->{attrs}{join}, $as, $seen, [@$jpath, {$join => $as}]);
+ }
+
return [ { $as => $rel_src->from,
-rsrc => $rel_src,
-join_type => $parent_force_left
@@ -1714,6 +1720,7 @@ sub _resolve_join {
),
-alias => $as,
-relation_chain_depth => ($seen->{-relation_chain_depth} || 0) + 1,
+ @grouped_joins ? (-join => \@grouped_joins) :(),
},
scalar $self->_resolve_condition($rel_info->{cond}, $as, $alias, $join)
];
diff -rupN DBIx-Class-0.082820/lib/DBIx/Class/SQLMaker.pm DBIx-Class-0.082820.new/lib/DBIx/Class/SQLMaker.pm
--- DBIx-Class-0.082820/lib/DBIx/Class/SQLMaker.pm 2015-03-20 07:54:07.000000000 -0400
+++ DBIx-Class-0.082820.new/lib/DBIx/Class/SQLMaker.pm 2015-05-05 17:38:39.899603508 -0400
@@ -402,6 +402,9 @@ sub _gen_from_blocks {
if (ref $to eq 'ARRAY') {
push(@j, '(', $self->_recurse_from(@$to), ')');
}
+ elsif (ref $to eq 'HASH' and $to->{-join}){
+ push(@j, '(', $self->_recurse_from($to, @{$to->{-join}}), ')');
+ }
else {
push(@j, $self->_from_chunk_to_sql($to));
}
Это позволяет использовать простой атрибут отношения к группе присоединяется.
package Test::Schema::Result::A;
...
__PACKAGE__->has_many(
"D" => "Test::Schema::Result::D",
{ "foreign.a_id" => "self.id" },
{ join => 'E' },
);
package Test::Schema::Result::D;
...
__PACKAGE__->has_many(
"E", "Test::Schema::Result::E",
{ "foreign.d_id" => "self.id" },
);
Кажется, что он работает с более сложными соединениями (hash и arrayrefs), но он не был тщательно протестирован. Все, что я могу сказать, это то, что он работает для моего случая, и он не нарушает текущий набор тестов.
Я все еще просматриваю источник DBIC, но похоже, что он поддерживает их в функции DBIx :: Class :: SQLMaker '_gen_from_blocks'. К сожалению, я думаю, что он вызван из SQL :: Abstract из DBIx :: Class (:: ResultSource?), Поэтому трудно определить, какие конкретные условия требуются. –
Если вы используете критерии в предложении where, можете ли вы исключить конкретные строки, которые вы не хотите, если используете LEFT JOIN для E? – kbenson
@kbenson При использовании 'LEFT JOIN' он вернет только первое, что находит в E, которое не всегда включает нужные строки, поэтому предложение WHERE даже не увидит их. Это по крайней мере тот случай, если E.c_id может быть «NULL»; мой конкретный случай не 1-к-1. –