X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FResultSet.pm;h=642187506defddbf9a8126a479d17a511b065be9;hb=37b17a93efef4652db90e299b247e55ab1145b0b;hp=4f7dd00e346115ea6c7995a52985a7c287cc515c;hpb=9c3018b6b589a8250b75a3db451a5baac9c6c3df;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index 4f7dd00..6421875 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -1264,10 +1264,10 @@ sub _count_subq_rs { my $sub_attrs = { %$attrs }; # 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/; + delete $sub_attrs->{$_} for qw/collapse select _prefetch_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 + # if we prefetch, we group_by primary keys only as this is what we would get out + # of the rs via ->next/->all. We DO WANT to clobber old group_by regardless if ( keys %{$attrs->{collapse}} ) { $sub_attrs->{group_by} = [ map { "$attrs->{alias}.$_" } ($rsrc->primary_columns) ] } @@ -1279,8 +1279,15 @@ sub _count_subq_rs { $sub_attrs->{from}, $sub_attrs->{alias} ); + # this is so that ordering can be thrown away in things like Top limit + $sub_attrs->{-for_count_only} = 1; + + my $sub_rs = $rsrc->resultset_class->new ($rsrc, $sub_attrs); + $attrs->{from} = [{ - count_subq => $rsrc->resultset_class->new ($rsrc, $sub_attrs )->as_query + -alias => 'count_subq', + -source_handle => $rsrc->handle, + count_subq => $sub_rs->as_query, }]; # the subquery replaces this @@ -1308,9 +1315,12 @@ sub _count_subq_rs { sub _switch_to_inner_join_if_needed { my ($self, $from, $alias) = @_; + # subqueries and other oddness is naturally not supported return $from if ( ref $from ne 'ARRAY' || + @$from <= 1 + || ref $from->[0] ne 'HASH' || ! $from->[0]{-alias} @@ -1318,10 +1328,6 @@ sub _switch_to_inner_join_if_needed { $from->[0]{-alias} eq $alias ); - # this would be the case with a subquery - we'll never find - # the target as it is not in the parseable part of {from} - return $from if @$from == 1; - my $switch_branch; JOINSCAN: for my $j (@{$from}[1 .. $#$from]) { @@ -1503,7 +1509,8 @@ sub _rs_update_delete { if (my $g = $attrs->{group_by}) { my @current_group_by = map { $_ =~ /\./ ? $_ : "$attrs->{alias}.$_" } - (ref $g eq 'ARRAY' ? @$g : $g ); + @$g + ; if ( join ("\x00", sort @current_group_by) @@ -2271,6 +2278,19 @@ Cresultset. Note Hashref. } }); +=over + +=item WARNING + +When subclassing ResultSet never attempt to override this method. Since +it is a simple shortcut for C<< $self->new_result($attrs)->insert >>, a +lot of the internals simply never call it, so your override will be +bypassed more often than not. Override either L +or L depending on how early in the +L process you need to intervene. + +=back + =cut sub create { @@ -2758,24 +2778,38 @@ sub _resolved_attrs { # build columns (as long as select isn't set) into a set of as/select hashes unless ( $attrs->{select} ) { - @colbits = map { - ( ref($_) eq 'HASH' ) - ? $_ - : { - ( - /^\Q${alias}.\E(.+)$/ - ? "$1" - : "$_" - ) - => - ( - /\./ - ? "$_" - : "${alias}.$_" - ) - } - } ( ref($attrs->{columns}) eq 'ARRAY' ) ? @{ delete $attrs->{columns}} : (delete $attrs->{columns} || $source->columns ); + + my @cols = ( ref($attrs->{columns}) eq 'ARRAY' ) + ? @{ delete $attrs->{columns}} + : ( + ( delete $attrs->{columns} ) + || + $source->storage->_order_select_columns( + $source, + [ $source->columns ], + ) + ) + ; + + @colbits = map { + ( ref($_) eq 'HASH' ) + ? $_ + : { + ( + /^\Q${alias}.\E(.+)$/ + ? "$1" + : "$_" + ) + => + ( + /\./ + ? "$_" + : "${alias}.$_" + ) + } + } @cols; } + # add the additional columns on foreach ( 'include_columns', '+columns' ) { push @colbits, map { @@ -2833,7 +2867,7 @@ sub _resolved_attrs { if ( $attrs->{join} || $attrs->{prefetch} ) { - $self->throw_exception ('join/prefetch can not be used with a literal scalarref {from}') + $self->throw_exception ('join/prefetch can not be used with a custom {from}') if ref $attrs->{from} ne 'ARRAY'; my $join = delete $attrs->{join} || {}; @@ -2857,25 +2891,23 @@ sub _resolved_attrs { ]; } - if ( $attrs->{order_by} ) { + if ( defined $attrs->{order_by} ) { $attrs->{order_by} = ( ref( $attrs->{order_by} ) eq 'ARRAY' ? [ @{ $attrs->{order_by} } ] - : [ $attrs->{order_by} ] + : [ $attrs->{order_by} || () ] ); } - if ($attrs->{group_by} and ! ref $attrs->{group_by}) { + if ($attrs->{group_by} and ref $attrs->{group_by} ne 'ARRAY') { $attrs->{group_by} = [ $attrs->{group_by} ]; } - # If the order_by is otherwise empty - we will use this for TOP limit - # emulation and the like. - # Although this is needed only if the order_by is not defined, it is - # actually cheaper to just populate this rather than properly examining - # order_by (stuf like [ {} ] and the like) - $attrs->{_virtual_order_by} = [ $self->result_source->primary_columns ]; - + # generate the distinct induced group_by early, as prefetch will be carried via a + # subquery (since a group_by is present) + if (delete $attrs->{distinct}) { + $attrs->{group_by} ||= [ grep { !ref($_) || (ref($_) ne 'HASH') } @{$attrs->{select}} ]; + } $attrs->{collapse} ||= {}; if ( my $prefetch = delete $attrs->{prefetch} ) { @@ -2888,19 +2920,16 @@ sub _resolved_attrs { my @prefetch = $source->_resolve_prefetch( $prefetch, $alias, $join_map, $prefetch_ordering, $attrs->{collapse} ); - $attrs->{prefetch_select} = [ map { $_->[0] } @prefetch ]; - push @{ $attrs->{select} }, @{$attrs->{prefetch_select}}; + # we need to somehow mark which columns came from 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 ); + push( @{$attrs->{order_by}}, @$prefetch_ordering ); $attrs->{_collapse_order_by} = \@$prefetch_ordering; } - - if (delete $attrs->{distinct}) { - $attrs->{group_by} ||= [ grep { !ref($_) || (ref($_) ne 'HASH') } @{$attrs->{select}} ]; - } - # if both page and offset are specified, produce a combined offset # even though it doesn't make much sense, this is what pre 081xx has # been doing @@ -2930,7 +2959,7 @@ sub _joinpath_aliases { for my $j (@$fromspec) { next if ref $j ne 'ARRAY'; - next if $j->[0]{-relation_chain_depth} < $cur_depth; + next if ($j->[0]{-relation_chain_depth} || 0) < $cur_depth; my $jpath = $j->[0]{-join_path}; @@ -2984,6 +3013,13 @@ sub _rollout_hash { sub _calculate_score { my ($self, $a, $b) = @_; + if (defined $a xor defined $b) { + return 0; + } + elsif (not defined $a) { + return 1; + } + if (ref $b eq 'HASH') { my ($b_key) = keys %{$b}; if (ref $a eq 'HASH') { @@ -3092,10 +3128,15 @@ These are in no particular order: =back -Which column(s) to order the results by. If a single column name, or -an arrayref of names is supplied, the argument is passed through -directly to SQL. The hashref syntax allows for connection-agnostic -specification of ordering direction: +Which column(s) to order the results by. + +[The full list of suitable values is documented in +L; the following is a summary of +common options.] + +If a single column name, or an arrayref of names is supplied, the +argument is passed through directly to SQL. The hashref syntax allows +for connection-agnostic specification of ordering direction: For descending order: @@ -3374,6 +3415,42 @@ with that artist is given below (assuming many-to-many from artists to tags): B If you specify a C attribute, the C and C