2015-05-01 4 views
2

Учитывая следующие таблицы, каждая из которых с простыми внешними ключами:Как сделать круглые скобки присоединяется DBIx :: Класс

B - C 
    // | 
A  | 
    \\ | 
    D - E 

A to B/D = has many; B to C and D to E = has one; C to E = might have? 

мне нужно, чтобы захватить все строки из A, B и C, а также соответствующие строки из D и Е, когда Е имеет ряд связанных как D и C. единственный способ, которым я могу думать, чтобы сделать это, чтобы присоединиться к D и Е в скобках, как показано ниже:

SELECT * 
FROM A 
    JOIN B ON (B.a_id = A.id) 
    JOIN C ON (C.b_id = B.id) 
    LEFT JOIN (D JOIN E ON (E.d_id = D.id AND E.c_id = C.id)) ON (D.a_id = A.id); 

Без скобок, это 'только возвращают строки B/C, которые имеют D/E. Если я изменю E на LEFT JOIN, он захватит первую строку в D с хорошей или без хорошей строки в E, даже если есть допустимые строки D/E для захвата. Возможно ли это с использованием DBIx :: Class/SQL :: Abstract или есть лучший способ сделать это?

+0

Я все еще просматриваю источник DBIC, но похоже, что он поддерживает их в функции DBIx :: Class :: SQLMaker '_gen_from_blocks'. К сожалению, я думаю, что он вызван из SQL :: Abstract из DBIx :: Class (:: ResultSource?), Поэтому трудно определить, какие конкретные условия требуются. –

+0

Если вы используете критерии в предложении where, можете ли вы исключить конкретные строки, которые вы не хотите, если используете LEFT JOIN для E? – kbenson

+0

@kbenson При использовании 'LEFT JOIN' он вернет только первое, что находит в E, которое не всегда включает нужные строки, поэтому предложение WHERE даже не увидит их. Это по крайней мере тот случай, если E.c_id может быть «NULL»; мой конкретный случай не 1-к-1. –

ответ

0

я не мог найти правильный способ сделать это, но я был в состоянии жюри установки патча:

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), но он не был тщательно протестирован. Все, что я могу сказать, это то, что он работает для моего случая, и он не нарушает текущий набор тестов.

 Смежные вопросы

  • Нет связанных вопросов^_^