restore unary op functionality
Matt S Trout [Sun, 14 Oct 2018 18:46:29 +0000 (18:46 +0000)]
lib/SQL/Abstract.pm
t/08special_ops.t

index 7327fe2..dc79349 100644 (file)
@@ -599,6 +599,9 @@ sub _expand_expr_hashpair {
       # top level special ops are illegal in general
       puke "Illegal use of top-level '-$op'"
         if List::Util::first { $op =~ $_->{regex} } @{$self->{special_ops}};
+      if (my $us = List::Util::first { $op =~ $_->{regex} } @{$self->{unary_ops}}) {
+        return { -op => [ $op, $v ] };
+      }
     }
     if ($k eq '-value' and my $m = our $Cur_Col_Meta) {
       return +{ -bind => [ $m, $v ] };
@@ -744,6 +747,13 @@ sub _expand_expr_hashpair {
     if (my $us = List::Util::first { $vk =~ $_->{regex} } @{$self->{user_special_ops}}) {
       return { -op => [ $vk, { -ident => $k }, $vv ] };
     }
+    if (my $us = List::Util::first { $vk =~ $_->{regex} } @{$self->{unary_ops}}) {
+      return { -op => [
+        $self->{cmp},
+        { -ident => $k },
+        { -op => [ $vk, $vv ] }
+      ] };
+    }
     if (ref($vv) eq 'ARRAY') {
       my ($logic, @values) = (
         (defined($vv->[0]) and $vv->[0] =~ /^-(and|or)$/i)
@@ -947,6 +957,9 @@ sub _render_op {
       unless my ($k) = map $_->{-ident}, grep ref($_) eq 'HASH', $args[0];
     return $self->${\($us->{handler})}($k, $op, $args[1]);
   }
+  if (my $us = List::Util::first { $op =~ $_->{regex} } @{$self->{unary_ops}}) {
+    return $self->${\($us->{handler})}($op, $args[0]);
+  }
   my $final_op = $op =~ /^(?:is|not)_/ ? join(' ', split '_', $op) : $op;
   if (@args == 1 and $op !~ /^(and|or)$/) {
     my ($expr_sql, @bind) = $self->_render_expr($args[0]);
index d989a79..131f99e 100644 (file)
@@ -33,6 +33,11 @@ my $sqlmaker = SQL::Abstract->new(special_ops => [
      }
    },
 
+], unary_ops => [
+  # unary op from Mojo::Pg
+  {regex => qr/^json$/i,
+   handler => sub { '?', { json => $_[2] } }
+  },
 ]);
 
 my @tests = (
@@ -50,6 +55,18 @@ my @tests = (
     bind  => [],
   },
 
+  #3
+  { where => { foo => { -json => { bar => 'baz' } } },
+    stmt => "WHERE foo = ?",
+    bind => [ { json => { bar => 'baz' } } ],
+  },
+
+  #4
+  { where => { foo => { '@>' => { -json => { bar => 'baz' } } } },
+    stmt => "WHERE foo @> ?",
+    bind => [ { json => { bar => 'baz' } } ],
+  },
+
 );
 
 for (@tests) {