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