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}) { |
6b9e9259 |
54 | +( |
55 | join('.',@{$_->{from}{elements}}) => Identifier($_->{to}), |
56 | $_->{from}{elements}[-1] => Identifier($_->{to}), |
57 | ) |
fdd10824 |
58 | } elsif (is_Identifier) { |
6b9e9259 |
59 | +( |
60 | join('.',@{$_->{elements}}) => $_, |
61 | $_->{elements}[-1] => $_, |
62 | ) |
fdd10824 |
63 | } else { |
64 | +() |
65 | } |
66 | } @inside_select_list; |
67 | |
fdd10824 |
68 | my @inside_order; |
69 | my $inner_body = do { |
70 | my $order = $orig_select->{from}; |
71 | while (is_Order $order) { |
72 | push @inside_order, $order; |
73 | $order = $order->{from}; |
74 | } |
75 | $order; |
76 | }; |
77 | |
78 | my $order_gensym_count; |
79 | my @outside_order = map { |
80 | my $by = $_->{by}; |
81 | if (is_Identifier $by) { |
82 | $default_inside_alias ||= $by->{elements}[0] |
83 | if @{$by->{elements}} == 2; |
84 | my $mapped_by |
85 | = $alias_map{join('.', @{$by->{elements}})} |
86 | ||= do { |
87 | if ( |
88 | @{$by->{elements}} == 2 |
89 | and $by->{elements}[0] eq $default_inside_alias |
90 | ) { |
91 | push @inside_select_list, $by; |
92 | $by; |
93 | } else { |
94 | my $name = sprintf("ORDER__BY__%03i",++$order_gensym_count); |
95 | push @inside_select_list, Alias($name, $by); |
96 | Identifier($name); |
97 | } |
98 | }; |
f5ba44a5 |
99 | Order($mapped_by, $_->{reverse}, $_->{nulls}); |
fdd10824 |
100 | } else { |
ce86e12a |
101 | my $name = sprintf("ORDER__BY__%03i",++$order_gensym_count); |
102 | push @inside_select_list, Alias($name, $by); |
f5ba44a5 |
103 | Order(Identifier($name), $_->{reverse}, $_->{nulls}); |
fdd10824 |
104 | } |
105 | } @inside_order; |
106 | |
107 | $default_inside_alias ||= 'me'; |
108 | |
109 | return ( |
110 | inside_select_list => \@inside_select_list, |
111 | outside_select_list => \@outside_select_list, |
112 | inside_order => \@inside_order, |
113 | outside_order => \@outside_order, |
114 | default_inside_alias => $default_inside_alias, |
115 | inner_body => $inner_body, |
116 | ); |
117 | } |
118 | |
119 | 1; |