[Dbix-class] For a reliable update_or_create we need to make create( { primary_key => undef, ... } ) work in Pg

Daniel Westermann-Clark dwc at pobox.com
Mon Jan 21 23:02:35 GMT 2008


On 2008-01-21 14:14:10 +0100, Zbigniew Lukasiak wrote:
> The reason for that is that finding without a unique condition is a
> special case - it's not really obvious what it should return - it
> could even be a run time error.  Find is based on search, normally
> when you remove a condition from search it should return more rows -
> but here when you remove a condition from find, to cooperate with
> the find_or_* methods, it should return no rows at all.  We can
> force it to do that - but this is quite complex, because you can
> have the conditions not only in the query but also in the resultset
> itself.  This needs to be done very carefully.
> 
> But I am OK with that solution - in fact I have sent a patch that
> worked for most of the cases that I imagined, but I am sure it would
> benefit from your review.  I am attaching it here once again.

There is an ~80% finished solution in ::ResultSet to resolve the query
and resultset conditions and check them for uniqueness.  mst made me
disable the warning at one point during the 0.07 RC cycle because
those 20% cases happen more often than you'd think.  :)

If we can bring the existing _is_unique_query up to date, adding an
option to turn off fallback sounds reasonable.  I agree that some
applications could use the explicit switch.

Since we're talking about changing the behavior of find, this most
likely belongs on the 0.09 cycle.  To that end, I've opened a branch
to start fixing _is_unique_query:

http://dev.catalystframework.org/svnweb/bast/browse/DBIx-Class/0.09/branches/find_unique_fallback/

I've started reworking the check a little, but there are still
problems inferring uniqueness across a join.  See, for example, the
final set of tests in t/79aliasing.t:

# Don't pass column names with related alias to new_result
{
  my $cd_rs = $schema->resultset('CD')->search({ 'artist.name' =>
  'Caterwauler McCrae' }, { join => 'artist' });

  my $cd = $cd_rs->find_or_new({ title => 'Huh?', year => 2006 });
  ok(! $cd->in_storage, 'new CD not in storage yet');
  is($cd->title, 'Huh?', 'new CD title is correct');
  is($cd->year, 2006, 'new CD year is correct');
}

Ideally this query should not warn: the search identifies a unique
artist row and the find identifies a unique CD row.

-- 
Daniel Westermann-Clark



More information about the DBIx-Class mailing list