shift->result_source->relationship_info(@_);
}
-sub resolve_condition {
- my ($self, $cond, $attrs) = @_;
- if (ref $cond eq 'HASH') {
- my %ret;
- foreach my $key (keys %$cond) {
- my $val = $cond->{$key};
- if (ref $val) {
- $self->throw("Can't handle this yet :(");
- } else {
- $ret{$self->_cond_key($attrs => $key)}
- = $self->_cond_value($attrs => $key => $val);
- }
- }
- return \%ret;
- } else {
- $self->throw("Can't handle this yet :(");
- }
-}
-
-sub _cond_key {
- my ($self, $attrs, $key, $alias) = @_;
- my $action = $attrs->{_action} || '';
- if ($action eq 'convert') {
- unless ($key =~ s/^foreign\.//) {
- $self->throw("Unable to convert relationship to WHERE clause: invalid key ${key}");
- }
- if (defined (my $alias = $attrs->{_aliases}{foreign})) {
- return "${alias}.${key}";
- } else {
- return $key;
- }
- } elsif ($action eq 'join') {
- return $key unless $key =~ /\./;
- my ($type, $field) = split(/\./, $key);
- if (my $alias = $attrs->{_aliases}{$type}) {
- my $class = $attrs->{_classes}{$alias};
- $self->throw("Unknown column $field on $class as $alias")
- unless $class->has_column($field);
- return join('.', $alias, $field);
- } else {
- $self->throw( "Unable to resolve type ${type}: only have aliases for ".
- join(', ', keys %{$attrs->{_aliases} || {}}) );
- }
- }
- return $self->next::method($attrs, $key);
-}
-
-sub _cond_value {
- my ($self, $attrs, $key, $value) = @_;
- my $action = $attrs->{_action} || '';
- if ($action eq 'convert') {
- unless ($value =~ s/^self\.//) {
- $self->throw( "Unable to convert relationship to WHERE clause: invalid value ${value}" );
- }
- unless ($self->has_column($value)) {
- $self->throw( "Unable to convert relationship to WHERE clause: no such accessor ${value}" );
- }
- return $self->get_column($value);
- } elsif ($action eq 'join') {
- return $key unless $key =~ /\./;
- my ($type, $field) = split(/\./, $value);
- if (my $alias = $attrs->{_aliases}{$type}) {
- my $class = $attrs->{_classes}{$alias};
- $self->throw("Unknown column $field on $class as $alias")
- unless $class->has_column($field);
- return join('.', $alias, $field);
- } else {
- $self->throw( "Unable to resolve type ${type}: only have aliases for ".
- join(', ', keys %{$attrs->{_aliases} || {}}) );
- }
- }
-
- return $self->next::method($attrs, $key, $value)
-}
-
=head2 search_related
My::Table->search_related('relname', $cond, $attrs);
sub search_related {
my $self = shift;
+ die "Can't call *_related as class methods" unless ref $self;
my $rel = shift;
my $attrs = { };
if (@_ > 1 && ref $_[$#_] eq 'HASH') {
$self->throw( "Invalid query: @_" ) if (@_ > 1 && (@_ % 2 == 1));
my $query = ((@_ > 1) ? {@_} : shift);
- $attrs->{_action} = 'convert'; # shouldn't we resolve the cond to something
- # to merge into the AST really?
- my ($cond) = $self->resolve_condition($rel_obj->{cond}, $attrs);
+ my ($cond) = $self->result_source->resolve_condition($rel_obj->{cond}, $rel, $self);
$query = ($query ? { '-and' => [ $cond, $query ] } : $cond);
- #use Data::Dumper; warn Dumper($query);
+ #use Data::Dumper; warn Dumper($cond);
#warn $rel_obj->{class}." $meth $cond ".join(', ', @{$attrs->{bind}||[]});
- delete $attrs->{_action};
- return $self->result_source->schema->resultset($rel_obj->{class}
- )->search($query, $attrs);
+ return $self->result_source->related_source($rel
+ )->resultset->search($query, $attrs);
}
=head2 count_related
=cut
sub create_related {
- my $class = shift;
+ my $self = shift;
my $rel = shift;
- return $class->search_related($rel)->create(@_);
+ return $self->search_related($rel)->create(@_);
}
=head2 new_related
return $self->resultset_class->new($self);
}
-=head2 has_column
-
+=head2 has_column
+
if ($obj->has_column($col)) { ... }
Returns 1 if the source has a column of this name, 0 otherwise.
} elsif (ref $join) {
die("No idea how to resolve join reftype ".ref $join);
} else {
- die("No such relationship ${join}") unless $self->has_relationship($join);
- my $type = $self->relationship_info($join)->{attrs}{join_type} || '';
+ my $rel_info = $self->relationship_info($join);
+ die("No such relationship ${join}") unless $rel_info;
+ my $type = $rel_info->{attrs}{join_type} || '';
return [ { $join => $self->related_source($join)->from,
-join_type => $type },
- $self->resolve_condition($join, $alias) ];
+ $self->resolve_condition($rel_info->{cond}, $join, $alias) ];
}
}
-=head2 resolve_condition($rel, $alias|$object)
+=head2 resolve_condition($cond, $rel, $alias|$object)
-Returns the conditional for the specified relationship. If given an alias,
+Resolves the passed condition to a concrete query fragment. If given an alias,
returns a join condition; if given an object, inverts that object to produce
a related conditional from that object.
=cut
sub resolve_condition {
- my ($self, $rel, $for) = @_;
- my $cond = $self->relationship_info($rel)->{cond};
+ my ($self, $cond, $rel, $for) = @_;
#warn %$cond;
if (ref $cond eq 'HASH') {
my %ret;
while (my ($k, $v) = each %{$cond}) {
# XXX should probably check these are valid columns
- $k =~ s/^foreign\./${rel}./ || die "Invalid rel cond key ${k}";
+ $k =~ s/^foreign\.// || die "Invalid rel cond key ${k}";
+ $v =~ s/^self\.// || die "Invalid rel cond val ${v}";
if (ref $for) { # Object
- die "Invalid ref cond val ${v}" unless $v =~ m/^self\.(.*)$/;
- $ret{$k} = $for->$1;
+ #warn "$self $k $for $v";
+ $ret{$k} = $for->get_column($v);
+ #warn %ret;
} else {
- $v =~ s/^self\./${for}./ || die "Invalid rel cond val ${v}";
+ $ret{"${rel}.${k}"} = "${for}.${v}";
}
- $ret{$k} = $v;
}
return \%ret;
} else {