}
die "Slice's inner is not a Select"
unless is_Select my $orig_select = $dq->{from};
- my %alias_map;
+ die "Slice's Select not followed by Order but order_is_stable set"
+ unless is_Order $orig_select->{from};
+
my $gensym_count;
- my (@inside_select_list, @outside_select_list);
my $default_inside_alias;
- SELECT: foreach my $s (@{$orig_select->{select}}) {
- my $name;
- if (is_Alias $s) {
- $name = $s->{to};
- $s = $s->{from};
- }
- my $key;
- if (is_Identifier $s) {
- if (!$name and @{$s->{elements}} == 2) {
- $default_inside_alias ||= $s->{elements}[0];
- if ($s->{elements}[0] eq $default_inside_alias) {
- $alias_map{join('.',@{$s->{elements}})} = $s;
- push @inside_select_list, $s;
- push @outside_select_list, $s;
- next SELECT;
- }
+
+ my @inside_select_list = map {
+ if (is_Alias) {
+ $_;
+ } elsif (is_Identifier) {
+ my @el = @{$_->{elements}};
+ if (@el == 2 and $el[0] eq ($default_inside_alias ||= $el[0])) {
+ $_;
+ } else {
+ Alias(join('__', @el), $_);
}
- $name ||= join('__', @{$s->{elements}});
- $key = join('.', @{$s->{elements}});
} else {
- die "XXX not implemented yet" unless $name;
- $key = "$s";
+ Alias(sprintf("GENSYM__%03i",++$gensym_count), $_);
}
- $name ||= sprintf("GENSYM__%03i",++$gensym_count);
- push @inside_select_list, Alias($name, $s);
- push @outside_select_list, $alias_map{$key} = Identifier($name);
- }
- my $order = $orig_select->{from};
+ } @{$orig_select->{select}};
+
+ my %alias_map = map {
+ if (is_Alias and is_Identifier $_->{from}) {
+ +(join('.',@{$_->{from}{elements}}) => Identifier($_->{to}))
+ } elsif (is_Identifier) {
+ +(join('.',@{$_->{elements}}) => $_)
+ } else {
+ +()
+ }
+ } @inside_select_list;
+
+ my @outside_select_list = map {
+ if (is_Alias) {
+ Identifier($_->{to});
+ } else {
+ $_;
+ }
+ } @inside_select_list;
+
+ my @order_nodes;
+ my $inner_body = do {
+ my $order = $orig_select->{from};
+ while (is_Order $order) {
+ push @order_nodes, $order;
+ $order = $order->{from};
+ }
+ $order;
+ };
+
my $order_gensym_count;
- die "Slice's Select not followed by Order but order_is_stable set"
- unless is_Order $order;
- my (@order_nodes, %order_map);
- while (is_Order $order) {
- my $by = $order->{by};
+ my @mapped_order = map {
+ my $by = $_->{by};
if (is_Identifier $by) {
$default_inside_alias ||= $by->{elements}[0]
if @{$by->{elements}} == 2;
- $order_map{$by}
+ my $mapped_by
= $alias_map{join('.', @{$by->{elements}})}
||= do {
if (
Identifier($name);
}
};
+ Order($mapped_by, $_->{reverse});
} else {
die "XXX not implemented yet";
}
- push @order_nodes, $order;
- $order = $order->{from};
- }
+ } @order_nodes;
+
$default_inside_alias ||= 'me';
+
my $limit_plus_offset = +{
%{$dq->{limit}}, value => $dq->{limit}{value} + $dq->{offset}{value}
};
- my $inner_body = $order;
+
return $self->_render(
map {
$dq->{preserve_order}
? Select(
\@outside_select_list,
compose {
- Order($order_map{$b->{by}}, $b->{reverse}, $a)
- } @order_nodes, Alias($default_inside_alias, $_)
+ Order($b->{by}, $b->{reverse}, $a)
+ } (
+ @mapped_order,
+ Alias($default_inside_alias, $_)
+ )
)
: $_
- } Slice(
+ } (
+ Slice(
undef, $dq->{limit},
Select(
[
@outside_select_list,
$dq->{preserve_order}
? (grep @{$_->{elements}} == 1,
- @order_map{map $_->{by}, @order_nodes})
+ map $_->{by}, @mapped_order)
: (),
],
compose {
- Order($order_map{$b->{by}}, !$b->{reverse}, $a)
+ Order($b->{by}, !$b->{reverse}, $a)
} (
- @order_nodes,
+ @mapped_order,
Alias(
$default_inside_alias,
Slice(
)
)
)
+ )
);
}