add double subquery handling to MySQL code
[dbsrgits/Data-Query.git] / lib / Data / Query / Renderer / SQL / MySQL.pm
CommitLineData
7d0fb8c0 1package Data::Query::Renderer::SQL::MySQL;
2
944c72bc 3sub map_descending (&;@) {
4 my ($block, $in) = @_;
5 local $_ = $in;
6 $_ = $block->($_) if ref($_) eq 'HASH';
7 if (ref($_) eq 'REF' and ref($$_) eq 'HASH') {
8 $$_;
9 } elsif (ref($_) eq 'HASH') {
10 my $mapped = $_;
11 local $_;
12 +{ map +($_ => &map_descending($block, $mapped->{$_})), keys %$mapped };
13 } elsif (ref($_) eq 'ARRAY') {
14 [ map &map_descending($block, $_), @$_ ]
15 } else {
16 $_
17 }
18}
19
20use Data::Query::Constants;
21use Data::Query::ExprHelpers;
7d0fb8c0 22use Moo;
23
24extends 'Data::Query::Renderer::SQL::Naive';
25
26with 'Data::Query::Renderer::SQL::Slice::LimitXY';
27
28sub _insert_default_values {
29 my ($self) = @_;
30 $self->_format_keyword('VALUES'), qw( ( ) );
31}
32
944c72bc 33foreach my $type (qw(update delete)) {
34 around "_render_${type}" => sub {
35 my ($orig, $self) = (shift, shift);
36 $self->$orig($self->_maybe_double_subquery(@_));
37 };
38}
39
40sub _maybe_double_subquery {
41 my ($self, $dq) = @_;
42 my $target = $dq->{target};
43 my $new = { %$dq };
44 foreach my $key (qw(set where)) {
45 next unless $dq->{$key};
46 $new->{$key} = map_descending {
47 if (is_Select) {
48 my $found;
49 scan_dq_nodes(do {
50 if (is_Identifier($target)) {
51 my $ident = $target->{elements}[0];
52 +{ DQ_IDENTIFIER ,=> sub {
53 my @el = @{$_[0]->{elements}};
54 $found = 1 if @el == 1 and $el[0] eq $ident;
55 }
56 };
57 } elsif (is_Literal($target)) {
58 my $ident = $target->{literal} or die "Can't handle complex literal";
59 +{ DQ_LITERAL ,=> sub {
60 my $lit = $_[0]->{literal};
61 $found = 1 if $lit and $lit eq $ident;
62 }
63 };
64 } else {
65 die "Can't handle target type ".$target->{type};
66 }
67 }, $_);
68 if ($found) {
69 \Select([ Identifier('*') ], Alias('_forced_double_subquery', $_));
70 } else {
71 $_
72 }
73 } else {
74 $_
75 }
76 } $dq->{$key};
77 }
78 $new;
79}
80
7d0fb8c0 811;