use warnings;
use Carp::Clan qw/^DBIx::Class/;
use DBI;
-use DBIx::Class::SQLAHacks;
use DBIx::Class::Storage::DBI::Cursor;
use DBIx::Class::Storage::Statistics;
use Scalar::Util();
my ($self) = @_;
unless ($self->_sql_maker) {
my $sql_maker_class = $self->sql_maker_class;
+ $self->ensure_class_loaded ($sql_maker_class);
$self->_sql_maker($sql_maker_class->new( $self->_sql_maker_args ));
}
return $self->_sql_maker;
# Genarating a single PK column subquery is trivial and supported
# by all RDBMS. However if we have a multicolumn PK, things get ugly.
# Look at _multipk_update_delete()
-sub subq_update_delete {
+sub _subq_update_delete {
my $self = shift;
my ($rs, $op, $values) = @_;
sub _select_args {
my ($self, $ident, $select, $condition, $attrs) = @_;
- my $order = $attrs->{order_by};
my $for = delete $attrs->{for};
my $sql_maker = $self->sql_maker;
$sql_maker->{for} = $for;
- my @in_order_attrs = qw/group_by having _virtual_order_by/;
- if (List::Util::first { exists $attrs->{$_} } (@in_order_attrs) ) {
- $order = {
- ($order
- ? (order_by => $order)
- : ()
- ),
- ( map { $_ => $attrs->{$_} } (@in_order_attrs) )
- };
- }
+ my $order = { map
+ { $attrs->{$_} ? ( $_ => $attrs->{$_} ) : () }
+ (qw/order_by group_by having _virtual_order_by/ )
+ };
+
my $bind_attrs = {};
my $tmp_attrs = { %$attrs };
- # take off any column specs, any pagers, record_filter is cdbi, and no point of ordering a count
- delete $tmp_attrs->{$_} for (qw/columns +columns select +select as +as rows offset page pager order_by record_filter/);
+ # take off any pagers, record_filter is cdbi, and no point of ordering a count
+ delete $tmp_attrs->{$_} for (qw/select as rows offset page order_by record_filter/);
+ # overwrite the selector
$tmp_attrs->{select} = { count => '*' };
- $tmp_attrs->{as} = [qw/count/];
my $tmp_rs = $source->resultset_class->new($source, $tmp_attrs);
my ($count) = $tmp_rs->cursor->next;
my $sub_attrs = { %$attrs };
# these can not go in the subquery, and there is no point of ordering it
- delete $sub_attrs->{$_} for qw/prefetch collapse select +select as +as columns +columns order_by/;
+ delete $sub_attrs->{$_} for qw/prefetch collapse 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
# simply deleting group_by suffices, as the code below will re-fill it
delete $sub_attrs->{group_by};
}
- $sub_attrs->{columns} = $sub_attrs->{group_by} ||= [ map { "$attrs->{alias}.$_" } ($source->primary_columns) ];
+ $sub_attrs->{group_by} ||= [ map { "$attrs->{alias}.$_" } ($source->primary_columns) ];
+ $sub_attrs->{select} = $self->_grouped_count_select ($source, $sub_attrs);
$attrs->{from} = [{
count_subq => $source->resultset_class->new ($source, $sub_attrs )->as_query
}];
# the subquery replaces this
- delete $attrs->{$_} for qw/where bind prefetch collapse distinct group_by having having_bind rows offset page pager/;
+ delete $attrs->{$_} for qw/where bind prefetch collapse group_by having having_bind rows offset page pager/;
return $self->count ($source, $attrs);
}
+#
+# Returns a SELECT to go with a supplied GROUP BY
+# (caled by count_grouped so a group_by is present)
+# Most databases expect them to match, but some
+# choke in various ways.
+#
+sub _grouped_count_select {
+ my ($self, $source, $rs_args) = @_;
+ return $rs_args->{group_by};
+}
+
sub source_bind_attributes {
my ($self, $source) = @_;