Adjust things for the is_literal_value and -ident SQLA 1.80 fixes
Peter Rabbitson [Fri, 26 Sep 2014 02:20:51 +0000 (04:20 +0200)]
(SQLA commits 52ce7dca and ddd6fbb6f)

The Oracle workaround is absolutely horrific and needs to be redone from
scratch. For the time being the tests seem to pass, so punt for later... sigh

Changes
lib/DBIx/Class/SQLMaker/OracleJoins.pm
lib/DBIx/Class/Storage/DBIHacks.pm
t/sqlmaker/oraclejoin.t

diff --git a/Changes b/Changes
index 6676078..6931858 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,8 @@
 Revision history for DBIx::Class
 
+    * Misc
+        - Adjust internals to accommodate fixed API in SQL::Abstract
+
 0.082800 2014-09-25 14:45 (UTC)
     * Known Issues
         - Passing large amounts of objects with stringification overload
index fe9bd07..0f50467 100644 (file)
@@ -93,13 +93,22 @@ sub _recurse_oracle_joins {
       @{$on->{-and}} == 1
     );
 
-    # sadly SQLA treats where($scalar) as literal, so we need to jump some hoops
-    push @where, map { \sprintf ('%s%s = %s%s',
-      ref $_ ? $self->_recurse_where($_) : $self->_quote($_),
-      $left_join,
-      ref $on->{$_} ? $self->_recurse_where($on->{$_}) : $self->_quote($on->{$_}),
-      $right_join,
-    )} keys %$on;
+
+    push @where, map { \do {
+        my ($sql) = $self->_recurse_where({
+          # FIXME - more borkage, more or less a copy of the kludge in ::SQLMaker::_join_condition()
+          $_ => ( length ref $on->{$_}
+            ? $on->{$_}
+            : { -ident => $on->{$_} }
+          )
+        });
+
+        $sql =~ s/\s*\=/$left_join =/
+          if $left_join;
+
+        "$sql$right_join";
+      }
+    } sort keys %$on;
   }
 
   return { -and => \@where };
index f8f908d..29b7f13 100644 (file)
@@ -1204,6 +1204,7 @@ sub _collapse_cond_unroll_pairs {
       if (ref $rhs eq 'HASH' and ! keys %$rhs) {
         # FIXME - SQLA seems to be doing... nothing...?
       }
+      # normalize top level -ident, for saner extract_fixed_condition_columns code
       elsif (ref $rhs eq 'HASH' and keys %$rhs == 1 and exists $rhs->{-ident}) {
         push @conds, { $lhs => { '=', $rhs } };
       }
@@ -1211,7 +1212,7 @@ sub _collapse_cond_unroll_pairs {
         push @conds, { $lhs => $rhs->{-value} };
       }
       elsif (ref $rhs eq 'HASH' and keys %$rhs == 1 and exists $rhs->{'='}) {
-        if( is_literal_value $rhs->{'='}) {
+        if ( length ref $rhs->{'='} and is_literal_value $rhs->{'='} ) {
           push @conds, { $lhs => $rhs };
         }
         else {
@@ -1229,7 +1230,14 @@ sub _collapse_cond_unroll_pairs {
 
             my ($l, $r) = %$p;
 
-            push @conds, ( ! length ref $r or is_plain_value($r) )
+            push @conds, (
+              ! length ref $r
+                or
+              # the unroller recursion may return a '=' prepended value already
+              ref $r eq 'HASH' and keys %$rhs == 1 and exists $rhs->{'='}
+                or
+              is_plain_value($r)
+            )
               ? { $l => $r }
               : { $l => { '=' => $r } }
             ;
@@ -1327,7 +1335,15 @@ sub _extract_fixed_condition_columns {
         }
       }
       # do not need to check for plain values - _collapse_cond did it for us
-      elsif(length ref $v->{'='} and is_literal_value($v->{'='}) ) {
+      elsif(
+        length ref $v->{'='}
+          and
+        (
+          ( ref $v->{'='} eq 'HASH' and keys %{$v->{'='}} == 1 and exists $v->{'='}{-ident} )
+            or
+          is_literal_value($v->{'='})
+        )
+       ) {
         $vals->{ 'SER_' . serialize $v->{'='} } = $v->{'='};
       }
     }
index c1725e0..e8e7444 100644 (file)
@@ -15,13 +15,15 @@ use DBIx::Class::SQLMaker::OracleJoins;
 
 my $sa = DBIx::Class::SQLMaker::OracleJoins->new;
 
+for my $rhs ( "me.artist", { -ident => "me.artist" } ) {
+
 #  my ($self, $table, $fields, $where, $order, @rest) = @_;
 my ($sql, @bind) = $sa->select(
     [
         { me => "cd" },
         [
             { "-join_type" => "LEFT", artist => "artist" },
-            { "artist.artistid" => "me.artist" },
+            { "artist.artistid" => $rhs },
         ],
     ],
     [ 'cd.cdid', 'cd.artist', 'cd.title', 'cd.year', 'artist.artistid', 'artist.name' ],
@@ -39,7 +41,7 @@ is_same_sql_bind(
         { me => "cd" },
         [
             { "-join_type" => "", artist => "artist" },
-            { "artist.artistid" => "me.artist" },
+            { "artist.artistid" => $rhs },
         ],
     ],
     [ 'cd.cdid', 'cd.artist', 'cd.title', 'cd.year', 'artist.artistid', 'artist.name' ],
@@ -56,8 +58,26 @@ is_same_sql_bind(
     [
         { me => "cd" },
         [
+            { "-join_type" => "right", artist => "artist" },
+            { "artist.artistid" => $rhs },
+        ],
+    ],
+    [ 'cd.cdid', 'cd.artist', 'cd.title', 'cd.year', 'artist.artistid', 'artist.name' ],
+    { 'artist.artistid' => 3 },
+    undef
+);
+is_same_sql_bind(
+  $sql, \@bind,
+  'SELECT cd.cdid, cd.artist, cd.title, cd.year, artist.artistid, artist.name FROM cd me, artist artist WHERE ( ( ( artist.artistid = me.artist(+) ) AND ( artist.artistid = ? ) ) )', [3],
+  'WhereJoins search with where clause'
+);
+
+($sql, @bind) = $sa->select(
+    [
+        { me => "cd" },
+        [
             { "-join_type" => "LEFT", artist => "artist" },
-            { "artist.artistid" => "me.artist" },
+            { "artist.artistid" => $rhs },
         ],
     ],
     [ 'cd.cdid', 'cd.artist', 'cd.title', 'cd.year', 'artist.artistid', 'artist.name' ],
@@ -70,5 +90,7 @@ is_same_sql_bind(
   'WhereJoins search with or in where clause'
 );
 
+}
+
 done_testing;