use DBIx::Class::ResultSourceHandle;
use DBIx::Class::Carp;
-use DBIx::Class::_Util 'is_literal_value';
+use DBIx::Class::_Util qw(is_literal_value UNRESOLVABLE_CONDITION);
use Devel::GlobalDestruction;
use Try::Tiny;
use List::Util 'first';
=back
- my @relnames = $source->relationships();
+ my @rel_names = $source->relationships();
Returns all relationship names for this source.
else {
$res_args[$_] ||= {};
+ # hate everywhere - have to pass in as a plain hash
+ # pretending to be an object at least for now
$self->throw_exception("Unsupported object-like structure encountered: $res_args[$_]")
unless ref $res_args[$_] eq 'HASH';
-
- # hate everywhere
- $res_args[$_] = $self->relationship_info($rel_name)->{source}->result_class->new($res_args[$_]);
}
}
my $args = {
condition => $cond,
- rel_name => $rel_name,
- $is_objlike[1] ? ( self_alias => $res_args[0], foreign_alias => 'me', self_resultobj => $res_args[1] )
- : $is_objlike[0] ? ( self_alias => 'me', foreign_alias => $res_args[1], foreign_resultobj => $res_args[0] )
- : ( self_alias => $res_args[1], foreign_alias => $res_args[0] )
+
+ # where-is-waldo block guesses relname, then further down we override it if available
+ (
+ $is_objlike[1] ? ( rel_name => $res_args[0], self_alias => $res_args[0], foreign_alias => 'me', self_resultobj => $res_args[1] )
+ : $is_objlike[0] ? ( rel_name => $res_args[1], self_alias => 'me', foreign_alias => $res_args[1], foreign_resultobj => $res_args[0] )
+ : ( rel_name => $res_args[0], self_alias => $res_args[1], foreign_alias => $res_args[0] )
+ ),
+
+ ( $rel_name ? ( rel_name => $rel_name ) : () ),
};
#######################
return wantarray ? @res : $res[0];
}
-our $UNRESOLVABLE_CONDITION = \ '1 = 0';
+# Keep this indefinitely. There is evidence of both CPAN and
+# darkpan using it, and there isn't much harm in an extra var
+# anyway.
+our $UNRESOLVABLE_CONDITION = UNRESOLVABLE_CONDITION;
+# YES I KNOW THIS IS EVIL
+# it is there to save darkpan from themselves, since internally
+# we are moving to a constant
+Internals::SvREADONLY($UNRESOLVABLE_CONDITION => 1);
# Resolves the passed condition to a concrete query fragment and a flag
# indicating whether this is a cross-table condition. Also an optional
self_resultsource => $self,
self_alias => $args->{self_alias},
foreign_alias => $args->{foreign_alias},
- self_resultobj => defined $args->{self_resultobj} ? $args->{self_resultobj} : undef,
+ self_resultobj => $args->{self_resultobj},
+ foreign_resultobj => $args->{foreign_resultobj},
};
# legacy - never remove these!!!
$cref_args->{foreign_relname} = $cref_args->{rel_name};
$cref_args->{self_rowobj} = $cref_args->{self_resultobj};
- my ($crosstable_cond, $joinfree_cond) = $args->{condition}->($cref_args);
+ my ($crosstable_cond, $joinfree_cond, @extra) = $args->{condition}->($cref_args);
+
+ # FIXME sanity check
+ carp_unique('A custom condition coderef can return at most 2 conditions: extra return values discarded')
+ if @extra;
my @nonvalue_cols;
if ($joinfree_cond) {
+ my ($joinfree_alias, $joinfree_source);
+ if (defined $args->{self_resultobj}) {
+ $joinfree_alias = $args->{foreign_alias};
+ $joinfree_source = $self->related_source($args->{rel_name});
+ }
+ elsif (defined $args->{foreign_resultobj}) {
+ $joinfree_alias = $args->{self_alias};
+ $joinfree_source = $self;
+ }
+
# FIXME sanity check until things stabilize, remove at some point
$self->throw_exception (
"A join-free condition returned for relationship '$args->{rel_name}' without a result object to chain from"
- ) unless defined $args->{self_resultobj};
+ ) unless $joinfree_alias;
- my $foreign_src_fq_col_list = { map { ( "$args->{foreign_alias}.$_" => 1 ) } $self->related_source($args->{rel_name})->columns };
+ my $fq_col_list = { map { ( "$joinfree_alias.$_" => 1 ) } $joinfree_source->columns };
# FIXME another sanity check
if (
ref $joinfree_cond ne 'HASH'
or
- grep { ! $foreign_src_fq_col_list->{$_} } keys %$joinfree_cond
+ grep { ! $fq_col_list->{$_} } keys %$joinfree_cond
) {
$self->throw_exception (
"The join-free condition returned for relationship '$args->{rel_name}' must be a hash "
- .'reference with all keys being fully qualified column names of the foreign source'
+ .'reference with all keys being fully qualified column names of the corresponding source'
);
}
@{ $self->schema->storage->_extract_fixed_condition_columns($joinfree_cond) }
};
@nonvalue_cols = map
- { $_ =~ /^\Q$args->{foreign_alias}.\E(.+)/ }
+ { $_ =~ /^\Q$joinfree_alias.\E(.+)/ }
grep
{ ! $joinfree_cond_equality_columns->{$_} }
keys %$joinfree_cond;
;
for my $i (0..$#$obj_cols) {
- if (defined $args->{self_resultobj} and ! $obj->has_column_loaded($obj_cols->[$i])) {
+
+ # FIXME - temp shim
+ if (! blessed $obj) {
+ $cond->{"$plain_alias.$plain_cols->[$i]"} = $obj->{$obj_cols->[$i]};
+ }
+ elsif (
+ defined $args->{self_resultobj}
+ and
+ ! $obj->has_column_loaded($obj_cols->[$i])
+ ) {
$self->throw_exception(sprintf
"Unable to resolve relationship '%s' from object '%s': column '%s' not "
$obj_cols->[$i],
) if $obj->in_storage;
- return $UNRESOLVABLE_CONDITION;
+ return UNRESOLVABLE_CONDITION;
}
else {
$cond->{"$plain_alias.$plain_cols->[$i]"} = $obj->get_column($obj_cols->[$i]);
}
elsif (ref $args->{condition} eq 'ARRAY') {
if (@{$args->{condition}} == 0) {
- return $UNRESOLVABLE_CONDITION;
+ return UNRESOLVABLE_CONDITION;
}
elsif (@{$args->{condition}} == 1) {
return $self->_resolve_relationship_condition({