dreel has asked for the wisdom of the Perl Monks concerning the following question:

I want to create a paged content and i'm using DBIx for it. When I write a query without paging - it works fine. SQL without paging:
$c->stash->{routes} = [$c->model('QDB::Route')->search( { 'n_1.net_id' => $c->stash->{net_id}, }, { alias => 'rt', # alias columns in accordance with "from" from => [ { rt => 'vi_route' }, [ { n_1 => 'vi_nodes', -join_type => 'inner' }, { 'rt.route_beg' => 'n_1.node_id', 'rt.net_id' => 'n_1.net_id' } ], [ { n_2 => 'vi_nodes', -join_type => 'inner' }, { 'rt.route_end' => 'n_2.node_id', 'rt.net_id' => 'n_2.net_id' } ], ], 'select' => [ 'rt.route_beg', 'rt.route_end', \'n_1.node_name AS node_name_beg', \'n_2.node_name AS node_name_end', \'COUNT(rt.route_beg) as grp_count', ], 'as' => [ qw/ route_beg route_end node_name_beg node_nam +e_end route_grp_count / ], 'group_by' => [qw/ rt.route_beg rt.route_end node_name_beg nod +e_name_end /], }, )];
Equivalent SQL is normal:
SELECT rt.route_beg, rt.route_end, n_1.node_name AS node_name_beg, n_2.node_name AS node_name_end, COUNT(rt.route_beg) as grp_count FROM vi_route rt INNER JOIN vi_nodes n_1 ON ( rt.net_id = n_1.net_id AND rt.route_beg = n_1.node_id ) INNER JOIN vi_nodes n_2 ON ( rt.net_id = n_2.net_id AND rt.route_end = n_2.node_id ) WHERE ( n_1.net_id = ? ) GROUP BY rt.route_beg, rt.route_end, n_1.node_name, n_2.node_name ORDER BY node_name_beg: 'param_value'
But if I add few lines:
page => 1, # page to return (defaults to 1) rows => 10, # number of results per page
It becomes wrong and throw exception( Because sql query becomes bad. Equivalent SQL becomes bad:
SELECT * FROM ( SELECT TOP 10 * FROM ( SELECT TOP 10 rt.route_beg, rt.route_end, n_1.node_name AS no +de_name_beg, n_2.node_name AS node_name_end, COUNT(rt.route_beg) as g +rp_count FROM vi_route rt INNER JOIN vi_nodes n_1 ON ( rt.net_id = n_1.net_id AND rt.route_beg = n_1.node_id ) INNER JOI +N vi_nodes n_2 ON ( rt.net_id = n_2.net_id AND rt.route_end = n_2.node_id ) WHERE ( n_1.net_id = ? ) ORDER BY node_name_beg ASC ) AS foo #-- There must be GROUP BY CLAUSE but it's missed! --# ORDER BY node_name_beg DESC ) AS bar ORDER BY node_name_beg ASC : 'param_value'
DBIC missing group_by clause when generates sql for paged result. And sql server return error because aggregate function COUNT(rt.route_beg) not included in ORDER BY or GROUP BY clause. ======= If you think it was discussed in mail-lists - it's wrong! Or may be google search is broken?

Replies are listed 'Best First'.
Re: dbix-class paging troubles - GROUP_BY
by zby (Vicar) on Sep 13, 2007 at 12:02 UTC
    Do you really need to use the 'from' attribute? I think it should be achievable with the oridinary 'join' attribute. You can also add join_type into the relationship definition if you need it (see DBIx::Class::Relationship::Base) - but I believe INNER join is used by default so you should not. Please accept my apologies if you've already tried that.
      Ok i'll try it now, but it seems to me I have already try it with fault. But i have double link between tables it's 'rt.route_beg' => 'n_1.node_id', 'rt.net_id' => 'n_1.net_id' and 'rt.route_end' => 'n_2.node_id', 'rt.net_id' => 'n_2.net_id'
      $c->stash->{routes} = [$c->model('QDB::Route')->search( { 'me.net_id' => $c->stash->{net_id}, -and => [ 'me.route_beg' => 'nodes.node_id', 'me.net_id' => 'nodes.net_id', 'me.route_end' => 'nodes_2.node_id', 'me.net_id' => 'nodes_2.net_id' ], }, { join => ['nodes', 'nodes'], 'select' => [ 'me.route_beg', 'me.route_end', \'nodes.node_name AS node_name_beg', \'nodes_2.node_name AS node_name_end', \'COUNT(me.route_beg) as grp_count', ], 'as' => [ qw/ route_beg route_end node_name_beg node_nam +e_end route_grp_count / ], 'group_by' => [qw/ me.route_beg me.route_end nodes.node_name + nodes_2.node_name /], 'order_by' => [ qw/ node_name_beg/ ], page => $page, # page to return (defaults to 1)use Data::Du +mper; die "SEARCH" . Dumper($new_attrs); rows => $rows, # number of results per page }, )];
      I create new with join, but it still MISSING Group By SQL:
      SELECT * FROM ( SELECT TOP 10 * FROM ( SELECT TOP 10 me.route_beg, me.route_end, nodes.node_name AS +node_name_beg, nodes_2.node_name AS node_name_end, COUNT(me.route_beg +) as grp_count FROM vi_route me JOIN vi_nodes nodes ON ( nodes.node_ +id = me.route_beg ) JOIN vi_nodes nodes_2 ON ( nodes_2.node_id = me. +route_beg ) WHERE ( ( ( me.route_beg = ? ) AND ( me.net_id = ? ) AND +( me.route_end = ? ) AND ( me.net_id = ? ) ) AND me.net_id = ? ) ORDE +R BY node_name_beg ASC ) AS foo ORDER BY node_name_beg DESC ) AS bar ORDER BY node_name_beg ASC : 'nodes.node_id', 'nodes.net_id', 'nodes_2.node_id', 'nodes_2.net_id' +, 'СЕВ'
      NO NEEDED GROUP BY!!! And sql becomes bad//((
        Temporary resolved through the database view and adding new DBIx schema-class for the view.