my $cond = $rsrc->schema->storage->_strip_cond_qualifiers ($self->{cond});
my $needs_group_by_subq = $self->_has_resolved_attr (qw/collapse group_by -join/);
- my $needs_subq = (not defined $cond) || $self->_has_resolved_attr(qw/row offset/);
+ my $needs_subq = $needs_group_by_subq || (not defined $cond) || $self->_has_resolved_attr(qw/row offset/);
if ($needs_group_by_subq or $needs_subq) {
=cut
sub populate {
- my $self = shift @_;
- my $data = ref $_[0][0] eq 'HASH'
- ? $_[0] : ref $_[0][0] eq 'ARRAY' ? $self->_normalize_populate_args($_[0]) :
- $self->throw_exception('Populate expects an arrayref of hashes or arrayref of arrayrefs');
+ my $self = shift;
+
+ # cruft placed in standalone method
+ my $data = $self->_normalize_populate_args(@_);
if(defined wantarray) {
my @created;
}
}
-=head2 _normalize_populate_args ($args)
-
-Private method used by L</populate> to normalize its incoming arguments. Factored
-out in case you want to subclass and accept new argument structures to the
-L</populate> method.
-
-=cut
+# populate() argumnets went over several incarnations
+# What we ultimately support is AoH
sub _normalize_populate_args {
- my ($self, $data) = @_;
- my @names = @{shift(@$data)};
- my @results_to_create;
- foreach my $datum (@$data) {
- my %result_to_create;
- foreach my $index (0..$#names) {
- $result_to_create{$names[$index]} = $$datum[$index];
+ my ($self, $arg) = @_;
+
+ if (ref $arg eq 'ARRAY') {
+ if (ref $arg->[0] eq 'HASH') {
+ return $arg;
+ }
+ elsif (ref $arg->[0] eq 'ARRAY') {
+ my @ret;
+ my @colnames = @{$arg->[0]};
+ foreach my $values (@{$arg}[1 .. $#$arg]) {
+ push @ret, { map { $colnames[$_] => $values->[$_] } (0 .. $#colnames) };
+ }
+ return \@ret;
}
- push @results_to_create, \%result_to_create;
}
- return \@results_to_create;
+
+ $self->throw_exception('Populate expects an arrayref of hashrefs or arrayref of arrayrefs');
}
=head2 pager
return \%unaliased;
}
-=head2 as_query (EXPERIMENTAL)
+=head2 as_query
=over 4
This is generally used as the RHS for a subquery.
-B<NOTE>: This feature is still experimental.
-
=cut
sub as_query {
"' has no such relationship $rel")
unless $rel_info;
- my ($from,$seen,$attrs) = $self->_chain_relationship($rel);
+ my $attrs = $self->_chain_relationship($rel);
- my $join_count = $seen->{$rel};
- my $alias = ($join_count > 1 ? join('_', $rel, $join_count) : $rel);
+ my $join_count = $attrs->{seen_join}{$rel};
+
+ my $alias = $self->result_source->storage
+ ->relname_to_table_alias($rel, $join_count);
#XXX - temp fix for result_class bug. There likely is a more elegant fix -groditi
delete @{$attrs}{qw(result_class alias)};
->search_rs(
undef, {
%$attrs,
- join => undef,
- prefetch => undef,
- select => undef,
- as => undef,
- where => $self->{cond},
- seen_join => $seen,
- from => $from,
+ where => $attrs->{where},
});
};
$new->set_cache($new_cache) if $new_cache;
my $source = $self->result_source;
my $attrs = { %{$self->{attrs}||{}} };
+ # we need to take the prefetch the attrs into account before we
+ # ->_resolve_join as otherwise they get lost - captainL
+ my $join = $self->_merge_attr( $attrs->{join}, $attrs->{prefetch} );
+
+ delete @{$attrs}{qw/join prefetch collapse distinct select as columns +select +as +columns/};
+
+ my $seen = { %{ (delete $attrs->{seen_join}) || {} } };
+
my $from;
- my @force_subq_attrs = qw/offset rows/;
+ my @force_subq_attrs = qw/offset rows group_by having/;
if (
($attrs->{from} && ref $attrs->{from} ne 'ARRAY')
||
$self->_has_resolved_attr (@force_subq_attrs)
) {
+ # Nuke the prefetch (if any) before the new $rs attrs
+ # are resolved (prefetch is useless - we are wrapping
+ # a subquery anyway).
+ my $rs_copy = $self->search;
+ $rs_copy->{attrs}{join} = $self->_merge_attr (
+ $rs_copy->{attrs}{join},
+ delete $rs_copy->{attrs}{prefetch},
+ );
+
$from = [{
-source_handle => $source->handle,
-alias => $attrs->{alias},
- $attrs->{alias} => $self->as_query,
+ $attrs->{alias} => $rs_copy->as_query,
}];
- delete @{$attrs}{@force_subq_attrs};
+ delete @{$attrs}{@force_subq_attrs, 'where'};
+ $seen->{-relation_chain_depth} = 0;
}
elsif ($attrs->{from}) { #shallow copy suffices
$from = [ @{$attrs->{from}} ];
}];
}
- my $seen = { %{$attrs->{seen_join} || {} } };
- my $jpath = ($attrs->{seen_join} && keys %{$attrs->{seen_join}})
+ my $jpath = ($seen->{-relation_chain_depth})
? $from->[-1][0]{-join_path}
: [];
- # we need to take the prefetch the attrs into account before we
- # ->_resolve_join as otherwise they get lost - captainL
- my $merged = $self->_merge_attr( $attrs->{join}, $attrs->{prefetch} );
-
my @requested_joins = $source->_resolve_join(
- $merged,
+ $join,
$attrs->{alias},
$seen,
$jpath,
$seen->{-relation_chain_depth}++;
- return ($from,$seen,$attrs);
+ return {%$attrs, from => $from, seen_join => $seen};
}
# too many times we have to do $attrs = { %{$self->_resolved_attrs} }