add null, in, between etc. support
Matt S Trout [Mon, 25 Jul 2011 06:41:06 +0000 (06:41 +0000)]
lib/Data/Query/Renderer/SQL/Naive.pm

index b2517b0..bb81339 100644 (file)
@@ -23,9 +23,12 @@ sub BUILDALL {
 
 sub _default_simple_ops {
   +{
-    (map +($_ => 'binop'), qw(= > < >= <=) ),
-    (map +($_ => 'unop'), (qw(NOT)) ),
+    (map +($_ => 'binop'), qw(= > < >= <= != LIKE), 'NOT LIKE' ),
+    (map +($_ => 'unop'), qw(NOT) ),
+    (map +($_ => 'unop_reverse'), ('IS NULL', 'IS NOT NULL')),
     (map +($_ => 'flatten'), qw(AND OR) ),
+    (map +($_ => 'in'), ('IN', 'NOT IN')),
+    (map +($_ => 'between'), ('BETWEEN', 'NOT BETWEEN'))
   }
 }
 
@@ -108,10 +111,14 @@ sub _render_operator {
   unless (exists $op->{$self->_operator_type}) {
     $op->{$self->_operator_type} = $self->_convert_op($dq);
   }
-  if (my $op_type = $self->{simple_ops}{my $op_name = $op->{$self->_operator_type}}) {
+  my $op_name = $op->{$self->_operator_type};
+  if (my $op_type = $self->{simple_ops}{$op_name}) {
     return $self->${\"_handle_op_type_${op_type}"}($op_name, $dq);
+  } elsif (my $meth = $self->can("_handle_op_special_${op_name}")) {
+    return $self->$meth($dq);
   }
-  die "Couldn't render operator ".$op->{$self->_operator_type};
+  #die "Couldn't render operator ".$op->{$self->_operator_type};
+  $self->_handle_op_type_binop($op_name, $dq);
 }
 
 sub _handle_op_type_binop {
@@ -132,8 +139,21 @@ sub _handle_op_type_unop {
       .scalar(@{$dq->{args}})." entries"
     unless @{$dq->{args}} == 1;
   [
-    [ $op_name ],
+    '(',
+    $op_name,
+    $self->_render($dq->{args}[0]),
+    ')',
+  ]
+}
+
+sub _handle_op_type_unop_reverse {
+  my ($self, $op_name, $dq) = @_;
+  die "${op_name} registered as unary op but args contain "
+      .scalar(@{$dq->{args}})." entries"
+    unless @{$dq->{args}} == 1;
+  [
     $self->_render($dq->{args}[0]),
+    $op_name,
   ]
 }
 
@@ -164,6 +184,20 @@ sub _handle_op_type_flatten {
   \@sql;
 }
 
+sub _handle_op_type_in {
+  my ($self, $op, $dq) = @_;
+  my ($lhs, @in) = @{$dq->{args}};
+  my @rhs = ('(', map +($self->_render($_), ','), @in);
+  $rhs[-1] = ')';
+  [ $self->_render($lhs), $op, @rhs ];
+}
+
+sub _handle_op_type_between {
+  my ($self, $op_name, $dq) = @_;
+  my ($lhs, $rhs1, $rhs2) = (map $self->_render($_), @{$dq->{args}});
+  [ $lhs, $op_name, $rhs1, 'AND', $rhs2 ];
+}
+
 sub _convert_op {
   my ($self, $dq) = @_;
   if (my $perl_op = $dq->{'operator'}->{'Perl'}) {