--- /dev/null
+package Data::Query::Renderer::SQL::Slice::RowNum;
+
+use Data::Query::ExprHelpers;
+use Moo::Role;
+
+with 'Data::Query::Renderer::SQL::Slice::SubqueryRemap';
+
+sub _render_slice {
+ my ($self, $dq) = @_;
+ die "Slice's inner is not a Select"
+ unless is_Select my $orig_select = $dq->{from};
+ my %remapped = $self->_subquery_remap_select($orig_select);
+ my $inside_select = Alias(
+ $remapped{default_inside_alias},
+ Select($remapped{inside_select_list}, $orig_select->{from}),
+ );
+ unless ($dq->{offset}) {
+ return $self->render(
+ Select(
+ $remapped{outside_select_list},
+ Where(
+ Operator(
+ { 'SQL.Naive' => '<=' },
+ [
+ Literal(SQL => 'ROWNUM'),
+ $dq->{limit}
+ ]
+ ),
+ $inside_select
+ )
+ )
+ );
+ }
+ my ($limit_plus_offset, $offset_plus) = (
+ { %{$dq->{limit}}, value => $dq->{limit}{value}+$dq->{offset}{value} },
+ { %{$dq->{limit}}, value => $dq->{offset}{value}+1 }
+ );
+
+ my $rownum_name = 'rownum__index';
+
+ if ($dq->{order_is_stable}) {
+ return $self->render(
+ Select(
+ $remapped{outside_select_list},
+ Where(
+ Operator(
+ { 'SQL.Naive' => '>=' },
+ [ Identifier($rownum_name), $limit_plus_offset, ]
+ ),
+ Alias(
+ $remapped{default_inside_alias},
+ Select(
+ [ @{$remapped{outside_select_list}},
+ Alias($rownum_name, Literal(SQL => 'ROWNUM')) ],
+ Where(
+ Operator(
+ { 'SQL.Naive' => '<=' },
+ [ Literal(SQL => 'ROWNUM'), $offset_plus ]
+ ),
+ $inside_select,
+ )
+ )
+ )
+ )
+ )
+ );
+ } else {
+ return $self->render(
+ Select(
+ $remapped{outside_select_list},
+ Where(
+ Operator(
+ { 'SQL.Naive' => 'BETWEEN' },
+ [ Identifier($rownum_name), $limit_plus_offset, $offset_plus ]
+ ),
+ Alias(
+ $remapped{default_inside_alias},
+ Select(
+ [ @{$remapped{outside_select_list}},
+ Alias($rownum_name, Literal(SQL => 'ROWNUM')) ],
+ $inside_select
+ )
+ )
+ )
+ )
+ );
+ }
+}
+
+1;