my $rsrc = $self->result_source;
$attrs ||= $self->_resolved_attrs;
- # only take pieces we need for a simple count
- my $tmp_attrs = { map
- { $_ => $attrs->{$_} }
- qw/ alias from where bind join /
- };
+ my $tmp_attrs = { %$attrs };
+ # take off any limits, record_filter is cdbi, and no point of ordering nor locking a count
+ delete @{$tmp_attrs}{qw/rows offset order_by record_filter for/};
# overwrite the selector (supplied by the storage)
- $tmp_attrs->{select} = $rsrc->storage->_count_select ($rsrc, $tmp_attrs);
+ $tmp_attrs->{select} = $rsrc->storage->_count_select ($rsrc, $attrs);
$tmp_attrs->{as} = 'count';
my $tmp_rs = $rsrc->resultset_class->new($rsrc, $tmp_attrs)->get_column ('count');
my $rsrc = $self->result_source;
$attrs ||= $self->_resolved_attrs;
- my $sub_attrs = { map
- { $_ => $attrs->{$_} }
- qw/ alias from where bind join group_by having rows offset /
- };
+ my $sub_attrs = { %$attrs };
+ # extra selectors do not go in the subquery and there is no point of ordering it, nor locking it
+ delete @{$sub_attrs}{qw/collapse select _prefetch_select as order_by for/};
# if we multi-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
# Calculate subquery selector
if (my $g = $sub_attrs->{group_by}) {
+ my $sql_maker = $rsrc->storage->sql_maker;
+
# necessary as the group_by may refer to aliased functions
my $sel_index;
for my $sel (@{$attrs->{select}}) {
}
for my $g_part (@$g) {
- push @{$sub_attrs->{select}}, $sel_index->{$g_part} || $g_part;
+ my $colpiece = $sel_index->{$g_part} || $g_part;
+
+ # disqualify join-based group_by's. Arcane but possible query
+ # also horrible horrible hack to alias a column (not a func.)
+ # (probably need to introduce SQLA syntax)
+ if ($colpiece =~ /\./ && $colpiece !~ /^$attrs->{alias}\./) {
+ my $as = $colpiece;
+ $as =~ s/\./__/;
+ $colpiece = \ sprintf ('%s AS %s', map { $sql_maker->_quote ($_) } ($colpiece, $as) );
+ }
+ push @{$sub_attrs->{select}}, $colpiece;
}
}
else {
->new ($rsrc, $sub_attrs)
->as_subselect_rs
->search ({}, { columns => { count => $rsrc->storage->_count_select ($rsrc, $attrs) } })
- -> get_column ('count');
+ ->get_column ('count');
}
sub _bool {
);
Example of creating a new row and also creating a row in a related
-C<belongs_to>resultset. Note Hashref.
+C<belongs_to> resultset. Note Hashref.
$cd_rs->create({
title=>"Music for Silly Walks",
# (the select/as attrs were deleted in the beginning), we need to flip all
# left joins to inner, so we get the expected results
# read the comment on top of the actual function to see what this does
- $attrs->{from} = $rsrc->schema->storage->_straight_join_to_node ($attrs->{from}, $alias);
+ $attrs->{from} = $rsrc->schema->storage->_inner_join_to_node ($attrs->{from}, $alias);
#XXX - temp fix for result_class bug. There likely is a more elegant fix -groditi
carp ("Useless use of distinct on a grouped resultset ('distinct' is ignored when a 'group_by' is present)");
}
else {
- $attrs->{group_by} = [ grep { !ref($_) || (ref($_) ne 'HASH') } @{$attrs->{select}} ];
+ my $storage = $self->result_source->schema->storage;
+ my $rs_column_list = $storage->_resolve_column_info ($attrs->{from});
+ my $group_spec = $attrs->{group_by} = [];
+ my %group_index;
+
+ for (@{$attrs->{select}}) {
+ if (! ref($_) or ref ($_) ne 'HASH' ) {
+ push @$group_spec, $_;
+ $group_index{$_}++;
+ if ($rs_column_list->{$_} and $_ !~ /\./ ) {
+ # add a fully qualified version as well
+ $group_index{"$rs_column_list->{$_}{-source_alias}.$_"}++;
+ }
+ }
+ }
# 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;
+ for my $chunk ($storage->_parse_order_by($attrs->{order_by})) {
- my $rs_column_list = $storage->_resolve_column_info ($attrs->{from});
+ # only consider real columns (for functions the user got to do an explicit group_by)
+ my $colinfo = $rs_column_list->{$chunk}
+ or next;
- for my $chunk ($storage->_parse_order_by($attrs->{order_by})) {
- if ($rs_column_list->{$chunk} && not $already_grouped{$chunk}++) {
- push @{$attrs->{group_by}}, $chunk;
- }
+ $chunk = "$colinfo->{-source_alias}.$chunk" if $chunk !~ /\./;
+ push @$group_spec, $chunk unless $group_index{$chunk}++;
}
}
}