minor helper tweaks
[dbsrgits/Data-Query.git] / lib / Data / Query / Renderer / SQL / Slice / RowNumberOver.pm
CommitLineData
77585983 1package Data::Query::Renderer::SQL::Slice::RowNumberOver;
2
fdd10824 3use Data::Query::Constants;
4use Data::Query::ExprHelpers;
77585983 5use Moo::Role;
6
fdd10824 7with 'Data::Query::Renderer::SQL::Slice::SubqueryRemap';
8
77585983 9sub _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
73sub _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
881;