1 package Data::Query::Renderer::SQL::Slice::FetchFirst;
3 use Data::Query::ExprHelpers;
6 sub _render_slice_limit {
9 ($dq->{from} ? $self->_render($dq->{from}) : ()),
10 $self->_format_keyword('FETCH FIRST'),
11 sprintf("%i", $dq->{limit}{value}),
12 $self->_format_keyword('ROWS ONLY')
16 sub _slice_type { 'FetchFirst' }
20 unless ($dq->{offset}) {
21 return $self->_render_slice_limit($dq);
23 unless ($dq->{order_is_stable}) {
24 die $self->_slice_type." limit style requires a stable order";
26 die "Slice's inner is not a Select"
27 unless is_Select my $orig_select = $dq->{from};
30 my (@inside_select_list, @outside_select_list);
31 my $default_inside_alias;
32 SELECT: foreach my $s (@{$orig_select->{select}}) {
39 if (is_Identifier $s) {
40 if (!$name and @{$s->{elements}} == 2) {
41 $default_inside_alias ||= $s->{elements}[0];
42 if ($s->{elements}[0] eq $default_inside_alias) {
43 $alias_map{join('.',@{$s->{elements}})} = $s;
44 push @inside_select_list, $s;
45 push @outside_select_list, $s;
49 $name ||= join('__', @{$s->{elements}});
50 $key = join('.', @{$s->{elements}});
52 die "XXX not implemented yet" unless $name;
55 $name ||= sprintf("GENSYM__%03i",++$gensym_count);
56 push @inside_select_list, Alias($name, $s);
57 push @outside_select_list, $alias_map{$key} = Identifier($name);
59 my $order = $orig_select->{from};
60 my $order_gensym_count;
61 die "Slice's Select not followed by Order but order_is_stable set"
62 unless is_Order $order;
63 my (@order_nodes, %order_map);
64 while (is_Order $order) {
65 my $by = $order->{by};
66 if (is_Identifier $by) {
67 $default_inside_alias ||= $by->{elements}[0]
68 if @{$by->{elements}} == 2;
70 = $alias_map{join('.', @{$by->{elements}})}
73 @{$by->{elements}} == 2
74 and $by->{elements}[0] eq $default_inside_alias
78 my $name = sprintf("ORDER__BY__%03i",++$order_gensym_count);
79 push @inside_select_list, Alias($name, $by);
84 die "XXX not implemented yet";
86 push @order_nodes, $order;
87 $order = $order->{from};
89 $default_inside_alias ||= 'me';
90 my $limit_plus_offset = +{
91 %{$dq->{limit}}, value => $dq->{limit}{value} + $dq->{offset}{value}
93 my $inner_body = $order;
94 return $self->_render(
98 \@outside_select_list,
100 Order($order_map{$b->{by}}, $b->{reverse}, $a)
101 } @order_nodes, Alias($default_inside_alias, $_)
108 @outside_select_list,
109 $dq->{preserve_order}
110 ? (grep @{$_->{elements}} == 1,
111 @order_map{map $_->{by}, @order_nodes})
115 Order($order_map{$b->{by}}, !$b->{reverse}, $a)
119 $default_inside_alias,
121 undef, $limit_plus_offset,
123 \@inside_select_list,
125 Order($b->{by}, $b->{reverse}, $a)
126 } @order_nodes, $inner_body