From: Peter Rabbitson Date: Mon, 15 Sep 2014 09:39:12 +0000 (+0200) Subject: Ensure undef_on_null_fk does not affect non-introspectable custom conds X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=139e7991dd0542b926ad9cac8de3711e4c716e13;p=dbsrgits%2FDBIx-Class-Historic.git Ensure undef_on_null_fk does not affect non-introspectable custom conds --- diff --git a/lib/DBIx/Class/Relationship/Accessor.pm b/lib/DBIx/Class/Relationship/Accessor.pm index aeefa84..40deeaf 100644 --- a/lib/DBIx/Class/Relationship/Accessor.pm +++ b/lib/DBIx/Class/Relationship/Accessor.pm @@ -35,15 +35,24 @@ sub add_relationship_accessor { return $self->{_relationship_data}{%1$s}; } else { - my $rel_info = $self->result_source->relationship_info(%1$s); - my $cond = $self->result_source->_resolve_condition( - $rel_info->{cond}, %1$s, $self, %1$s + my $relcond = $self->result_source->_resolve_relationship_condition( + rel_name => %1$s, + foreign_alias => %1$s, + self_alias => 'me', + self_result_object => $self, ); - if ($rel_info->{attrs}->{undef_on_null_fk}){ - return undef unless ref($cond) eq 'HASH'; - return undef if grep { not defined $_ } values %%$cond; - } - my $val = $self->find_related( %1$s => {} ); + + return undef if ( + $relcond->{join_free_condition} + and + $relcond->{join_free_condition} ne DBIx::Class::_Util::UNRESOLVABLE_CONDITION + and + scalar grep { not defined $_ } values %%{ $relcond->{join_free_condition} || {} } + and + $self->result_source->relationship_info(%1$s)->{attrs}{undef_on_null_fk} + ); + + my $val = $self->search_related( %1$s )->single; return $val unless $val; # $val instead of undef so that null-objects can go through return $self->{_relationship_data}{%1$s} = $val; diff --git a/t/lib/DBICTest/Schema/CD.pm b/t/lib/DBICTest/Schema/CD.pm index 190f11d..1a0771b 100644 --- a/t/lib/DBICTest/Schema/CD.pm +++ b/t/lib/DBICTest/Schema/CD.pm @@ -55,6 +55,14 @@ __PACKAGE__->belongs_to( single_track => 'DBICTest::Schema::Track', { join_type => 'left'}, ); +__PACKAGE__->belongs_to( single_track_opaque => 'DBICTest::Schema::Track', + sub { + my $args = &check_customcond_args; + \ " $args->{foreign_alias}.trackid = $args->{self_alias}.single_track "; + }, + { join_type => 'left'}, +); + # add a non-left single relationship for the complex prefetch tests __PACKAGE__->belongs_to( existing_single_track => 'DBICTest::Schema::Track', { 'foreign.trackid' => 'self.single_track' }, diff --git a/t/relationship/custom_opaque.t b/t/relationship/custom_opaque.t new file mode 100644 index 0000000..1139c6a --- /dev/null +++ b/t/relationship/custom_opaque.t @@ -0,0 +1,51 @@ +use strict; +use warnings; + +use Test::More; + +use lib 't/lib'; +use DBICTest; + +my $schema = DBICTest->init_schema( no_populate => 1, quote_names => 1 ); + +$schema->resultset('CD')->create({ + title => 'Equinoxe', + year => 1978, + artist => { name => 'JMJ' }, + genre => { name => 'electro' }, + tracks => [ + { title => 'e1' }, + { title => 'e2' }, + { title => 'e3' }, + ], + single_track => { + title => 'o1', + cd => { + title => 'Oxygene', + year => 1976, + artist => { name => 'JMJ' }, + }, + }, +}); + +my $cd = $schema->resultset('CD')->search({ single_track => { '!=', undef } })->first; + +$schema->is_executed_sql_bind( + sub { is( eval{$cd->single_track_opaque->title}, 'o1', 'Found correct single track' ) }, + [ + [ + 'SELECT "me"."trackid", "me"."cd", "me"."position", "me"."title", "me"."last_updated_on", "me"."last_updated_at" + FROM cd "cd__row" + JOIN "track" "me" + ON me.trackid = cd__row.single_track + WHERE "cd__row"."cdid" = ? + ', + [ + { dbic_colname => "cd__row.cdid", sqlt_datatype => "integer" } + => 2 + ] + ], + ], +); + +done_testing;