Commit | Line | Data |
fdd10824 |
1 | package Data::Query::Renderer::SQL::Slice::SubqueryRemap; |
2 | |
3 | use Data::Query::ExprHelpers; |
4 | use Moo::Role; |
5 | |
af2d4155 |
6 | sub _subquery_remap_select { |
fdd10824 |
7 | my ($self, $orig_select) = @_; |
8 | |
9 | my $gensym_count; |
10 | my $default_inside_alias; |
11 | |
12 | my @inside_select_list = map { |
13 | if (is_Alias) { |
14 | $_; |
15 | } elsif (is_Identifier) { |
16 | my @el = @{$_->{elements}}; |
17 | if (@el == 2 and $el[0] eq ($default_inside_alias ||= $el[0])) { |
18 | $_; |
19 | } else { |
20 | Alias(join('__', @el), $_); |
21 | } |
22 | } else { |
23 | Alias(sprintf("GENSYM__%03i",++$gensym_count), $_); |
24 | } |
25 | } @{$orig_select->{select}}; |
26 | |
af2d4155 |
27 | my @outside_select_list = map { |
28 | if (is_Alias) { |
29 | Identifier($_->{to}); |
30 | } else { |
31 | $_; |
32 | } |
33 | } @inside_select_list; |
34 | |
35 | return ( |
36 | inside_select_list => \@inside_select_list, |
37 | outside_select_list => \@outside_select_list, |
38 | default_inside_alias => $default_inside_alias, |
39 | ); |
40 | } |
41 | |
42 | sub _subquery_remap { |
43 | my ($self, $orig_select) = @_; |
44 | |
45 | my $gensym_count; |
46 | my %select_remap = $self->_subquery_remap_select($orig_select); |
47 | |
48 | my $default_inside_alias = $select_remap{default_inside_alias}; |
49 | my @inside_select_list = @{$select_remap{inside_select_list}}; |
50 | my @outside_select_list = @{$select_remap{outside_select_list}}; |
51 | |
fdd10824 |
52 | my %alias_map = map { |
53 | if (is_Alias and is_Identifier $_->{from}) { |
54 | +(join('.',@{$_->{from}{elements}}) => Identifier($_->{to})) |
55 | } elsif (is_Identifier) { |
56 | +(join('.',@{$_->{elements}}) => $_) |
57 | } else { |
58 | +() |
59 | } |
60 | } @inside_select_list; |
61 | |
fdd10824 |
62 | my @inside_order; |
63 | my $inner_body = do { |
64 | my $order = $orig_select->{from}; |
65 | while (is_Order $order) { |
66 | push @inside_order, $order; |
67 | $order = $order->{from}; |
68 | } |
69 | $order; |
70 | }; |
71 | |
72 | my $order_gensym_count; |
73 | my @outside_order = map { |
74 | my $by = $_->{by}; |
75 | if (is_Identifier $by) { |
76 | $default_inside_alias ||= $by->{elements}[0] |
77 | if @{$by->{elements}} == 2; |
78 | my $mapped_by |
79 | = $alias_map{join('.', @{$by->{elements}})} |
80 | ||= do { |
81 | if ( |
82 | @{$by->{elements}} == 2 |
83 | and $by->{elements}[0] eq $default_inside_alias |
84 | ) { |
85 | push @inside_select_list, $by; |
86 | $by; |
87 | } else { |
88 | my $name = sprintf("ORDER__BY__%03i",++$order_gensym_count); |
89 | push @inside_select_list, Alias($name, $by); |
90 | Identifier($name); |
91 | } |
92 | }; |
93 | Order($mapped_by, $_->{reverse}); |
94 | } else { |
ce86e12a |
95 | my $name = sprintf("ORDER__BY__%03i",++$order_gensym_count); |
96 | push @inside_select_list, Alias($name, $by); |
97 | Order(Identifier($name), $_->{reverse}); |
fdd10824 |
98 | } |
99 | } @inside_order; |
100 | |
101 | $default_inside_alias ||= 'me'; |
102 | |
103 | return ( |
104 | inside_select_list => \@inside_select_list, |
105 | outside_select_list => \@outside_select_list, |
106 | inside_order => \@inside_order, |
107 | outside_order => \@outside_order, |
108 | default_inside_alias => $default_inside_alias, |
109 | inner_body => $inner_body, |
110 | ); |
111 | } |
112 | |
113 | 1; |