Commit | Line | Data |
98994ccc |
1 | package Data::Query::Renderer::SQL::Slice::RowNum; |
2 | |
3 | use Data::Query::ExprHelpers; |
4 | use Moo::Role; |
5 | |
6 | with 'Data::Query::Renderer::SQL::Slice::SubqueryRemap'; |
7 | |
8b2c306b |
8 | sub slice_stability { |
9 | (offset => 'check'); |
10 | } |
11 | |
98994ccc |
12 | sub _render_slice { |
13 | my ($self, $dq) = @_; |
14 | die "Slice's inner is not a Select" |
15 | unless is_Select my $orig_select = $dq->{from}; |
16 | my %remapped = $self->_subquery_remap_select($orig_select); |
17 | my $inside_select = Alias( |
18 | $remapped{default_inside_alias}, |
19 | Select($remapped{inside_select_list}, $orig_select->{from}), |
20 | ); |
21 | unless ($dq->{offset}) { |
22 | return $self->render( |
23 | Select( |
24 | $remapped{outside_select_list}, |
25 | Where( |
26 | Operator( |
27 | { 'SQL.Naive' => '<=' }, |
28 | [ |
29 | Literal(SQL => 'ROWNUM'), |
30 | $dq->{limit} |
31 | ] |
32 | ), |
33 | $inside_select |
34 | ) |
35 | ) |
36 | ); |
37 | } |
38 | my ($limit_plus_offset, $offset_plus) = ( |
39 | { %{$dq->{limit}}, value => $dq->{limit}{value}+$dq->{offset}{value} }, |
40 | { %{$dq->{limit}}, value => $dq->{offset}{value}+1 } |
41 | ); |
42 | |
43 | my $rownum_name = 'rownum__index'; |
44 | |
45 | if ($dq->{order_is_stable}) { |
46 | return $self->render( |
47 | Select( |
48 | $remapped{outside_select_list}, |
49 | Where( |
50 | Operator( |
51 | { 'SQL.Naive' => '>=' }, |
29b2dace |
52 | [ Identifier($rownum_name), $offset_plus ] |
98994ccc |
53 | ), |
54 | Alias( |
55 | $remapped{default_inside_alias}, |
56 | Select( |
57 | [ @{$remapped{outside_select_list}}, |
58 | Alias($rownum_name, Literal(SQL => 'ROWNUM')) ], |
59 | Where( |
60 | Operator( |
61 | { 'SQL.Naive' => '<=' }, |
29b2dace |
62 | [ Literal(SQL => 'ROWNUM'), $limit_plus_offset ] |
98994ccc |
63 | ), |
64 | $inside_select, |
65 | ) |
66 | ) |
67 | ) |
68 | ) |
69 | ) |
70 | ); |
71 | } else { |
72 | return $self->render( |
73 | Select( |
74 | $remapped{outside_select_list}, |
75 | Where( |
76 | Operator( |
77 | { 'SQL.Naive' => 'BETWEEN' }, |
29b2dace |
78 | [ Identifier($rownum_name), $offset_plus, $limit_plus_offset ] |
98994ccc |
79 | ), |
80 | Alias( |
81 | $remapped{default_inside_alias}, |
82 | Select( |
83 | [ @{$remapped{outside_select_list}}, |
84 | Alias($rownum_name, Literal(SQL => 'ROWNUM')) ], |
85 | $inside_select |
86 | ) |
87 | ) |
88 | ) |
89 | ) |
90 | ); |
91 | } |
92 | } |
93 | |
94 | 1; |