Skip Menu |

This queue is for tickets about the DBIx-Class CPAN distribution.

Report information
The Basics
Id: 52777
Status: rejected
Priority: 0/
Queue: DBIx-Class

People
Owner: Nobody in particular
Requestors: ovid [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 0.08115
Fixed in: (no value)



Subject: might_have() relationships return bad data
Bug: might_have relationships which depend on an attribute with "is_nullable" being true can return incorrect data if that attribute is NULL. Peter Rabbitson mentions this bug in a mailing list response, but it appears that people think the bug was eliminated. It's now causing incorrect responses at my work. http://lists.scsys.co.uk/pipermail/dbix-class/2009-December/008680.html I've attached sample program to reproduce this error on DBIx::Class version 0.08115. Note that even though we create a customer with *no* account information (as is allowed by the code), the code still reports the customer as having a "Premium" account. Cheers, Ovid
Subject: might_have.pl
#!/usr/bin/env perl use strict; use warnings; my $db = 'premium.db'; my $sql = <<'END'; create table customer ( id int primary key, account_id int null, foreign key(account_id) references account(id) ); create table account ( id int primary key, type varchar(10) ); insert into account values ( 1, 'Premium' ); END unlink $db if -f $db; open my $fh, "| sqlite3 $db" or die "Cannot pipe to sqlite3: $!"; print $fh $sql or die $!; close $fh or die $!; { package The::Schema; use parent qw/DBIx::Class::Schema/; } { package The::Schema::Account; use parent 'DBIx::Class'; __PACKAGE__->load_components("Core"); __PACKAGE__->table("account"); __PACKAGE__->add_columns( id => { data_type => "int" }, type => { data_type => "varchar" }, ); __PACKAGE__->set_primary_key("id"); The::Schema->register_class( 'Account', __PACKAGE__ ); } { package The::Schema::Customer; use parent 'DBIx::Class'; __PACKAGE__->load_components("Core"); __PACKAGE__->table("customer"); __PACKAGE__->add_columns( id => { data_type => "int" }, account_id => { data_type => "int", is_nullable => 1 }, ); __PACKAGE__->set_primary_key("id"); __PACKAGE__->might_have( "account", "The::Schema::Account" ); The::Schema->register_class( 'Customer', __PACKAGE__ ); } my $schema = The::Schema->connect("dbi:SQLite:dbname=$db"); my $cust = $schema->resultset('Customer')->create( {} ); print $cust->account->type;
On Tue Dec 15 05:37:50 2009, OVID wrote: Show quoted text
> Bug: might_have relationships which depend on an attribute with > "is_nullable" being true can return incorrect data if that attribute is > NULL. > > Peter Rabbitson mentions this bug in a mailing list response, but it > appears that people think the bug was eliminated. It's now causing > incorrect responses at my work. > > http://lists.scsys.co.uk/pipermail/dbix-class/2009-December/008680.html > > I've attached sample program to reproduce this error on DBIx::Class > version 0.08115. Note that even though we create a customer with *no* > account information (as is allowed by the code), the code still reports > the customer as having a "Premium" account. > > Cheers, > Ovid
The example is completely flawed. You have Customer which may or may not be related to an Account. However you keep the primary key of the Account in a foreign key column in Customer (which is odd in itself). The only relationship helper for this is belong_to. Think of relationships as two-way: on one side you ALWAYS have belongs_to on the other you have has_one/might_have/has_many belongs_to signals: "This class holds the foreign PK in an FK column" anything else says: Someone holds *our* PK in a column in the foreign class The reason you see what you see is weirdness in the might_have/has_one automatic column inference. Long story short the actual relationship becomes JOIN ... ON 'account'.'id' = 'customer'.'id', which is why you get the account returned (1 == 1). In general in order to avoid such pitfalls always supply the 3rd argument to the relationship helper. The automatic inference is an imho unfortunate cargo-cult from CDBI, and is causing much more grief than the value it supposedly brings.
On Tue Dec 15 06:26:27 2009, RIBASUSHI wrote: Show quoted text
> The example is completely flawed. You have Customer which may or
may not Show quoted text
> be related to an Account. However you keep the primary key of the > Account in a foreign key column in Customer (which is odd in itself). > The only relationship helper for this is belong_to. Think of > relationships as two-way: > on one side you ALWAYS have belongs_to > on the other you have has_one/might_have/has_many > > belongs_to signals: "This class holds the foreign PK in an FK column" > anything else says: Someone holds *our* PK in a column in the
foreign class Show quoted text
> > The reason you see what you see is weirdness in the
might_have/has_one Show quoted text
> automatic column inference. Long story short the actual relationship > becomes JOIN ... ON 'account'.'id' = 'customer'.'id', which is why you > get the account returned (1 == 1). > > In general in order to avoid such pitfalls always supply the 3rd > argument to the relationship helper. The automatic inference is an
imho Show quoted text
> unfortunate cargo-cult from CDBI, and is causing much more grief
than Show quoted text
> the value it supposedly brings. >
Hi Peter, Thanks for the quick response. While I agree that the example is problematic, the response is even more so. It's a silent failure mode. The larger an application, the harder something like this would be to find. Could the inference be deprecated? Is there another way this could be handled? Cheers, Ovid
Not a bug. Confusion was due to improper documentation, improvements pending.