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