more functional select list generation
Matt S Trout [Sun, 29 Jul 2012 15:20:05 +0000 (15:20 +0000)]
lib/Data/Query/Renderer/SQL/Slice/FetchFirst.pm

index 3579215..f7be0b2 100644 (file)
@@ -25,43 +25,58 @@ sub _render_slice {
   }
   die "Slice's inner is not a Select"
     unless is_Select my $orig_select = $dq->{from};
-  my %alias_map;
+  die "Slice's Select not followed by Order but order_is_stable set"
+    unless is_Order $orig_select->{from};
+
   my $gensym_count;
-  my (@inside_select_list, @outside_select_list);
   my $default_inside_alias;
-  SELECT: foreach my $s (@{$orig_select->{select}}) {
-    my $name;
-    if (is_Alias $s) {
-      $name = $s->{to};
-      $s = $s->{from};
-    }
-    my $key;
-    if (is_Identifier $s) {
-      if (!$name and @{$s->{elements}} == 2) {
-        $default_inside_alias ||= $s->{elements}[0];
-        if ($s->{elements}[0] eq $default_inside_alias) {
-          $alias_map{join('.',@{$s->{elements}})} = $s;
-          push @inside_select_list, $s;
-          push @outside_select_list, $s;
-          next SELECT;
-        }
+
+  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), $_);
       }
-      $name ||= join('__', @{$s->{elements}});
-      $key = join('.', @{$s->{elements}});
     } else {
-      die "XXX not implemented yet" unless $name;
-      $key = "$s";
+      Alias(sprintf("GENSYM__%03i",++$gensym_count), $_);
     }
-    $name ||= sprintf("GENSYM__%03i",++$gensym_count);
-    push @inside_select_list, Alias($name, $s);
-    push @outside_select_list, $alias_map{$key} = Identifier($name);
-  }
-  my $order = $orig_select->{from};
+  } @{$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;
-  die "Slice's Select not followed by Order but order_is_stable set"
-    unless is_Order $order;
-  my (@order_nodes, %order_map);
-  while (is_Order $order) {
+  my %order_map;
+  foreach my $order (@order_nodes) {
     my $by = $order->{by};
     if (is_Identifier $by) {
       $default_inside_alias ||= $by->{elements}[0]
@@ -83,14 +98,14 @@ sub _render_slice {
     } else {
       die "XXX not implemented yet";
     }
-    push @order_nodes, $order;
-    $order = $order->{from};
   }
+
   $default_inside_alias ||= 'me';
+
   my $limit_plus_offset = +{
     %{$dq->{limit}}, value => $dq->{limit}{value} + $dq->{offset}{value}
   };
-  my $inner_body = $order;
+
   return $self->_render(
     map {
       $dq->{preserve_order}