1 package DBIx::Class::SQLMaker::Renderer::OracleJoins;
3 sub map_descending (&;@) {
6 $_ = $block->($_) if ref($_) eq 'HASH';
7 if (ref($_) eq 'REF' and ref($$_) eq 'HASH') {
9 } elsif (ref($_) eq 'HASH') {
12 +{ map +($_ => &map_descending($block, $mapped->{$_})), keys %$mapped };
13 } elsif (ref($_) eq 'ARRAY') {
14 [ map &map_descending($block, $_), @$_ ]
20 use Data::Query::ExprHelpers;
24 extends 'Data::Query::Renderer::SQL::Naive';
26 around render => sub {
27 my ($orig, $self) = (shift, shift);
28 $self->$orig($self->_oracle_joins_unroll(@_));
31 sub _oracle_joins_unroll {
34 return $_ unless is_Join;
35 return \$self->_oracle_joins_mangle_join($_);
39 sub _oracle_joins_mangle_join {
41 my ($mangled, $where) = $self->_oracle_joins_recurse_join($dq);
44 ? Operator({ 'SQL.Naive' => 'AND' }, $where)
50 sub _oracle_joins_recurse_join {
52 die "Can't handle cross join" unless $dq->{on};
53 my $mangled = { %$dq };
54 delete @{$mangled}{qw(on outer)};
57 foreach my $side (qw(left right)) {
58 if (is_Join $dq->{$side}) {
59 ($mangled->{$side}, my ($side_where, $side_idents))
60 = $self->_oracle_joins_recurse_join($dq->{$side});
61 push @where, $side_where;
62 $idents{$side} = $side_idents;
64 if (is_Identifier($dq->{$side})) {
65 $idents{$side} = { join($;, @{$dq->{$side}{elements}}) => 1 };
66 } elsif (is_Alias($dq->{$side})) {
67 $idents{$side} = { $dq->{$side}{to} => 1 };
69 $mangled->{$side} = $self->_oracle_joins_unroll($dq->{$side});
72 my %other = (left => 'right', right => 'left');
77 if is_Operator and ($_->{operator}{'SQL.Naive'}||'') eq '(+)';
78 return $_ unless is_Identifier;
79 die "Can't unroll single part identifiers in on"
80 unless @{$_->{elements}} > 1;
81 my $check = join($;, @{$_->{elements}}[0..($#{$_->{elements}}-1)]);
82 if ($idents{$other{$dq->{outer}}}{$check}) {
83 return \Operator({ 'SQL.Naive' => '(+)' }, [ $_ ]);
89 return ($mangled, \@where, { map %{$_||{}}, @idents{qw(left right)} });
92 around _default_simple_ops => sub {
93 my ($orig, $self) = (shift, shift);
96 '(+)' => 'unop_reverse',