[Dbix-class] BUG? Unable to resolve relationship

Peter Rabbitson rabbit+dbic at rabbit.us
Sat Dec 12 11:40:30 GMT 2009

Ovid wrote:
> ----- Original Message ----
>> From: Peter Rabbitson <rabbit+dbic at rabbit.us>
>>> When I upgrade to 0.08115:
>>>   My::Schema::Customer::account(): Unable to resolve relationship from 
>> Customer to account: column account.account_id not loaded from storage (or not 
>> passed to new() prior to insert()). Maybe you forgot to call ->discard_changes 
>> to get defaults from the db. at loader.pl line 7
>> This is correct and expected. Read the error message more carefully. To break it 
>> down:
>> *) You create a row, without specifying a value for account_id.
>> *) The resulting object has only a name, and its autoinc id, dbic does not 
>> assume
>> that the value of account_id is NULL/undef, it simply isn't there (i.e. the 
>> db-side
>> default may be 0, or 42 or 'kinky sex')
>> *) Since there is no value for the FK, the relationship can not be resolved and
>> subsequently the exception you see is thrown.
>> *) If you do what has been suggeste d- call discard_changes to make a db-trip to
>> retrieve the missing values - everything will just work. Alternatively you can
>> create() the row explici5tly specifying account_id => undef - this will work as
>> expected too.
> Hi Peter,
> Thanks for your explanation.  That helps quite a bit.  I have a couple of comments.

What I list below are not dismissals of your suggestions, I in general agree. However
what we have here is a pretty warty system, so please follow the links for more
background of what and why.

> 1.  I've just created the object.  Having to call "discard changes" on something with no changes seems very counter-intuitive to me.  If I view the creation as the change, then "discard changes" implies that the creation will be discarded, but that's obviously not the case.  I'm still not sure I understand what's happening here.
It is extremely counter-intuitive, at the time this method was added someone dropped
the ball with naming. Read the comment at the very end of this file[1] for the
proposed staged solution.

> 2.  We have a very large performance-sensitive system.  Having to make a second trip to the database isn't ideal for us.
Which is why dbic is being conservative and throws its hands in the air when it knows
that it doesn't know the db-value.

> 3.  Since the "account_id" has "is_nullable" set to a true value, would it be appropriate for DBIx::Class to assume that a missing nullable value is actually NULL and thus not throw an exception here?
Unfortunately no, for several reasons:
*) A column can be both is_nullable and have a db-side default (in which case
discard_changes() would yield a different result from assuming null)
*) We currently do not have a stable system for db-side default introspection
it is expected that the default => key in the column definition can be
*anything* (including SQL snippets \'...')

All in all this is a case where you need to define dbic-side defaults on your
own as there is no one size fits all solution. Depending on your exact needs
you can either use [2] or [3].


[1] http://dev.catalyst.perl.org/repos/bast/DBIx-Class/0.08/trunk/t/60core.t
[2] http://search.cpan.org/~flora/DBIx-Class-DynamicDefault-0.03/lib/DBIx/Class/DynamicDefault.pm
[3] http://search.cpan.org/~frew/DBIx-Class-0.08115/lib/DBIx/Class/Manual/Cookbook.pod#Setting_default_values_for_a_row

More information about the DBIx-Class mailing list