Commit | Line | Data |
01d7143b |
1 | package Data::Query::Renderer::SQL::Slice::GenericSubquery; |
2 | |
3 | use Data::Query::ExprHelpers; |
4 | use Moo::Role; |
5 | |
6 | with 'Data::Query::Renderer::SQL::Slice::SubqueryRemap'; |
7 | |
fbf38b8e |
8 | sub slice_subquery { |
9 | (limit => 1, offset => 1); |
10 | } |
11 | |
8b2c306b |
12 | sub slice_stability { |
13 | (limit => 'requires', offset => 'requires'); |
14 | } |
15 | |
01d7143b |
16 | sub _render_slice { |
17 | my ($self, $dq) = @_; |
18 | die "Slice's inner is not a Select" |
19 | unless is_Select my $orig_select = $dq->{from}; |
20 | my %remapped = $self->_subquery_remap($orig_select); |
21 | my $first_from = $remapped{inner_body}; |
5a058623 |
22 | # Should we simply strip until we reach a join/alias/etc. here? |
23 | $first_from = $first_from->{from}{from} if is_Having($first_from); |
01d7143b |
24 | $first_from = $first_from->{from} if is_Where($first_from); |
25 | while (is_Join $first_from) { |
26 | $first_from = $first_from->{left}; |
27 | } |
28 | $first_from = $first_from->{from} if is_Alias($first_from); |
29 | my $first_order = $remapped{inside_order}[0]{by}; |
30 | my $count_col = $first_order->{elements}[-1]; |
31 | my $count_alias = 'rownum__emulation'; |
32 | my $count_sel = Select( |
33 | [ Operator({ 'SQL.Naive' => 'apply' }, [ Identifier('COUNT'), Identifier('*') ]) ], |
34 | Where( |
35 | Operator( |
e31249d4 |
36 | { 'SQL.Naive' => ($remapped{inside_order}[0]{reverse} ? '>' : '<') }, |
37 | [ |
38 | Identifier($count_alias, $count_col), |
39 | $remapped{outside_order}[0]{by} |
40 | ] |
01d7143b |
41 | ), |
42 | Alias($count_alias, $first_from) |
43 | ) |
44 | ); |
45 | my $count_where = Operator( |
46 | { 'SQL.Naive' => ($dq->{offset} ? 'BETWEEN' : '<') }, |
47 | [ $count_sel, ( |
48 | $dq->{offset} |
49 | ? ( |
50 | $dq->{offset}, |
51 | { |
52 | %{$dq->{limit}}, |
53 | value => $dq->{limit}{value}+$dq->{offset}{value}-1 |
54 | } |
55 | ) |
56 | : ($dq->{limit}) |
57 | ) |
58 | ] |
59 | ); |
60 | return $self->render( |
61 | Select( |
62 | $remapped{outside_select_list}, |
e3335558 |
63 | (compose { no warnings 'once'; Order($b->{by}, $b->{reverse}, $b->{nulls}, $a) } |
01d7143b |
64 | @{$remapped{outside_order}}, |
65 | Where( |
66 | $count_where, |
67 | Alias( |
68 | $remapped{default_inside_alias}, |
69 | Select( |
70 | $remapped{inside_select_list}, |
71 | $remapped{inner_body}, |
72 | ) |
73 | ) |
74 | ) |
75 | ) |
76 | ) |
77 | ); |
78 | } |
79 | |
80 | 1; |