add slice stability requirement code
[dbsrgits/Data-Query.git] / lib / Data / Query / Renderer / SQL / Slice / RowNum.pm
CommitLineData
98994ccc 1package Data::Query::Renderer::SQL::Slice::RowNum;
2
3use Data::Query::ExprHelpers;
4use Moo::Role;
5
6with 'Data::Query::Renderer::SQL::Slice::SubqueryRemap';
7
8b2c306b 8sub slice_stability {
9 (offset => 'check');
10}
11
98994ccc 12sub _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
941;