Applied patch from Zbigniew Lukasiak (with slight modifications) to accept "col ...
Norbert Buchmuller [Sun, 15 Feb 2009 15:39:26 +0000 (15:39 +0000)]
lib/SQL/Abstract.pm
t/07subqueries.t

index 46d2a4f..fcee0f9 100644 (file)
@@ -697,25 +697,36 @@ sub _where_field_IN {
   # backwards compatibility : if scalar, force into an arrayref
   $vals = [$vals] if defined $vals && ! ref $vals;
 
-  ref $vals eq 'ARRAY'
-    or puke "special op 'in' requires an arrayref";
-
   my ($label)       = $self->_convert($self->_quote($k));
   my ($placeholder) = $self->_convert('?');
-  my $and           = $self->_sqlcase('and');
   $op               = $self->_sqlcase($op);
 
-  if (@$vals) { # nonempty list
-    my $placeholders  = join ", ", (($placeholder) x @$vals);
-    my $sql           = "$label $op ( $placeholders )";
-    my @bind = $self->_bindtype($k, @$vals);
+  my ($sql, @bind) = $self->_SWITCH_refkind($vals, {
+    ARRAYREF => sub {     # list of choices
+      if (@$vals) { # nonempty list
+        my $placeholders  = join ", ", (($placeholder) x @$vals);
+        my $sql           = "$label $op ( $placeholders )";
+        my @bind = $self->_bindtype($k, @$vals);
 
-    return ($sql, @bind);
-  }
-  else { # empty list : some databases won't understand "IN ()", so DWIM
-    my $sql = ($op =~ /\bnot\b/i) ? $self->{sqltrue} : $self->{sqlfalse};
-    return ($sql);
-  }
+        return ($sql, @bind);
+      }
+      else { # empty list : some databases won't understand "IN ()", so DWIM
+        my $sql = ($op =~ /\bnot\b/i) ? $self->{sqltrue} : $self->{sqlfalse};
+        return ($sql);
+      }
+    },
+
+    ARRAYREFREF => sub {  # literal SQL with bind
+      my ($sql, @bind) = @$$vals;
+      return ("$label $op ( $sql )", @bind);
+    },
+
+    FALLBACK => sub {
+      puke "special op 'in' requires an arrayref (or arrayref-ref)";
+    },
+  });
+
+  return ($sql, @bind);
 }
 
 
index 85f973e..3c79842 100644 (file)
@@ -77,6 +77,19 @@ push @tests, {
   bind => [10, 20, '%son%'],\r
 };\r
 \r
+#6\r
+($sub_stmt, @sub_bind) = ("SELECT c1 FROM t1 WHERE c2 < ? AND c3 LIKE ?",\r
+                          100, "foo%");\r
+$where = {\r
+    foo => 1234,\r
+    bar => { -in => \[$sub_stmt => @sub_bind] },\r
+  };\r
+push @tests, {\r
+  where => $where,\r
+  stmt => " WHERE ( bar IN (SELECT c1 FROM t1 WHERE c2 < ? AND c3 LIKE ?) AND foo = ? )",\r
+  bind => [100, "foo%", 1234],\r
+};\r
+\r
 \r
 plan tests => scalar(@tests);\r
 \r