MOAR order
Matt S Trout [Mon, 7 May 2012 06:16:12 +0000 (06:16 +0000)]
lib/Data/Query/Renderer/SQL/Pg.pm [new file with mode: 0644]
lib/Data/Query/Renderer/SQL/Slice/FetchFirst.pm
lib/Data/Query/Renderer/SQL/Slice/SkipFirst.pm [new file with mode: 0644]
lib/Data/Query/Renderer/SQL/Slice/Top.pm [new file with mode: 0644]

diff --git a/lib/Data/Query/Renderer/SQL/Pg.pm b/lib/Data/Query/Renderer/SQL/Pg.pm
new file mode 100644 (file)
index 0000000..bc55ec4
--- /dev/null
@@ -0,0 +1,9 @@
+package Data::Query::Renderer::SQL::Pg;
+
+use Moo;
+
+extends 'Data::Query::Renderer::SQL::Naive';
+
+with 'Data::Query::Renderer::SQL::Slice::LimitOffset';
+
+1;
index c45f836..e3d8372 100644 (file)
@@ -5,18 +5,25 @@ use Data::Query::Constants qw(
 );
 use Moo::Role;
 
+sub _render_slice_limit {
+  my ($self, $dq) = @_;
+  return [
+    ($dq->{from} ? $self->_render($dq->{from}) : ()),
+    $self->_format_keyword('FETCH FIRST'),
+    sprintf("%i", $dq->{limit}{value}),
+    $self->_format_keyword('ROWS ONLY')
+  ];
+}
+
+sub _slice_type { 'FetchFirst' }
+
 sub _render_slice {
   my ($self, $dq) = @_;
   unless ($dq->{offset}) {
-    return [
-      ($dq->{from} ? $self->_render($dq->{from}) : ()),
-      $self->_format_keyword('FETCH FIRST'),
-      sprintf("%i", $dq->{limit}{value}),
-      $self->_format_keyword('ROWS ONLY')
-    ];
+    return $self->_render_slice_limit($dq);
   }
   unless ($dq->{order_is_stable}) {
-    die "FetchFirst limit style requires a stable order";
+    die $self->_slice_type." limit style requires a stable order";
   }
   die "Slice's inner is not a Select"
     unless (my $orig_select = $dq->{from})->{type} eq DQ_SELECT;
@@ -32,7 +39,7 @@ sub _render_slice {
     }
     my $key;
     if ($s->{type} eq DQ_IDENTIFIER) {
-      if (@{$s->{elements}} == 2) {
+      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;
@@ -44,7 +51,8 @@ sub _render_slice {
       $name ||= join('__', @{$s->{elements}});
       $key = join('.', @{$s->{elements}});
     } else {
-      die "XXX not implemented yet";
+      die "XXX not implemented yet" unless $name;
+      $key = "$s";
     }
     $name ||= sprintf("GENSYM__%03i",++$gensym_count);
     push @inside_select_list, +{
@@ -65,19 +73,28 @@ sub _render_slice {
   while ($order->{type} eq DQ_ORDER) {
     my $by = $order->{by};
     if ($by->{type} eq DQ_IDENTIFIER) {
+      $default_inside_alias ||= $by->{elements}[0]
+        if @{$by->{elements}} == 2;
       $order_map{$by}
         = $alias_map{join('.', @{$by->{elements}})}
           ||= do {
-                my $name = sprintf("ORDER__BY__%03i",++$order_gensym_count);
-                push @inside_select_list, +{
-                  type => DQ_ALIAS,
-                  from => $by,
-                  to => $name
-                };
-                +{
-                  type => DQ_IDENTIFIER,
-                  elements => [ $name ],
-                };
+                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, +{
+                    type => DQ_ALIAS,
+                    from => $by,
+                    to => $name
+                  };
+                  +{
+                    type => DQ_IDENTIFIER,
+                    elements => [ $name ],
+                  };
+                }
               };
     } else {
       die "XXX not implemented yet";
diff --git a/lib/Data/Query/Renderer/SQL/Slice/SkipFirst.pm b/lib/Data/Query/Renderer/SQL/Slice/SkipFirst.pm
new file mode 100644 (file)
index 0000000..f922fa1
--- /dev/null
@@ -0,0 +1,9 @@
+package Data::Query::Renderer::SQL::Slice::SkipFirst;
+
+use Moo::Role;
+
+with 'Data::Query::Renderer::SQL::Slice::FirstSkip';
+
+sub _slice_order { qw(offset limit) }
+
+1;
diff --git a/lib/Data/Query/Renderer/SQL/Slice/Top.pm b/lib/Data/Query/Renderer/SQL/Slice/Top.pm
new file mode 100644 (file)
index 0000000..124564d
--- /dev/null
@@ -0,0 +1,23 @@
+package Data::Query::Renderer::SQL::Slice::Top;
+
+use Data::Query::Constants qw(
+  DQ_SELECT DQ_ALIAS DQ_IDENTIFIER DQ_ORDER DQ_SLICE
+);
+use Moo::Role;
+
+with 'Data::Query::Renderer::SQL::Slice::FetchFirst';
+
+sub _render_slice_limit {
+  my ($self, $dq) = @_;
+  my $basic = $self->_render($dq->{from});
+  return [
+    $basic->[0],
+    $self->_format_keyword('TOP'),
+    sprintf("%i", $dq->{limit}{value}),
+    @{$basic}[1..$#$basic]
+  ];
+}
+
+sub _slice_type { 'Top' }
+
+1;