25a4929c433a245158302902fa0ce35decfbe25a
[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 sub _insert_default_values {
12   my ($self) = @_;
13   $self->_format_keyword('VALUES'), qw( ( ) );
14 }
15
16 foreach my $type (qw(update delete)) {
17   around "_render_${type}" => sub {
18     my ($orig, $self) = (shift, shift);
19     $self->$orig($self->_maybe_double_subquery(@_));
20   };
21 }
22
23 sub _maybe_double_subquery {
24   my ($self, $dq) = @_;
25   my $target = $dq->{target};
26   my $new = { %$dq };
27   foreach my $key (qw(set where)) {
28     next unless $dq->{$key};
29     $new->{$key} = map_dq_tree {
30       if (is_Select) {
31         my $found;
32         scan_dq_nodes(do {
33           if (is_Identifier($target)) {
34             my $ident = $target->{elements}[0];
35             +{ DQ_IDENTIFIER ,=> sub {
36                  my @el = @{$_[0]->{elements}};
37                  $found = 1 if @el == 1 and $el[0] eq $ident;
38                }
39             };
40           } elsif (is_Literal($target)) {
41             my $ident = $target->{literal} or die "Can't handle complex literal";
42             +{ DQ_LITERAL ,=> sub {
43                  my $lit = $_[0]->{literal};
44                  $found = 1 if $lit and $lit eq $ident;
45                }
46             };
47           } else {
48             die "Can't handle target type ".$target->{type};
49           }
50         }, $_);
51         if ($found) {
52           \Select([ Identifier('*') ], Alias('_forced_double_subquery', $_));
53         } else {
54           $_
55         }
56       } else {
57         $_
58       }
59     } $dq->{$key};
60   }
61   $new;
62 }
63
64 1;