limit/offset
Matt S Trout [Thu, 11 Oct 2012 12:34:10 +0000 (13:34 +0100)]
lib/Data/Query/ExprDeclare.pm
t/example.t

index b2f38a6..8cb1fbc 100644 (file)
@@ -9,7 +9,7 @@ use Safe::Isa;
 use base qw(Exporter);
 
 our @EXPORT = qw(
-  expr SELECT AS FROM BY JOIN ON LEFT WHERE ORDER GROUP DESC
+  expr SELECT AS FROM BY JOIN ON LEFT WHERE ORDER GROUP DESC LIMIT OFFSET
 );
 
 sub expr (&) {
@@ -50,7 +50,14 @@ sub SELECT (&;@) {
      );
   }
       
-  return Select(\@final, $_[0]);
+  my $final = Select(\@final, shift);
+
+  if (is_Slice($_[0])) {
+    my ($limit, $offset) = @{+shift}{qw(limit offset)};
+    $final = Slice($offset, $limit, $final);
+  }
+
+  return $final;
 }
 
 sub BY (&;@) { @_ }
@@ -79,7 +86,7 @@ sub FROM (&;@) {
     my $order = shift;
     $from_dq = Order($order->{by}, $order->{reverse}, $from_dq);
   }
-  return $from_dq;
+  return ($from_dq, @_);
 }
 
 sub LEFT {
@@ -90,7 +97,7 @@ sub LEFT {
 }
 
 sub JOIN (&;@) {
-  my $join = FROM(\&{+shift});
+  my ($join) = FROM(\&{+shift});
   my $on = do {
     if ($_[0]->$_isa('LIES::ON')) {
       ${+shift}
@@ -122,7 +129,21 @@ sub ORDER {
       0;
     }
   };
-  return compose { Order($b, $reverse, $a) } @order, undef;
+  return ((compose { Order($b, $reverse, $a) } @order, undef), @_);
+}
+
+sub LIMIT (&;@) {
+  my ($limit) = map _value($_), _run_expr(shift);
+  if (is_Slice($_[0])) {
+    my $slice = shift;
+    return +{ %{$slice}, limit => $limit }, @_;
+  }
+  return Slice(undef, $limit), @_;
+}
+
+sub OFFSET (&;@) {
+  my ($offset) = map _value($_), _run_expr(shift);
+  return Slice($offset, undef), @_;
 }
 
 1;
index 35a1a92..f7999d6 100644 (file)
@@ -1,6 +1,7 @@
 use strictures;
 use Data::Query::ExprDeclare;
 use Data::Query::Renderer::SQL::Naive;
+use Moo::Role ();
 use Devel::Dwarn;
 
 my $renderer = Data::Query::Renderer::SQL::Naive->new;
@@ -53,3 +54,15 @@ DwarnL render_expr(
 DwarnL render_expr(
   SELECT { $_->cd->name } FROM { $_->cds, AS 'cd' } ORDER BY { $_->year }
 );
+
+$renderer = Moo::Role->create_class_with_roles(
+  'Data::Query::Renderer::SQL::Naive',
+  'Data::Query::Renderer::SQL::Slice::LimitOffset'
+)->new;
+
+DwarnL render_expr(
+  SELECT { $_->cd->name }
+  FROM { $_->cds, AS 'cd' }
+  ORDER BY { $_->year }
+  LIMIT { 10 } OFFSET { 10 }
+);