don't negate undef in Slice/FetchFirst
[dbsrgits/Data-Query.git] / lib / Data / Query / Renderer / SQL / Slice / FetchFirst.pm
index d885fb4..f2741d6 100644 (file)
@@ -3,6 +3,8 @@ package Data::Query::Renderer::SQL::Slice::FetchFirst;
 use Data::Query::ExprHelpers;
 use Moo::Role;
 
+with 'Data::Query::Renderer::SQL::Slice::SubqueryRemap';
+
 sub _render_slice_limit {
   my ($self, $dq) = @_;
   return [
@@ -13,6 +15,10 @@ sub _render_slice_limit {
   ];
 }
 
+sub slice_stability {
+  (offset => 'requires');
+}
+
 sub _slice_type { 'FetchFirst' }
 
 sub _render_slice {
@@ -28,79 +34,14 @@ sub _render_slice {
   die "Slice's Select not followed by Order but order_is_stable set"
     unless is_Order $orig_select->{from};
 
-  my $gensym_count;
-  my $default_inside_alias;
-
-  my @inside_select_list = map {
-    if (is_Alias) {
-      $_;
-    } elsif (is_Identifier) {
-      my @el = @{$_->{elements}};
-      if (@el == 2 and $el[0] eq ($default_inside_alias ||= $el[0])) {
-        $_;
-      } else {
-        Alias(join('__', @el), $_);
-      }
-    } else {
-      Alias(sprintf("GENSYM__%03i",++$gensym_count), $_);
-    }
-  } @{$orig_select->{select}};
-
-  my %alias_map = map {
-    if (is_Alias and is_Identifier $_->{from}) {
-      +(join('.',@{$_->{from}{elements}}) => Identifier($_->{to}))
-    } elsif (is_Identifier) {
-      +(join('.',@{$_->{elements}}) => $_)
-    } else {
-      +()
-    }
-  } @inside_select_list;
-
-  my @outside_select_list = map {
-    if (is_Alias) {
-      Identifier($_->{to});
-    } else {
-      $_;
-    }
-  } @inside_select_list;
-
-  my @order_nodes;
-  my $inner_body = do {
-    my $order = $orig_select->{from};
-    while (is_Order $order) {
-      push @order_nodes, $order;
-      $order = $order->{from};
-    }
-    $order;
-  };
-
-  my $order_gensym_count;
-  my @mapped_order = map {
-    my $by = $_->{by};
-    if (is_Identifier $by) {
-      $default_inside_alias ||= $by->{elements}[0]
-        if @{$by->{elements}} == 2;
-      my $mapped_by
-        = $alias_map{join('.', @{$by->{elements}})}
-          ||= do {
-                if (
-                  @{$by->{elements}} == 2
-                  and $by->{elements}[0] eq $default_inside_alias
-                ) {
-                  $by;
-                } else {
-                  my $name = sprintf("ORDER__BY__%03i",++$order_gensym_count);
-                  push @inside_select_list, Alias($name, $by);
-                  Identifier($name);
-                }
-              };
-      Order($mapped_by, $_->{reverse});
-    } else {
-      die "XXX not implemented yet";
-    }
-  } @order_nodes;
+  my %remapped = $self->_subquery_remap($orig_select);
 
-  $default_inside_alias ||= 'me';
+  my @inside_select_list = @{$remapped{inside_select_list}};
+  my @outside_select_list = @{$remapped{outside_select_list}};
+  my @inside_order = @{$remapped{inside_order}};
+  my @outside_order = @{$remapped{outside_order}};
+  my $default_inside_alias = $remapped{default_inside_alias};
+  my $inner_body = $remapped{inner_body};
 
   my $limit_plus_offset = +{
     %{$dq->{limit}}, value => $dq->{limit}{value} + $dq->{offset}{value}
@@ -112,9 +53,9 @@ sub _render_slice {
         ? Select(
           \@outside_select_list,
           compose {
-            Order($b->{by}, $b->{reverse}, $a)
+            Order($b->{by}, $b->{reverse}, $b->{nulls}, $a)
           } (
-            @mapped_order,
+            @outside_order,
             Alias($default_inside_alias, $_)
           )
         )
@@ -127,13 +68,13 @@ sub _render_slice {
             @outside_select_list,
             $dq->{preserve_order}
               ? (grep @{$_->{elements}} == 1,
-                  map $_->{by}, @mapped_order)
+                  map $_->{by}, @outside_order)
               : (),
           ],
           compose {
-            Order($b->{by}, !$b->{reverse}, $a)
+            Order($b->{by}, !$b->{reverse}, -($b->{nulls}||0), $a)
           } (
-            @mapped_order,
+            @outside_order,
             Alias(
               $default_inside_alias,
               Slice(
@@ -141,8 +82,8 @@ sub _render_slice {
                 Select(
                   \@inside_select_list,
                   compose {
-                    Order($b->{by}, $b->{reverse}, $a)
-                  } @order_nodes, $inner_body
+                    Order($b->{by}, $b->{reverse}, $b->{nulls}, $a)
+                  } @inside_order, $inner_body
                 )
               )
             )