my $unique_query = $self->_build_unique_query($input_query, \@unique_cols);
$query = $self->_add_alias($unique_query, $alias);
}
+ elsif ($self->{attrs}{accessor} and $self->{attrs}{accessor} eq 'single') {
+ # This means that we got here after a merger of relationship conditions
+ # in ::Relationship::Base::search_related (the row method), and furthermore
+ # the relationship is of the 'single' type. This means that the condition
+ # provided by the relationship (already attached to $self) is sufficient,
+ # as there can be only one row in the databse that would satisfy the
+ # relationship
+ }
else {
my @unique_queries = $self->_unique_queries($input_query, $attrs);
$query = @unique_queries
}
# Run the query
- if (keys %$attrs) {
- my $rs = $self->search($query, $attrs);
- if (keys %{$rs->_resolved_attrs->{collapse}}) {
- my $row = $rs->next;
- carp "Query returned more than one row" if $rs->next;
- return $row;
- }
- else {
- return $rs->single;
- }
+ my $rs = $self->search ($query, $attrs);
+ if (keys %{$rs->_resolved_attrs->{collapse}}) {
+ my $row = $rs->next;
+ carp "Query returned more than one row" if $rs->next;
+ return $row;
}
else {
- if (keys %{$self->_resolved_attrs->{collapse}}) {
- my $rs = $self->search($query);
- my $row = $rs->next;
- carp "Query returned more than one row" if $rs->next;
- return $row;
- }
- else {
- return $self->single($query);
- }
+ return $rs->single;
}
}
my $sub_attrs = { %$attrs };
- # these can not go in the subquery, and there is no point of ordering it
- delete $sub_attrs->{$_} for qw/collapse select as order_by/;
+ # extra selectors do not go in the subquery and there is no point of ordering it
+ delete $sub_attrs->{$_} for qw/collapse prefetch_select select as order_by/;
# if we prefetch, we group_by primary keys only as this is what we would get out of the rs via ->next/->all
# clobber old group_by regardless
my @obj;
- # TODO: don't call resolve here
if (keys %{$self->_resolved_attrs->{collapse}}) {
-# if ($self->{attrs}{prefetch}) {
- # Using $self->cursor->all is really just an optimisation.
- # If we're collapsing has_many prefetches it probably makes
- # very little difference, and this is cleaner than hacking
- # _construct_object to survive the approach
+ # Using $self->cursor->all is really just an optimisation.
+ # If we're collapsing has_many prefetches it probably makes
+ # very little difference, and this is cleaner than hacking
+ # _construct_object to survive the approach
+ $self->cursor->reset;
my @row = $self->cursor->next;
while (@row) {
push(@obj, $self->_construct_object(@row));
=back
Resets the resultset's cursor, so you can iterate through the elements again.
+Implicitly resets the storage cursor, so a subsequent L</next> will trigger
+another query.
=cut
=back
$cd->cd_to_producer->find_or_create({ producer => $producer },
- { key => 'primary });
+ { key => 'primary' });
Tries to find a record based on its primary key or unique constraints; if none
is found, creates one and returns that instead.
$self->{related_resultsets} ||= {};
return $self->{related_resultsets}{$rel} ||= do {
- my $rel_obj = $self->result_source->relationship_info($rel);
+ my $rel_info = $self->result_source->relationship_info($rel);
$self->throw_exception(
"search_related: result source '" . $self->result_source->source_name .
"' has no such relationship $rel")
- unless $rel_obj;
+ unless $rel_info;
- my ($from,$seen) = $self->_resolve_from($rel);
+ my ($from,$seen) = $self->_chain_relationship($rel);
my $join_count = $seen->{$rel};
my $alias = ($join_count > 1 ? join('_', $rel, $join_count) : $rel);
# in order to properly resolve prefetch aliases (any alias
# with a relation_chain_depth less than the depth of the
# current prefetch is not considered)
-sub _resolve_from {
- my ($self, $extra_join) = @_;
+sub _chain_relationship {
+ my ($self, $rel) = @_;
my $source = $self->result_source;
my $attrs = $self->{attrs};
# ->_resolve_join as otherwise they get lost - captainL
my $merged = $self->_merge_attr( $attrs->{join}, $attrs->{prefetch} );
- push @$from, $source->_resolve_join($merged, $attrs->{alias}, $seen) if ($merged);
+ my @requested_joins = $source->_resolve_join($merged, $attrs->{alias}, $seen);
+
+ push @$from, @requested_joins;
++$seen->{-relation_chain_depth};
- push @$from, $source->_resolve_join($extra_join, $attrs->{alias}, $seen);
+ # if $self already had a join/prefetch specified on it, the requested
+ # $rel might very well be already included. What we do in this case
+ # is effectively a no-op (except that we bump up the chain_depth on
+ # the join in question so we could tell it *is* the search_related)
+ my $already_joined;
+
+ # we consider the last one thus reverse
+ for my $j (reverse @requested_joins) {
+ if ($rel eq $j->[0]{-join_path}[-1]) {
+ $j->[0]{-relation_chain_depth}++;
+ $already_joined++;
+ last;
+ }
+ }
+ unless ($already_joined) {
+ push @$from, $source->_resolve_join($rel, $attrs->{alias}, $seen);
+ }
++$seen->{-relation_chain_depth};
: [ $attrs->{order_by} ]
);
}
- else {
- $attrs->{order_by} = [];
+
+ if ($attrs->{group_by} and ! ref $attrs->{group_by}) {
+ $attrs->{group_by} = [ $attrs->{group_by} ];
}
# If the order_by is otherwise empty - we will use this for TOP limit
my @prefetch =
$source->_resolve_prefetch( $prefetch, $alias, $join_map, $prefetch_ordering, $attrs->{collapse} );
- push( @{ $attrs->{select} }, map { $_->[0] } @prefetch );
- push( @{ $attrs->{as} }, map { $_->[1] } @prefetch );
+ $attrs->{prefetch_select} = [ map { $_->[0] } @prefetch ];
+ push @{ $attrs->{select} }, @{$attrs->{prefetch_select}};
+ push @{ $attrs->{as} }, (map { $_->[1] } @prefetch);
push( @{ $attrs->{order_by} }, @$prefetch_ordering );
$attrs->{_collapse_order_by} = \@$prefetch_ordering;
identical to creating a non-pages resultset and then calling ->page($page)
on it.
-If L<rows> attribute is not specified it defualts to 10 rows per page.
+If L<rows> attribute is not specified it defaults to 10 rows per page.
When you have a paged resultset, L</count> will only return the number
of rows in the page. To get the total, use the L</pager> and call