[Dbix-class] convention for naming primary keys to avoidambiguousselects

Noel Burton-Krahn noel at burton-krahn.com
Tue Nov 25 23:27:57 GMT 2008


On Tue, Nov 25, 2008 at 2:06 PM, Peter Rabbitson <rabbit+list at rabbit.us> wrote:
> Octavian Rasnita wrote:
>> From: "Noel Burton-Krahn" <noel at burton-krahn.com>
>>
>> By the way, does anyone know what happends if a secondary table is named
>> "me"?
>>
> The name of the table is irrelevant as they are all aliased anyway. If
> you have a relationship called 'me' (hence JOIN <tblname> me), then I
> believe DBIC will switch it to me2 (just like it does with stacked joins
> over the same relationship[1]). If not - it might very well be a bug,
> tests/patches welcome :)
>


Not exactly irrelevant.  If you have a table named "me", then you get
an ambiguous table reference.  In theis schema I have a table named
"person" and another named "me".

$rs = $schema->resultset('Person')->search({ 'id' => $person_id},
{prefetch => [ qw(me) ]});

SELECT COUNT( * ) FROM person me LEFT JOIN me me ON ( me.person_id =
me.id ) WHERE ( id = ? ): '1'
DBIx::Class::ResultSet::count(): DBI Exception: DBD::mysql::st execute
failed: Not unique table/alias: 'me' [for Statement "SELECT COUNT( * )
FROM person me LEFT JOIN me me ON ( me.person_id = me.id ) WHERE ( id
= ? )" with ParamValues: 0='1'] at t/dbix_unique_prefix_where.t line
114

My test script is below.


~Noel





#! /usr/bin/perl -w
=head1 NAME

 dbix_unique_prefix_where.t - reproduce DBIx's ambiguous select

=head1 DESCRIPTION

DBIx::Class::ResultSet::select does not always qualify column names in
a join, resulting in ambiguous selects.

=head1 AUTHOR

Noel Burton-Krahn <noel at burton-krahn.com>

=cut

use strict;
use warnings;

#--------------------
package My::DBIx::Class;
use base qw/DBIx::Class/;

__PACKAGE__->load_components(qw/PK::Auto Core/);

use overload '""' => 'dump';

sub dump {
	my($self) = shift;
	return join(" ", map { "$_=" . $self->get_column($_) } $self->columns);
}

#--------------------
package MySchema::Person;
use base qw/My::DBIx::Class/;
__PACKAGE__->table('person');
__PACKAGE__->add_columns(qw(id name));
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many(me => 'MySchema::Me', 'person_id');

sub delete {
	my $self = shift;
	$_->delete for $self->me;
	$self->SUPER::delete(@_);
}


#--------------------
package MySchema::Me;
use base  qw/My::DBIx::Class/;
__PACKAGE__->table('me');
__PACKAGE__->add_columns(qw(id person_id me));
__PACKAGE__->set_primary_key('id');
__PACKAGE__->belongs_to(person => 'MySchema::Person', 'person_id');

#--------------------
package MySchema;
use base qw/DBIx::Class::Schema/;

__PACKAGE__->load_classes({
	'MySchema' => [ qw(Person Me) ],
});

#--------------------
package Test::DbixCascaseDelete;
use Test::More tests => 5;

# create a mysql database to test with
system(<<'EOS');
mysqladmin -f drop mytest >/dev/null 2>&1

mysqladmin create mytest

mysql mytest <<ESQL
create table person (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
  ,name VARCHAR(1024) NOT NULL
) ENGINE=INNODB;

create table me (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
  ,person_id INT NOT NULL
  ,me VARCHAR(1024) NOT NULL
  ,FOREIGN KEY (person_id) REFERENCES person (id)
) ENGINE=INNODB;
ESQL

#mysql mytest <<ESQL
#show tables;
#show create table person;
#show create table me;
#ESQL

EOS
	;
is($?, 0, "create database");

# connect
my $schema = MySchema->connect("dbi:mysql:mytest", '', '') or
die("connect: $!");
ok($schema, "connect to db");

$schema->storage->debug(1);


my $rs;
my $person;

$person = $schema->resultset('Person')->create({ name => 'fred'});
ok($person, "create Person: $person");
my $person_id = $person->id;

# this is ok, but a hack:  I'm counting on DBIx to name person.id as "me.id
$rs = $schema->resultset('Person')->search({ 'id' => $person_id},
{prefetch => [ qw(me) ]});
is($rs->count, 1, "joined with me on me.id");

# this will fail: "id" in ambiguous with me.id
eval {
	$rs = $schema->resultset('Person')->search({ id => $person_id},
{prefetch => [ qw(me) ]});
	$rs->count;
};
ok($@, "joined with me on id => ambiguous select: $@");



More information about the DBIx-Class mailing list