Fix trailing whitespace
[dbsrgits/Data-Query.git] / lib / Data / Query / Renderer / SQL / MySQL.pm
1 package Data::Query::Renderer::SQL::MySQL;
2
3 use Data::Query::Constants;
4 use Data::Query::ExprHelpers;
5 use Moo;
6
7 extends 'Data::Query::Renderer::SQL::Naive';
8
9 with 'Data::Query::Renderer::SQL::Slice::LimitXY';
10
11 has needs_inner_join => (is => 'ro', default => sub { 0 });
12
13 around _format_join_keyword => sub {
14   my ($orig, $self) = (shift, shift);
15   my ($dq) = @_;
16   if ($dq->{'Data::Query::Renderer::SQL::MySQL.straight_join'}) {
17     return $self->_format_keyword('STRAIGHT_JOIN');
18   } elsif ($self->needs_inner_join and $dq->{on} and !$dq->{outer}) {
19     return $self->_format_keyword('INNER JOIN');
20   }
21   return $self->$orig(@_);
22 };
23
24 sub _insert_default_values {
25   my ($self) = @_;
26   $self->_format_keyword('VALUES'), qw( ( ) );
27 }
28
29 foreach my $type (qw(update delete)) {
30   around "_render_${type}" => sub {
31     my ($orig, $self) = (shift, shift);
32     $self->$orig($self->_maybe_double_subquery(@_));
33   };
34 }
35
36 sub _maybe_double_subquery {
37   my ($self, $dq) = @_;
38   my $target = $dq->{target};
39   my $new = { %$dq };
40   foreach my $key (qw(set where)) {
41     next unless $dq->{$key};
42     $new->{$key} = map_dq_tree {
43       if (is_Select) {
44         my $found;
45         scan_dq_nodes(do {
46           if (is_Identifier($target)) {
47             my $ident = $target->{elements}[0];
48             +{ DQ_IDENTIFIER ,=> sub {
49                  my @el = @{$_[0]->{elements}};
50                  $found = 1 if @el == 1 and $el[0] eq $ident;
51                }
52             };
53           } elsif (is_Literal($target)) {
54             my $ident = $target->{literal} or die "Can't handle complex literal";
55             +{ DQ_LITERAL ,=> sub {
56                  my $lit = $_[0]->{literal};
57                  $found = 1 if $lit and $lit eq $ident;
58                }
59             };
60           } else {
61             die "Can't handle target type ".$target->{type};
62           }
63         }, $_);
64         if ($found) {
65           \Select([ Identifier('*') ], Alias('_forced_double_subquery', $_));
66         } else {
67           $_
68         }
69       } else {
70         $_
71       }
72     } $dq->{$key};
73   }
74   $new;
75 }
76
77 1;