add slice_subquery method for DBIC introspection
[dbsrgits/Data-Query.git] / lib / Data / Query / Renderer / SQL / Slice / GenericSubquery.pm
CommitLineData
01d7143b 1package Data::Query::Renderer::SQL::Slice::GenericSubquery;
2
3use Data::Query::ExprHelpers;
4use Moo::Role;
5
6with 'Data::Query::Renderer::SQL::Slice::SubqueryRemap';
7
fbf38b8e 8sub slice_subquery {
9 (limit => 1, offset => 1);
10}
11
8b2c306b 12sub slice_stability {
13 (limit => 'requires', offset => 'requires');
14}
15
01d7143b 16sub _render_slice {
17 my ($self, $dq) = @_;
18 die "Slice's inner is not a Select"
19 unless is_Select my $orig_select = $dq->{from};
20 my %remapped = $self->_subquery_remap($orig_select);
21 my $first_from = $remapped{inner_body};
5a058623 22 # Should we simply strip until we reach a join/alias/etc. here?
23 $first_from = $first_from->{from}{from} if is_Having($first_from);
01d7143b 24 $first_from = $first_from->{from} if is_Where($first_from);
25 while (is_Join $first_from) {
26 $first_from = $first_from->{left};
27 }
28 $first_from = $first_from->{from} if is_Alias($first_from);
29 my $first_order = $remapped{inside_order}[0]{by};
30 my $count_col = $first_order->{elements}[-1];
31 my $count_alias = 'rownum__emulation';
32 my $count_sel = Select(
33 [ Operator({ 'SQL.Naive' => 'apply' }, [ Identifier('COUNT'), Identifier('*') ]) ],
34 Where(
35 Operator(
e31249d4 36 { 'SQL.Naive' => ($remapped{inside_order}[0]{reverse} ? '>' : '<') },
37 [
38 Identifier($count_alias, $count_col),
39 $remapped{outside_order}[0]{by}
40 ]
01d7143b 41 ),
42 Alias($count_alias, $first_from)
43 )
44 );
45 my $count_where = Operator(
46 { 'SQL.Naive' => ($dq->{offset} ? 'BETWEEN' : '<') },
47 [ $count_sel, (
48 $dq->{offset}
49 ? (
50 $dq->{offset},
51 {
52 %{$dq->{limit}},
53 value => $dq->{limit}{value}+$dq->{offset}{value}-1
54 }
55 )
56 : ($dq->{limit})
57 )
58 ]
59 );
60 return $self->render(
61 Select(
62 $remapped{outside_select_list},
e3335558 63 (compose { no warnings 'once'; Order($b->{by}, $b->{reverse}, $b->{nulls}, $a) }
01d7143b 64 @{$remapped{outside_order}},
65 Where(
66 $count_where,
67 Alias(
68 $remapped{default_inside_alias},
69 Select(
70 $remapped{inside_select_list},
71 $remapped{inner_body},
72 )
73 )
74 )
75 )
76 )
77 );
78}
79
801;