support expr {} in join cond
Matt S Trout [Fri, 15 Nov 2013 10:07:47 +0000 (10:07 +0000)]
lib/DBIx/Class/ResultSource.pm
t/dq/join.t [new file with mode: 0644]

index 3233e3a..d758ed7 100644 (file)
@@ -13,6 +13,7 @@ use Devel::GlobalDestruction;
 use Try::Tiny;
 use List::Util 'first';
 use Scalar::Util qw/blessed weaken isweak/;
+use Data::Query::ExprHelpers;
 
 use namespace::clean;
 
@@ -1811,6 +1812,33 @@ sub _resolve_condition {
     }
     return wantarray ? (\@ret, $crosstable) : \@ret;
   }
+  elsif (blessed($cond) and $cond->isa('Data::Query::ExprBuilder')) {
+    my %cross;
+    my $as = blessed($for) ? 'me' : $as;
+    my $mapped = map_dq_tree {
+      if (is_Identifier and @{$_->{elements}} == 2) {
+        foreach my $check ([ foreign => $as ], [ self => $for ]) {
+          my ($ident, $thing) = @$check;
+          if ($_->{elements}[0] eq $ident) {
+            if ($thing and !ref($thing)) {
+              $cross{$thing} = 1;
+              return \Identifier($thing, $_->{elements}[1]);
+            } elsif (!defined($thing)) {
+              return \perl_scalar_value(undef);
+            } elsif ((ref($thing)||'') eq 'HASH') {
+              return \perl_scalar_value($thing->{$_->{elements}[1]});
+            } elsif (blessed($thing)) {
+              return \perl_scalar_value($thing->get_column($_->{elements}[1]));
+            } else {
+              die "I have no idea what ${thing} is supposed to be";
+            }
+          }
+        }
+      }
+      return $_;
+    } $cond->{expr};
+    return (wantarray ? (\$mapped, (keys %cross == 2)) : \$mapped);
+  }
   else {
     $self->throw_exception ("Can't handle condition $cond for relationship '$rel_name' yet :(");
   }
diff --git a/t/dq/join.t b/t/dq/join.t
new file mode 100644 (file)
index 0000000..b6ca14b
--- /dev/null
@@ -0,0 +1,35 @@
+use strict;
+use warnings;
+
+use Test::More;
+use Test::Exception;
+use Test::Warn;
+use lib qw(t/lib);
+use DBICTest::Schema::Artist;
+use Data::Query::ExprDeclare;
+BEGIN {
+  DBICTest::Schema::Artist->has_many(
+    cds2 => 'DBICTest::Schema::CD',
+    expr { $_->foreign->artist == $_->self->artistid }
+  );
+  DBICTest::Schema::Artist->has_many(
+    cds2_pre2k => 'DBICTest::Schema::CD',
+    expr {
+      $_->foreign->artist == $_->self->artistid
+      & $_->foreign->year < 2000
+    }
+  );
+}
+use DBICTest;
+use DBIC::SqlMakerTest;
+
+my $schema = DBICTest->init_schema();
+
+my $mccrae = $schema->resultset('Artist')
+                    ->find({ name => 'Caterwauler McCrae' });
+
+is($mccrae->cds2->count, 3, 'CDs returned from expr join');
+
+is($mccrae->cds2_pre2k->count, 2, 'CDs returned from expr w/cond');
+
+done_testing;