Fix trailing whitespace
[dbsrgits/Data-Query.git] / lib / Data / Query / ExprDeclare.pm
index 971e3cc..b6896bd 100644 (file)
@@ -5,13 +5,21 @@ use Data::Query::ExprBuilder::Identifier;
 use Data::Query::ExprHelpers;
 use Data::Query::Constants;
 use Safe::Isa;
+use Exporter ();
 
-use base qw(Exporter);
+sub import {
+  warnings->unimport('precedence');
+  goto &Exporter::import;
+}
+
+our @EXPORT = qw(expr);
 
-our @EXPORT = qw(expr SELECT AS FROM BY JOIN ON LEFT WHERE ORDER GROUP);
+our @EXPORT_OK = qw(
+  SELECT AS FROM BY JOIN ON LEFT WHERE ORDER GROUP DESC LIMIT OFFSET NULLS FIRST LAST
+);
 
 sub expr (&) {
-  _run_expr($_[0])->{expr};
+  _run_expr($_[0]);
 }
 
 sub _run_expr {
@@ -47,8 +55,15 @@ sub SELECT (&;@) {
         : $e
      );
   }
-      
-  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 (&;@) { @_ }
@@ -66,9 +81,18 @@ sub FROM (&;@) {
     $from_dq = { %{+shift}, left => $from_dq };
   }
   if (is_Where($_[0])) {
-    $from_dq = Where(shift->{where}, $from_dq);
+    my $where = shift->{where};
+    if (is_Select($from_dq)) {
+      $from_dq = Select($from_dq->{select}, Where($where, $from_dq->{from}));
+    } else {
+      $from_dq = Where($where, $from_dq);
+    }
+  }
+  while (is_Order($_[0])) {
+    my $order = shift;
+    $from_dq = Order($order->{by}, $order->{reverse}, $order->{nulls}, $from_dq);
   }
-  return $from_dq;
+  return ($from_dq, @_);
 }
 
 sub LEFT {
@@ -79,7 +103,7 @@ sub LEFT {
 }
 
 sub JOIN (&;@) {
-  my $join = FROM(\&{+shift});
+  my ($join) = FROM(\&{+shift});
   my $on = do {
     if ($_[0]->$_isa('LIES::ON')) {
       ${+shift}
@@ -100,4 +124,37 @@ sub WHERE (&;@) {
   return Where(_value(_run_expr($w))), @_;
 }
 
+sub DESC { bless({}, 'LIES::DESC'), @_ }
+sub NULLS { bless(\shift, 'LIES::NULLS'), @_ }
+sub FIRST { 1, @_ }
+sub LAST { -1, @_ }
+
+sub ORDER {
+  my @order = map _value($_), _run_expr(shift);
+  my $reverse = do {
+    if ($_[0]->$_isa('LIES::DESC')) {
+      shift; 1;
+    } else {
+      0;
+    }
+  };
+  my $nulls = $_[0]->$_isa('LIES::NULLS') ? ${+shift} : undef;
+
+  return ((compose { Order($b, $reverse, $nulls, $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;