[Dbix-class] -current branch: please test

Nilson Santos Figueiredo Junior acid06 at gmail.com
Wed Jul 12 19:48:02 CEST 2006


On 7/11/06, David Kamholz <davekam at pobox.com> wrote:
> Well, after a fair amount of thought on Matt's part and some work,
> we've implemented some improved resultset code, resolving some subtle
> bugs that came up in the last few days. The new implementation
> (codenamed ResultSet 2: Electric Boogaloo) has been committed to the -
> current branch. I would once again like to ask anyone who has an app
> with twisty and complex joins and prefetches to test it out. If all
> looks well, we will release it as a final RC in a couple days to here
> and the Catalyst list. At present there are no known bugs -- we're
> hoping this will become the 0.07 final.

I hate to be the one to say it again but my Catalyst application fails
right away with -current as it is.

I'm getting this error:
Coldn't render template "undef error -
DBIx::Class::ResultSet::count(): Error executing 'SELECT COUNT(
DISTINCT( task.id ) ) FROM task_user me  JOIN task task ON ( task.id =
me.task_id ) LEFT JOIN task_log logs ON ( logs.task_id = task.id )
LEFT JOIN task_log logs ON ( logs.task_id = task.id ) WHERE ( ( (
is_closed = ? ) AND ( me.user_id = ? ) ) )': Not unique table/alias:
'logs' at E:\cgi\MyTasks\root\user\tasklist.tt line 4"

As you can see from the query, the join is duplicated. This didn't
happen before (neither in trunk nor in -current).

The error happens when I issue a "tasks.count" on a resultset that was
produced as follows:

my $user = $c->model('Persistent::User')->find($user_id);
my $tasks = $user->tasks->search_hours_spent;

If I don't populate "hours_spent" through the search_hours_spent()
method, the error doesn't occur, so probably it's something in it
(again):

  sub search_hours_spent {
      my $self = shift;
      my $alias = $self->{attrs}{alias};

      $self->search(
          undef,
          {
              join     => [qw/logs/],
              select   => [(map {"${alias}.${_}"}
$self->result_source->columns), {sum => 'logs.hours_spent'} ],
              as       => [$self->result_source->columns, qw/hours_spent/],
              group_by => ["${alias}.id"]
          }
      );
  }

The "tasks" relationship is a many-to-many one, as follows:

  $pkg->has_many('task_users' => 'MyTasks::Schema::TaskUser', 'user_id');
  $pkg->many_to_many('tasks' => 'task_users', 'task');

The weirdest part of all of this is that there's another User
relationship, "created_tasks" for which the search_hours_spent()
method works flawlessly. It is a plain one-to-many relationship so
maybe the issue is somewhat related to many-to-many relationships.
This relationship (the one that works) is defined as:

  $pkg->has_many('created_tasks' => 'MyTasks::Schema::Task',  'creator_id');

The specific relationship being joined twice is defined as:

  $pkg->has_many('logs'       => 'MyTasks::Schema::TaskLog',  'user_id');

The related Schema classes:

    package MyTasks::Schema::User;
    use warnings;
    use strict;
    use base qw/DBIx::Class/;

    my $pkg = __PACKAGE__;
    $pkg->load_components(qw/PK::Auto Core/);
    $pkg->table('user');
    $pkg->add_columns(qw/id login passwd name type/);
    $pkg->set_primary_key('id');
    $pkg->add_unique_constraint( login => ['login'] );
    $pkg->add_unique_constraint( name  => ['name' ] );

    # foreign keys
    $pkg->has_many('logs'       => 'MyTasks::Schema::TaskLog',  'user_id');

    $pkg->has_many('created_tasks' => 'MyTasks::Schema::Task',  'creator_id');

    $pkg->has_many('task_users' => 'MyTasks::Schema::TaskUser', 'user_id');
    $pkg->many_to_many('tasks' => 'task_users', 'task');

    1;

    package MyTasks::Schema::Task;
    use warnings;
    use strict;
    use base qw/DBIx::Class/;

    my $pkg = __PACKAGE__;

    $pkg->load_components(qw/PK::Auto Core/);
    $pkg->table('task');
    $pkg->add_columns(qw/id project_id creator_id date deadline
priority description is_closed comments parent_id
support_request_id/);
    $pkg->set_primary_key('id');
    $pkg->resultset_class('MyTasks::Schema::ResultSet::Task');

    # foreign keys
    $pkg->belongs_to('project', 'MyTasks::Schema::Project', 'project_id');

    $pkg->belongs_to('creator', 'MyTasks::Schema::User', 'creator_id');

    $pkg->has_many('logs', 'MyTasks::Schema::TaskLog', 'task_id');

    $pkg->has_many('task_users' => 'MyTasks::Schema::TaskUser', 'task_id');
    $pkg->many_to_many('users' => 'task_users', 'user');

    $pkg->has_many('child_tasks' => 'MyTasks::Schema::Task', 'parent_id');
    $pkg->belongs_to('parent_task' => 'MyTasks::Schema::Task', 'parent_id');
    $pkg->belongs_to('support_request' =>
'MyTasks::Schema::SupportRequest', 'support_request_id');

    1;

    package MyTasks::Schema::TaskLog;
    use warnings;
    use strict;
    use base qw/DBIx::Class/;

    __PACKAGE__->load_components(qw/PK::Auto Core/);
    __PACKAGE__->table('task_log');
    __PACKAGE__->add_columns(qw/id task_id user_id date hours_spent comments/);
    __PACKAGE__->set_primary_key('id');

    # foreign keys
    __PACKAGE__->belongs_to('task', 'MyTasks::Schema::Task', 'task_id');
    __PACKAGE__->belongs_to('user', 'MyTasks::Schema::User', 'user_id');

    1;

    package MyTasks::Schema::TaskUser;
    use warnings;
    use strict;
    use base qw/DBIx::Class/;

    __PACKAGE__->load_components(qw/PK::Auto Core/);
    __PACKAGE__->table('task_user');
    __PACKAGE__->add_columns(qw/task_id user_id/);
    __PACKAGE__->set_primary_key(qw/task_id user_id/);

    # foreign keys
    __PACKAGE__->belongs_to('task', 'MyTasks::Schema::Task', 'task_id');
    __PACKAGE__->belongs_to('user', 'MyTasks::Schema::User', 'user_id');

    1;

I tried including as much information as possible. But, if necessary,
I can provide whatever else information is needed.

-Nilson Santos F. Jr.



More information about the Dbix-class mailing list