Commit | Line | Data |
77585983 |
1 | package Data::Query::Renderer::SQL::Slice::RowNumberOver; |
2 | |
fdd10824 |
3 | use Data::Query::Constants; |
4 | use Data::Query::ExprHelpers; |
77585983 |
5 | use Moo::Role; |
6 | |
fdd10824 |
7 | with 'Data::Query::Renderer::SQL::Slice::SubqueryRemap'; |
8 | |
fbf38b8e |
9 | sub slice_subquery { |
10 | (limit => 1, offset => 1); |
11 | } |
12 | |
8b2c306b |
13 | sub slice_stability { } |
14 | |
77585983 |
15 | sub _render_slice { |
16 | my ($self, $dq) = @_; |
17 | die "Slice's inner is not a Select" |
18 | unless (my $orig_select = $dq->{from})->{type} eq DQ_SELECT; |
fdd10824 |
19 | |
20 | my %remapped = $self->_subquery_remap($orig_select); |
21 | |
22 | my @inside_select_list = @{$remapped{inside_select_list}}; |
23 | my @outside_select_list = @{$remapped{outside_select_list}}; |
24 | my @inside_order = @{$remapped{inside_order}}; |
25 | my @outside_order = @{$remapped{outside_order}}; |
26 | my $default_inside_alias = $remapped{default_inside_alias}; |
27 | my $inner_body = $remapped{inner_body}; |
28 | |
29 | my $rno_name = 'rno__row__index'; |
30 | |
e3335558 |
31 | my $order = compose { Order($b->{by}, $b->{reverse}, $b->{nulls}, $a) } |
fdd10824 |
32 | @outside_order, undef; |
33 | |
34 | my $rno_node = Alias($rno_name, $self->_rno_literal($order)); |
35 | |
36 | my $limit_plus_offset = +{ |
37 | %{$dq->{limit}}, value => ($dq->{limit}{value}||0) + ($dq->{offset}{value}||0) |
77585983 |
38 | }; |
fdd10824 |
39 | |
40 | my $offset_plus = +{ |
41 | %{$dq->{limit}}, value => ($dq->{offset}{value}||0)+1 |
77585983 |
42 | }; |
fdd10824 |
43 | |
44 | return $self->_render( |
45 | Select( |
46 | \@outside_select_list, |
47 | Where( |
48 | Operator( |
49 | { 'SQL.Naive' => 'AND' }, |
50 | [ |
51 | Operator( |
52 | { 'SQL.Naive' => '>=' }, |
53 | [ Identifier($rno_name), $offset_plus ], |
54 | ), |
55 | Operator( |
56 | { 'SQL.Naive' => '<=' }, |
57 | [ Identifier($rno_name), $limit_plus_offset ], |
58 | ), |
77585983 |
59 | ] |
fdd10824 |
60 | ), |
61 | Alias( |
62 | $default_inside_alias, |
63 | Select( |
64 | [ @outside_select_list, $rno_node ], |
65 | Alias( |
66 | $default_inside_alias, |
67 | Select( |
68 | \@inside_select_list, |
69 | $inner_body |
70 | ), |
71 | ), |
72 | ), |
73 | ) |
74 | ) |
75 | ) |
76 | ); |
77585983 |
77 | } |
78 | |
79 | sub _rno_literal { |
80 | my ($self, $order) = @_; |
81 | my ($order_str, @order_bind) = ( |
82 | $order |
3d84f4a9 |
83 | ? @{$self->render($order)} |
77585983 |
84 | : ('') |
85 | ); |
86 | return +{ |
87 | type => DQ_LITERAL, |
88 | subtype => 'SQL', |
89 | literal => "ROW_NUMBER() OVER( $order_str )", |
90 | values => \@order_bind |
91 | }; |
92 | } |
93 | |
94 | 1; |