[Dbix-class] find redux

Zbigniew Lukasiak zzbbyy at gmail.com
Fri Jan 25 16:32:43 GMT 2008


On Jan 25, 2008 5:10 PM, Zbigniew Lukasiak <zzbbyy at gmail.com> wrote:
> On Jan 25, 2008 2:30 PM, Matt S Trout <dbix-class at trout.me.uk> wrote:
> > On Fri, Jan 25, 2008 at 12:24:27PM +0100, Zbigniew Lukasiak wrote:
> > > Let me sidestep that a bit
> >
> > No, I won't let you.
> >
> > I spent an hour discussing with people how to structure this discussion so
> > we can actually work out how to proceed in a framework that's clear, precise
> > and reasonably easy to convert across to code.
> >
> > Please do me the courtesy of respecting the effort that went into this
> > and working within the structure provided.
>
> OK, if that will help you I am happy to provide that help.
>
> I am not sure what you meant in the end note - I'll assume here that
> it means that when you say 'all columns' you mean the columns in the
> query and in the internal resultset condition.  Correct me if I am
> wrong.  This question of including the 'implicite rs columns' is the
> most important thing in this whole analysis - because it is the least
> understood one.  My opinion is that those columns should be included.
>
> And assuming that I differ with you in the analysis of
>
> Case 1 - called with 'key' attr and all columns for that key
>
> If all the key columns are in the query then the behaviour is correct,
> but if one of the columns for the key is in the condition instead of
> the query then a search by all columns will be issued.
> This was documented in my email from Jan. 17th in the thread rs->find
> finds by all columns.
> Here I repeat the test case:
>
> my $cd = $schema->resultset("CD")->first;
> my $old_artistid = $cd->artist->artistid;
> $cd->artist->update( { name => 'new name' } );
> $schema->storage->debug(1);
> my $art = $cd->update_or_create_related( 'artist', { name => 'some
> other name' } );
> is( $old_artistid, $art->artistid, 'artist updated not recreated' );
>
>
> __OUTPUT__
>
> SELECT me.artistid, me.name FROM artist me WHERE ( ( ( me.name = ? )
> AND ( me.artistid = ? ) ) ): 'some other name', '1'
> INSERT INTO artist (artistid, name) VALUES (?, ?): '1', 'some other name'
> DBIx::Class::Relationship::Base::update_or_create_related(): DBI
> Exception: DBD::SQLite::st execute failed: PRIMARY KEY must be
> unique(19) at dbdimp.c line 403 [for Statement "INSERT INTO artist
> (artistid, name) VALUES (?, ?)"] at t/61findnot.t line 16

Sorry that was more Case 3 - it falls back to Case 1 - but to be
strict I've updated the test case:

my $cd = $schema->resultset("CD")->first;
my $old_artistid = $cd->artist->artistid;
$cd->artist->update( { name => 'new name' } );
$schema->storage->debug(1);
my $art = $cd->update_or_create_related( 'artist', { name => 'some
        other name' }, { key => 'primary' } );
is( $old_artistid, $art->artistid, 'artist updated not recreated' );

__OUTPUT__

t/61findnot......SELECT me.artistid, me.name FROM artist me WHERE ( (
( me.name = ? ) AND ( me.artistid = ? ) ) ): 'some
        other name', '1'
INSERT INTO artist (artistid, name) VALUES (?, ?): '1', 'some
        other name'
DBIx::Class::Relationship::Base::update_or_create_related(): DBI
Exception: DBD::SQLite::st execute failed: PRIMARY KEY must be
unique(19) at dbdimp.c line 403 [for Statement "INSERT INTO artist
(artistid, name) VALUES (?, ?)"] at t/61findnot.t line 16
# Looks like your test died before it could output anything.

>
> =head1 better behaviour: find()
>
> The Case 1 is the most important one to fix.
>
> In my opinion if the user provides all the needed columns (be it in
> the query or in the internal resultset condition) it should always
> return the found record if there is one or return undef if there is no
> such record.
>
> Cheers,
> Zbigniew
> http://perlalchemy.blogspot.com/
>



-- 
Zbigniew Lukasiak
http://brudnopis.blogspot.com/



More information about the DBIx-Class mailing list