my $rsrc = $self->result_source;
+ # if a condition exists we need to strip all table qualifiers
+ # if this is not possible we'll force a subquery below
+ 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 = $self->_has_resolved_attr (qw/row offset/);
+ my $needs_subq = (not defined $cond) || $self->_has_resolved_attr(qw/row offset/);
if ($needs_group_by_subq or $needs_subq) {
return $rsrc->storage->$op(
$rsrc,
$op eq 'update' ? $values : (),
- $self->{cond},
+ $cond,
);
}
}
}
}
+ ## merge with the conditions from $self (inherited conditions)
+ my ($inherited_cond) = $self->_merge_with_cond({});
+ delete @{$inherited_cond}{@names};
+ my @inherited_names = keys %$inherited_cond;
+ my @values;
+ foreach my $row (@$data) {
+ my %row_data;
+ @row_data{@names} = @{$row}{@names};
+ my ($merged_cond) = $self->_merge_with_cond(\%row_data);
+ push @values, [ @{$merged_cond}{@names, @inherited_names} ];
+ }
+ push @names, @inherited_names;
+
## do bulk insert on current row
$self->result_source->storage->insert_bulk(
$self->result_source,
$self->throw_exception( "new_result needs a hash" )
unless (ref $values eq 'HASH');
- my %new;
+ my ($merged_cond, $from_resultset) = $self->_merge_with_cond($values);
+
+ my %new = (
+ %$merged_cond,
+ @$from_resultset
+ ? (-from_resultset => $from_resultset)
+ : (),
+ -source_handle => $self->_source_handle,
+ -result_source => $self->result_source, # DO NOT REMOVE THIS, REQUIRED
+ );
+
+ return $self->result_class->new(\%new);
+}
+
+# _merge_with_cond
+#
+# Merges $values (a hashref) with the condition in the resultset and returns
+# the resulting hashref and an arrayref that contains the keys that are coming
+# from related resultsets.
+
+sub _merge_with_cond {
+ my ($self, $values) = @_;
+
+ my (%merged_cond, @from_resultset);
+
my $alias = $self->{attrs}{alias};
if (
defined $self->{cond}
&& $self->{cond} eq $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION
) {
- %new = %{ $self->{attrs}{related_objects} || {} }; # nothing might have been inserted yet
- $new{-from_resultset} = [ keys %new ] if keys %new;
+ %merged_cond = %{ $self->{attrs}{related_objects} || {} }; # nothing might have been inserted yet
+ @from_resultset = keys %merged_cond;
} else {
$self->throw_exception(
"Can't abstract implicit construct, condition not a hash"
# precendence must be given to passed values over values inherited from
# the cond, so the order here is important.
- my %implied = %{$self->_remove_alias($collapsed_cond, $alias)};
- while( my($col,$value) = each %implied ){
- if(ref($value) eq 'HASH' && keys(%$value) && (keys %$value)[0] eq '='){
- $new{$col} = $value->{'='};
+ my %implied = %{$self->_remove_alias($collapsed_cond, $alias)};
+ while ( my($col, $value) = each %implied ) {
+ if (ref($value) eq 'HASH' && keys(%$value) && (keys %$value)[0] eq '=') {
+ $merged_cond{$col} = $value->{'='};
next;
}
- $new{$col} = $value if $self->_is_deterministic_value($value);
+ $merged_cond{$col} = $value if $self->_is_deterministic_value($value);
}
}
- %new = (
- %new,
+ %merged_cond = (
+ %merged_cond,
%{ $self->_remove_alias($values, $alias) },
- -source_handle => $self->_source_handle,
- -result_source => $self->result_source, # DO NOT REMOVE THIS, REQUIRED
);
- return $self->result_class->new(\%new);
+ return (\%merged_cond, \@from_resultset);
}
# _is_deterministic_value
}
else {
$attrs->{group_by} = [ grep { !ref($_) || (ref($_) ne 'HASH') } @{$attrs->{select}} ];
+
+ # add any order_by parts that are not already present in the group_by
+ # we need to be careful not to add any named functions/aggregates
+ # i.e. select => [ ... { count => 'foo', -as 'foocount' } ... ]
+ my %already_grouped = map { $_ => 1 } (@{$attrs->{group_by}});
+
+ my $storage = $self->result_source->schema->storage;
+ my $rs_column_list = $storage->_resolve_column_info ($attrs->{from});
+ my @chunks = $storage->sql_maker->_order_by_chunks ($attrs->{order_by});
+
+ for my $chunk (map { ref $_ ? @$_ : $_ } (@chunks) ) {
+ $chunk =~ s/\s+ (?: ASC|DESC ) \s* $//ix;
+ if ($rs_column_list->{$chunk} && not $already_grouped{$chunk}++) {
+ push @{$attrs->{group_by}}, $chunk;
+ }
+ }
}
}