my %remapped = $self->_subquery_remap($orig_select);
my $first_from = $remapped{inner_body};
# Should we simply strip until we reach a join/alias/etc. here?
- $first_from = $first_from->{from}{from} if is_Having($first_from);
- $first_from = $first_from->{from} if is_Where($first_from);
- while (is_Join $first_from) {
- $first_from = $first_from->{left};
+ STRIP: while ($first_from) {
+ if (is_Group($first_from)) {
+ $first_from = $first_from->{from};
+ next STRIP;
+ } elsif (is_Where($first_from)) {
+ $first_from = $first_from->{from};
+ next STRIP;
+ } elsif (is_Join($first_from)) {
+ $first_from = $first_from->{left};
+ next STRIP;
+ }
+ last STRIP;
}
+ die "WHAT" unless $first_from;
$first_from = $first_from->{from} if is_Alias($first_from);
- my $first_order = $remapped{inside_order}[0]{by};
- my $count_col = $first_order->{elements}[-1];
+ my @main_order;
+ foreach my $i (0..$#{$remapped{inside_order}}) {
+ my $order = $remapped{inside_order}[$i];
+ my $outside = $remapped{outside_order}[$i];
+ if (is_Identifier($order->{by})
+ and (
+ (@{$order->{by}{elements}} == 2
+ and $order->{by}{elements}[0] eq $remapped{default_inside_alias})
+ or (@{$order->{by}{elements}} == 1))
+ ) {
+ push @main_order, [
+ $outside->{by}, $order->{by}{elements}[-1], $order->{reverse}
+ ];
+ } else {
+ last;
+ }
+ }
+
my $count_alias = 'rownum__emulation';
+ my ($op_and, $op_or) = map +{ 'SQL.Naive' => $_ }, qw(AND OR);
+ my $count_cond = compose {
+ my $lhs = $b->[0];
+ my $rhs = Identifier($count_alias, $b->[1]);
+ ($lhs, $rhs) = ($rhs, $lhs) if $b->[2];
+ my $this = Operator($op_or, [
+ Operator($op_and, [
+ Operator({ 'SQL.Naive' => 'IS NOT NULL' }, [ $lhs ]),
+ Operator({ 'SQL.Naive' => 'IS NULL' }, [ $rhs ]),
+ ]),
+ Operator({ 'SQL.Naive' => '>' }, [ $lhs, $rhs ]),
+ ]);
+ ($a
+ ? Operator($op_or, [
+ $this,
+ Operator($op_and, [
+ Operator($op_or, [
+ Operator($op_and, [
+ map Operator({ 'SQL.Naive' => 'IS NULL' }, [ $_ ]), $lhs, $rhs
+ ]),
+ Operator({ 'SQL.Naive' => '=' }, [ $lhs, $rhs ])
+ ]),
+ $a
+ ])
+ ])
+ : $this)
+ } @main_order, undef;
my $count_sel = Select(
[ Operator({ 'SQL.Naive' => 'apply' }, [ Identifier('COUNT'), Identifier('*') ]) ],
Where(
- Operator(
- { 'SQL.Naive' => ($remapped{inside_order}[0]{reverse} ? '>' : '<') },
- [
- Identifier($count_alias, $count_col),
- $remapped{outside_order}[0]{by}
- ]
- ),
+ $count_cond,
Alias($count_alias, $first_from)
)
);