[Dbix-class] Bug with relationships on new objects.

Scott Thomson smoothhound at gmail.com
Tue Jan 22 12:29:50 GMT 2008


On Jan 22, 2008 9:16 AM, Matt S Trout <dbix-class at trout.me.uk> wrote:
>
> On Mon, Jan 21, 2008 at 01:04:21PM +0000, Scott Thomson wrote:
> >
> > On Jan 7, 2008 8:36 PM, Brett Gardner <brett at clientcomm.com.au> wrote:
> > > I'm not saying that the test is incorrect. That is when a foreign key is
> > > empty. The case that affects me is when the primary key is empty.
> > >
> > > To use the examples below, it is like saying that a new Artist owns all
> > > the existing CDs even though those CDs have their Artists set, until
> > > insert is called.
> > >
> > > Brett
> > >
> > >
> > > Brett Gardner wrote:
> > > > I call new because I then call a method on the object which returns a
> > > > list of form controls to edit the object.
> > > >
> > > > In other cases I also have to set accessors before calling the insert
> > > > method.
> > > >
> > > > Jess Robinson wrote:
> > > >>
> > > >>
> > > >> On Mon, 7 Jan 2008, brett gardner wrote:
> > > >>
> > > >>> The offending line is on line 793 of ResultSource.pm
> > > >>>
> > > >>> $ret{$k} = $for->get_column($v) if $for->has_column_loaded($v);
> > > >>
> > > >> That's because has_column_loaded returns true if the data is in/was
> > > >> loaded from the database, you're calling new(), which doesnt insert a
> > > >> new row into the database. So it's doing the correct thing.
> > > >>
> > > >> Call create() instead. That does new() and insert().
> > > >>
> > > >>> my $undef_artist_cd = $schema->resultset("CD")->new_result({ 'title'
> > > >>> => 'badgers', 'year' => 2007 });
> > > >>> 207 is($undef_artist_cd->has_column_loaded('artist'), '', 'FK not
> > > >>> loaded');
> > > >>> 208 is($undef_artist_cd->search_related('artist')->count, 3, 'open
> > > >>> search on undef FK');
> > > >>
> > > >> new_result (or new) don't insert any data in the db, so this is
> > > >> perfectly correct.
> > > >>
> > > >>> in 66relationship.t
> > > >>>
> > > >>> brett gardner wrote:
> > > >>>> I have a schema where there are clients who have subscribers.
> > > >>>>
> > > >>>> So there is an object "Client" which has a has_many relationship to
> > > >>>> "Subscriber".
> > > >>>>
> > > >>>> If I do the following
> > > >>>>
> > > >>>> my $client = $app->schema->resultset('Client')->find(...);
> > > >>>> my $subscribers = $client->subscribers;
> > > >>>>
> > > >>>> Then the relationship is correct and only pulls out the subscribers
> > > >>>> attached to that client.
> > > >>>>
> > > >>>> But if I do the following.
> > > >>>>
> > > >>>> my $client = $app->schema->resultset('Client')->new({});
> > > >>>> my $subscribers = $client->subscribers;
> > > >>>> Then all the subscribers are pulled out which is not ideal and
> > > >>>> potentially a very embarrassing privacy breach. Looking at the SQL
> > > >>>> generated by "$client->subscribers" it is not putting in the
> > > >>>> limiting where clause "WHERE me.client_id = ..."
> > > >>
> > > >> As your row is not in the database, how would you expect it to do a
> > > >> where?
> > > >>
> > > >>
> > > >> Did you really miss all this, or am I misunderstanding your problem?
> > > >>
> > > >> Jess
> >
>
> << fixed top-posting and trimmed list footers, learn to use your
>    mail clients please people ... >>
>
> > I've also run into a version of this problem. Mine occurs when
> > creating an object with an unset FK. It doesn't matter if the object
> > is new'd or created - it still doesn't have a key for the FK in
> > _column_data.
> >
> > I'm considering simply overriding 'new' where appropriate and
> > explicitly setting the FK(s) to undef but what concerns me is that the
> > behaviour of the created object is different from when the object is
> > loaded from the DB and I'm worried that this might bite me elsewhere.
>
> If the column value isn't present at all, maybe related_resultset should
> throw an exception on the grounds it can't actually create one yet?
>
> I can't see that breaking any code that isn't already terminally broken -
> does one of you guys want to have a go at writing a test case? (because
> that's how it'll get fixed :)

I'm up for writing a test case, I've already got the beginnings of one
against which I used to help me locate the cause of the problem.
However, I'm not at all sure what is the correct behaviour to assert.

I do think that a 'create'd object should have exactly the same
external behaviour of an inflated object, which is currently not the
case, as to what that behaviour should be I'm not so sure.

Looking at the test cases accompanying the commit that introduced this
behaviour, it would seem that the author (CaptainL) thinks that
calling a relationship on an unset FK should return all rows, this
doesn't seem right to me - but if that's correct then the same object
when inflated should do the same.

I'm going to read up on relational DB theory in an attempt to form a
stronger opinion  :)



More information about the DBIx-Class mailing list