Remove last internal use of the legacy _resolve_condition (find)
Peter Rabbitson [Tue, 7 Jul 2015 20:14:42 +0000 (22:14 +0200)]
Also fixes the overly coarse 'is it a HASH' check added in 49ca473e/096f4212

lib/DBIx/Class/ResultSet.pm
t/sqlmaker/bind_transport.t
xt/extra/diagnostics/find_via_unsupported_rel.t [new file with mode: 0644]

index a0305c8..cf6e129 100644 (file)
@@ -9,6 +9,7 @@ use DBIx::Class::Carp;
 use DBIx::Class::ResultSetColumn;
 use DBIx::Class::ResultClass::HashRefInflator;
 use Scalar::Util qw( blessed reftype );
+use SQL::Abstract 'is_literal_value';
 use DBIx::Class::_Util qw(
   dbic_internal_try dbic_internal_catch dump_value emit_loud_diag
   fail_on_internal_wantarray fail_on_internal_call UNRESOLVABLE_CONDITION
@@ -777,7 +778,6 @@ sub find {
   my $self = shift;
   my $attrs = (@_ > 1 && ref $_[-1] eq 'HASH' ? pop(@_) : {});
 
-  my $rsrc = $self->result_source;
 
   my $constraint_name;
   if (exists $attrs->{key}) {
@@ -790,6 +790,8 @@ sub find {
   # Parse out the condition from input
   my $call_cond;
 
+  my $rsrc = $self->result_source;
+
   if (ref $_[0] eq 'HASH') {
     $call_cond = { %{$_[0]} };
   }
@@ -812,25 +814,34 @@ sub find {
   }
 
   # process relationship data if any
+  my $rel_list;
+
   for my $key (keys %$call_cond) {
     if (
       length ref($call_cond->{$key})
         and
-      my $relinfo = $rsrc->relationship_info($key)
+      ( $rel_list ||= { map { $_ => 1 } $rsrc->relationships } )
+        ->{$key}
         and
-      # implicitly skip has_many's (likely MC)
+      ! is_literal_value( $call_cond->{$key} )
+        and
+      # implicitly skip has_many's (likely MC), via the delete()
       ( ref( my $val = delete $call_cond->{$key} ) ne 'ARRAY' )
     ) {
-      my ($rel_cond, $crosstable) = $rsrc->_resolve_condition(
-        $relinfo->{cond}, $val, $key, $key
-      );
 
-      $self->throw_exception("Complex condition via relationship '$key' is unsupported in find()")
-         if $crosstable or ref($rel_cond) ne 'HASH';
+      # FIXME: it seems wrong that relationship conditions take precedence...?
+      $call_cond = {
+        %$call_cond,
 
-      # supplement condition
-      # relationship conditions take precedence (?)
-      @{$call_cond}{keys %$rel_cond} = values %$rel_cond;
+        %{ $rsrc->_resolve_relationship_condition(
+          rel_name => $key,
+          foreign_values => $val,
+          infer_values_based_on => {},
+
+          self_alias => "\xFE", # irrelevant
+          foreign_alias => "\xFF", # irrelevant
+        )->{inferred_values} },
+      };
     }
   }
 
index aacd59c..93b3c16 100644 (file)
@@ -18,6 +18,17 @@ my ($ROWS, $OFFSET) = (
 
 my $schema = DBICTest->init_schema();
 
+$schema->is_executed_sql_bind(
+  sub { $schema->resultset('Artist')->find( Math::BigInt->new(42) ) },
+  [
+    [
+      'SELECT me.artistid, me.name, me.rank, me.charfield FROM artist me WHERE me.artistid = ?',
+      [ { dbic_colname => "me.artistid", sqlt_datatype => "integer" }
+        => Math::BigInt->new(42) ],
+    ]
+  ]
+);
+
 my $rs = $schema->resultset('CD')->search({ -and => [
   'me.artist' => { '!=', '666' },
   'me.artist' => { '!=', \[ '?', [ _ne => 'bar' ] ] },
diff --git a/xt/extra/diagnostics/find_via_unsupported_rel.t b/xt/extra/diagnostics/find_via_unsupported_rel.t
new file mode 100644 (file)
index 0000000..10328e2
--- /dev/null
@@ -0,0 +1,31 @@
+BEGIN { do "./t/lib/ANFANG.pm" or die ( $@ || $! ) }
+
+use strict;
+use warnings;
+
+use Test::More;
+use Test::Exception;
+
+use DBICTest;
+
+my $schema = DBICTest->init_schema( no_deploy => 1 );
+
+my $artist = $schema->resultset('Artist')->new_result({ artistid => 1 });
+
+throws_ok {
+  $schema->resultset('ArtistUndirectedMap')->find({
+    mapped_artists => $artist,
+  });
+} qr/\QUnable to complete value inferrence - relationship 'mapped_artists' on source 'ArtistUndirectedMap' results in expression(s) instead of definitive values: ( id1 = ? OR id2 = ? )/,
+  'proper exception on OR relationship inferrence'
+;
+
+throws_ok {
+  $schema->resultset('Artwork_to_Artist')->find({
+    artist_limited_rank_opaque => $artist
+  })
+} qr/\QRelationship 'artist_limited_rank_opaque' on source 'Artwork_to_Artist' does not resolve to a 'foreign_values'-based reversed-join-free condition fragment/,
+  'proper exception on ipaque custom cond'
+;
+
+done_testing;