<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii">
<meta name=Generator content="Microsoft Word 12 (filtered medium)">
<style>
<!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Consolas;
        panose-1:2 11 6 9 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p.MsoPlainText, li.MsoPlainText, div.MsoPlainText
        {mso-style-priority:99;
        mso-style-link:"Plain Text Char";
        margin:0in;
        margin-bottom:.0001pt;
        font-size:10.5pt;
        font-family:Consolas;}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
span.PlainTextChar
        {mso-style-name:"Plain Text Char";
        mso-style-priority:99;
        mso-style-link:"Plain Text";
        font-family:Consolas;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page Section1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.Section1
        {page:Section1;}
-->
</style>
<!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang=EN-US link=blue vlink=purple>
<div class=Section1>
<p class=MsoPlainText>Hi there,<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>We're currently upgrading our DBIC from v0.08012 to the
latest version (v0.08120) on a project I'm working on. Most things are going
smoothly, but we've run into a use case for find_or_create_related that used to
work in the older DBIC but no longer does. We had some code that was calling
$row->find_or_create_related('rel', { ... }) on a new row object that hasn't
been inserted into the database yet. This ought to work because the
relationship is a belongs_to, so it doesn't need to know anything about $row.
In the new version, the related row is always created regardless of whether the
related object already exists in the DB.<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>We can change the code easily to just call
find_or_create() on the related table itself, but we were doing it this way
because we wanted to find_or_create on the related table without having to know
what class to search on (that's my guess, anyway - the original impetus for the
way this was written is long gone now). Having the new row object and the
relationship names was an easy way to do this, and seems like a quirky yet
valid use case, so I would argue that it ought to be supported. Or at least it
would be nice if there was some kind of error or warning or something, rather
than the current behavior which is to silently create a new row in the related
table even if the find() would have succeeded.<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>I'll provide more detail about my exact use case below,
and I'm happy to provide anything else.<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>We have two related tables, build_data and build_urls,
which are pasted below with the irrelevant columns and relationships removed:<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=======================<o:p></o:p></p>
<p class=MsoPlainText>=== BEGIN BuildData ===<o:p></o:p></p>
<p class=MsoPlainText>=======================<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>package NBT::Schema::Icebox::BuildData;<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText># Created by DBIx::Class::Schema::Loader # DO NOT MODIFY
THE FIRST PART OF THIS FILE<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>use strict;<o:p></o:p></p>
<p class=MsoPlainText>use warnings;<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>use base 'DBIx::Class::Core';<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=head1 NAME<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>NBT::Schema::Icebox::BuildData<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=cut<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>__PACKAGE__->table("build_data");<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=head1 ACCESSORS<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=head2 id<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText> data_type: INT<o:p></o:p></p>
<p class=MsoPlainText> default_value: undef<o:p></o:p></p>
<p class=MsoPlainText> extra: HASH(0xa042260)<o:p></o:p></p>
<p class=MsoPlainText> is_auto_increment: 1<o:p></o:p></p>
<p class=MsoPlainText> is_nullable: 0<o:p></o:p></p>
<p class=MsoPlainText> size: 10<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=head2 build_url<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText> data_type: INT<o:p></o:p></p>
<p class=MsoPlainText> default_value: undef<o:p></o:p></p>
<p class=MsoPlainText> extra: HASH(0xa047638)<o:p></o:p></p>
<p class=MsoPlainText> is_foreign_key: 1<o:p></o:p></p>
<p class=MsoPlainText> is_nullable: 1<o:p></o:p></p>
<p class=MsoPlainText> size: 10<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=cut<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>__PACKAGE__->add_columns(<o:p></o:p></p>
<p class=MsoPlainText> "id",<o:p></o:p></p>
<p class=MsoPlainText> {<o:p></o:p></p>
<p class=MsoPlainText> data_type => "INT",<o:p></o:p></p>
<p class=MsoPlainText> default_value => undef,<o:p></o:p></p>
<p class=MsoPlainText> extra => { unsigned => 1 },<o:p></o:p></p>
<p class=MsoPlainText> is_auto_increment => 1,<o:p></o:p></p>
<p class=MsoPlainText> is_nullable => 0,<o:p></o:p></p>
<p class=MsoPlainText> size => 10,<o:p></o:p></p>
<p class=MsoPlainText> },<o:p></o:p></p>
<p class=MsoPlainText> "build_url",<o:p></o:p></p>
<p class=MsoPlainText> {<o:p></o:p></p>
<p class=MsoPlainText> data_type => "INT",<o:p></o:p></p>
<p class=MsoPlainText> default_value => undef,<o:p></o:p></p>
<p class=MsoPlainText> extra => { unsigned => 1 },<o:p></o:p></p>
<p class=MsoPlainText> is_foreign_key => 1,<o:p></o:p></p>
<p class=MsoPlainText> is_nullable => 1,<o:p></o:p></p>
<p class=MsoPlainText> size => 10,<o:p></o:p></p>
<p class=MsoPlainText> },<o:p></o:p></p>
<p class=MsoPlainText>);<o:p></o:p></p>
<p class=MsoPlainText>__PACKAGE__->set_primary_key("id");<o:p></o:p></p>
<p class=MsoPlainText>__PACKAGE__->add_unique_constraint("build_pxe_branch",
["build_url", "pxe_kernel", "branch"]);<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=head1 RELATIONS<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=head2 build_url<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>Type: belongs_to<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>Related object: L<NBT::Schema::Icebox::BuildUrls><o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=cut<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>__PACKAGE__->belongs_to(<o:p></o:p></p>
<p class=MsoPlainText> "build_url",<o:p></o:p></p>
<p class=MsoPlainText> "NBT::Schema::Icebox::BuildUrls",<o:p></o:p></p>
<p class=MsoPlainText> { id => "build_url" },<o:p></o:p></p>
<p class=MsoPlainText> { join_type => "LEFT" },<o:p></o:p></p>
<p class=MsoPlainText>);<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=======================<o:p></o:p></p>
<p class=MsoPlainText>=== BEGIN BuildUrls ===<o:p></o:p></p>
<p class=MsoPlainText>=======================<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>package NBT::Schema::Icebox::BuildUrls;<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText># Created by DBIx::Class::Schema::Loader # DO NOT MODIFY
THE FIRST PART OF THIS FILE<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>use strict;<o:p></o:p></p>
<p class=MsoPlainText>use warnings;<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>use base 'DBIx::Class::Core';<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=head1 NAME<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>NBT::Schema::Icebox::BuildUrls<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=cut<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>__PACKAGE__->table("build_urls");<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=head1 ACCESSORS<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=head2 id<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText> data_type: INT<o:p></o:p></p>
<p class=MsoPlainText> default_value: undef<o:p></o:p></p>
<p class=MsoPlainText> extra: HASH(0xa04789c)<o:p></o:p></p>
<p class=MsoPlainText> is_auto_increment: 1<o:p></o:p></p>
<p class=MsoPlainText> is_nullable: 0<o:p></o:p></p>
<p class=MsoPlainText> size: 10<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=head2 name<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText> data_type: VARCHAR<o:p></o:p></p>
<p class=MsoPlainText> default_value: undef<o:p></o:p></p>
<p class=MsoPlainText> is_nullable: 0<o:p></o:p></p>
<p class=MsoPlainText> size: 255<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=cut<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>__PACKAGE__->add_columns(<o:p></o:p></p>
<p class=MsoPlainText> "id",<o:p></o:p></p>
<p class=MsoPlainText> {<o:p></o:p></p>
<p class=MsoPlainText> data_type => "INT",<o:p></o:p></p>
<p class=MsoPlainText> default_value => undef,<o:p></o:p></p>
<p class=MsoPlainText> extra => { unsigned => 1 },<o:p></o:p></p>
<p class=MsoPlainText> is_auto_increment => 1,<o:p></o:p></p>
<p class=MsoPlainText> is_nullable => 0,<o:p></o:p></p>
<p class=MsoPlainText> size => 10,<o:p></o:p></p>
<p class=MsoPlainText> },<o:p></o:p></p>
<p class=MsoPlainText> "name",<o:p></o:p></p>
<p class=MsoPlainText> {<o:p></o:p></p>
<p class=MsoPlainText> data_type => "VARCHAR",<o:p></o:p></p>
<p class=MsoPlainText> default_value => undef,<o:p></o:p></p>
<p class=MsoPlainText> is_nullable => 0,<o:p></o:p></p>
<p class=MsoPlainText> size => 255,<o:p></o:p></p>
<p class=MsoPlainText> },<o:p></o:p></p>
<p class=MsoPlainText>);<o:p></o:p></p>
<p class=MsoPlainText>__PACKAGE__->set_primary_key("id");<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=head1 RELATIONS<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=head2 build_datas<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>Type: has_many<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>Related object: L<NBT::Schema::Icebox::BuildData><o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>=cut<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>__PACKAGE__->has_many(<o:p></o:p></p>
<p class=MsoPlainText> "build_datas",<o:p></o:p></p>
<p class=MsoPlainText> "NBT::Schema::Icebox::BuildData",<o:p></o:p></p>
<p class=MsoPlainText> { "foreign.build_url" =>
"self.id" },<o:p></o:p></p>
<p class=MsoPlainText>);<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText># Created by DBIx::Class::Schema::Loader v0.05003 @
2010-03-17 16:38:08 # DO NOT MODIFY THIS OR ANYTHING ABOVE!
md5sum:Ln4fU7T0Koi6pqWzS6APfw<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>===================<o:p></o:p></p>
<p class=MsoPlainText>=== END PASTIES ===<o:p></o:p></p>
<p class=MsoPlainText>===================<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>We have some code that does a find_or_create_related call
like this:<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText> $build_datum =
$schema->resultset("NBT::Schema::Icebox::BuildData")->new_result({});<o:p></o:p></p>
<p class=MsoPlainText> # actually we loop through a list of relationships
next, but I'm keeping it simple for the sake of the example<o:p></o:p></p>
<p class=MsoPlainText>
$build_datum->find_or_create_related("build_url", { name =>
'...' });<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>This produces some strange SQL that looks like this:<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText> SELECT me.id, me.name, me.modified_ts FROM build_urls
me WHERE ( ( me.name = ? AND 1 = 0 ) ): '...'<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>The 'AND 1 = 0' condition makes the select impossible, so
a related row is always created. The impossible condition seems to come from
DBIx::Class::ResultSource->_resolve_condition(), which decides that the
relationship condition is unresolvable and returns \'1 = 0'. The condition is
'unresolvable' because the build_url column is not in_storage on $build_datum,
because $build_datum is a new_result. If the 'AND 1 = 0' were left out, this
would do the right thing, I think. But maybe theres a good reason for its
existence in this case and I'm just confused?<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>Thanks for your time,<o:p></o:p></p>
<p class=MsoPlainText><o:p> </o:p></p>
<p class=MsoPlainText>Byron Young (original author, I’m sending this for
him since he can’t mail the list for some reason -Robert)<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
</div>
</body>
</html>