Allow scalarref in IN and open up non-grouping parenthesis around IN arguments (saves...
Peter Rabbitson [Tue, 22 Sep 2009 08:10:34 +0000 (08:10 +0000)]
lib/SQL/Abstract.pm
t/05in_between.t [moved from t/05between.t with 80% similarity]

index 7740f79..431d428 100644 (file)
@@ -893,20 +893,34 @@ sub _where_field_IN {
       }
     },
 
+    SCALARREF => sub {  # literal SQL
+      my $sql = $self->_open_outer_paren ($$vals);
+      return ("$label $op ( $sql )");
+    },
     ARRAYREFREF => sub {  # literal SQL with bind
       my ($sql, @bind) = @$$vals;
       $self->_assert_bindval_matches_bindtype(@bind);
+      $sql = $self->_open_outer_paren ($sql);
       return ("$label $op ( $sql )", @bind);
     },
 
     FALLBACK => sub {
-      puke "special op 'in' requires an arrayref (or arrayref-ref)";
+      puke "special op 'in' requires an arrayref (or scalarref/arrayref-ref)";
     },
   });
 
   return ($sql, @bind);
 }
 
+# Some databases (SQLite) treat col IN (1, 2) different from
+# col IN ( (1, 2) ). Use this to strip all outer parens while
+# adding them back in the corresponding method
+sub _open_outer_paren {
+  my ($self, $sql) = @_;
+  $sql = $1 while $sql =~ /^ \s* \( (.*) \) \s* $/x;
+  return $sql;
+}
+
 
 #======================================================================
 # ORDER BY
similarity index 80%
rename from t/05between.t
rename to t/05in_between.t
index a155b20..ae6e61c 100644 (file)
@@ -9,20 +9,6 @@ use SQL::Abstract::Test import => ['is_same_sql_bind'];
 use Data::Dumper;
 use SQL::Abstract;
 
-=begin
-Test -between and -in 
-  * between
-    * [scalar, scalar]
-    * [scalarref, scalar]
-    * [scalar, scalarref]
-    * [scalarref, scalarref]
-    * \[]
-      * \["? AND ?", scalar, scalar]
-      * \["1 AND ?", scalar]
-      * \["? AND 2", scalar]
-      * \["1 AND 2"]
-=cut
-
 my @in_between_tests = (
   {
     where => { x => { -between => [1, 2] } },
@@ -78,6 +64,29 @@ my @in_between_tests = (
     bind => [],
     test => '-between with literal sql with a literal (\"\'this\' AND \'that\'")',
   },
+
+
+  {
+    parenthesis_significant => 1,
+    where => { x => { -in => [ 1 .. 3] } },
+    stmt => "WHERE ( x IN (?, ?, ?) )",
+    bind => [ 1 .. 3],
+    test => '-in with an array of scalars',
+  },
+  {
+    parenthesis_significant => 1,
+    where => { x => { -in => \'( 1,2,lower(y) )' } },
+    stmt => "WHERE ( x IN (1, 2, lower(y) ) )",
+    bind => [],
+    test => '-in with a literal scalarref',
+  },
+  {
+    parenthesis_significant => 1,
+    where => { x => { -in => \['( ( ?,?,lower(y) ) )', 1, 2] } },
+    stmt => "WHERE ( x IN (?, ?, lower(y) ) )",
+    bind => [1, 2],
+    test => '-in with a literal arrayrefref',
+  },
 );
 
 plan tests => @in_between_tests*4;
@@ -85,6 +94,7 @@ plan tests => @in_between_tests*4;
 for my $case (@in_between_tests) {
   TODO: {
     local $TODO = $case->{todo} if $case->{todo};
+    local $SQL::Abstract::Test::parenthesis_significant = $case->{parenthesis_significant};
 
     local $Data::Dumper::Terse = 1;