X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FResultSet.pm;h=ea0f2966dc12fafe46a421e24c05c59218d26bc4;hb=fc7cabbcfe26164d6d7fa2fa7901ef855c8eb38c;hp=58e9b07b00d3cbb3d51cfb304d6dfc449ccc1e82;hpb=12b79b7c35d74e69a9d385b66287058d2b4befda;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index 58e9b07..ea0f296 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -1426,8 +1426,12 @@ sub _rs_update_delete { 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) { @@ -1475,7 +1479,7 @@ sub _rs_update_delete { return $rsrc->storage->$op( $rsrc, $op eq 'update' ? $values : (), - $self->{cond}, + $cond, ); } } @@ -1711,6 +1715,19 @@ sub populate { } } + ## 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, @@ -1852,15 +1869,39 @@ sub new_result { $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" @@ -1874,24 +1915,22 @@ sub new_result { # 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 @@ -2816,6 +2855,22 @@ sub _resolved_attrs { } 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; + } + } } }