[Dbix-class] Unexpected behavior with possible NULL foreign key relationship

mike pulsation at gmail.com
Thu Aug 7 20:08:54 BST 2008


i'm bringing this issue back up, as i've had time to look at it again.
 first, some context:

On Fri, Mar 21, 2008 at 03:14:40PM -0700, Damon Snyder wrote:
> Hi Everyone,
> I'm new to the list so bear with me if I'm missing something. I have a
> foreign key relationship where it's possible that the belongs_to
> relationship is NULL. See the classes below. When I create a new
> Smsmessage object e.g. like so:

[snip]

>> >  On Wed, Apr 2, 2008 at 3:52 PM, mike <pulsation at gmail.com> wrote:
>> however, this current problem is not mysql.  i have confirmed that it
>> only occurs
>> on newly created objects by adding a call to discard_changes after the c=
reation.
>> following is the modified patch including the test that illustrates
>> this behavior.
>
> (1) your mail client mangled the patch
> (2) after unmangling it, it makes 60core and 91debug fail.
>
> Can I have another patch that doesn't break anything else please? :)

attached you will find my modified patch, produced against 0.08 trunk
(r4736).  if only by virtue of being an attachment, it should not have
been mangled by gmail or this unholy fvwm->rdesktop->win32->firefox
setup i use.

i've been perusing around the innards, but i'm not sure where the issue
is.  the field is not specified to create(), so Row's constructor is not
calling store_column for it.  if the field is specified, the accessor
returns undef, as expected.  however, if the field is not specified, the
accessor returns an object that describes a row from that table.  if the
table is empty, the accessor returns undef.

if the table contains multiple rows, we see the warning:

	DBICTest::Schema::CD::genre(): Query returned more than one row.
	SQL that returns multiple rows is DEPRECATED for ->find and ->single

it appears that the search_related that is called performs a simple
SELECT * FROM table.  on lib/DBIx/Class/Relationship/Accessor.pm:21-33:

    $meth{$rel} =3D sub {
      my $self =3D shift;
      if (@_) {
        $self->set_from_related($rel, @_);
        return $self->{_relationship_data}{$rel} =3D $_[0];
      } elsif (exists $self->{_relationship_data}{$rel}) {
        return $self->{_relationship_data}{$rel};
      } else {
        my $val =3D $self->find_related($rel, {}, {}); # <-- performs
unconditional search??
        return unless $val;
        return $self->{_relationship_data}{$rel} =3D $val;
      }
    };

also attached you will find a patch to lib/DBIx/Class/Row.pm that fixes
this problem, but also breaks a single test in both t/cdbi-t/04-lazy.t
and t/cdbi-t/13-constraint.t in ways i haven't begun to try to figure
out.  i don't like explicitly setting the column values to undef.  i
think the better method is to fetch the values from storage if the
requested column does not exist in _column_data.  i could attempt to
provide a patch for this, but it will probably be crappy.  i'm throwing
this information out there in the hopes that somebody more familiar with
DBIC guts can come up with a quick, yet elegant, fix.

-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: accessor.patch
Type: application/octet-stream
Size: 7013 bytes
Desc: not available
Url : http://lists.scsys.co.uk/pipermail/dbix-class/attachments/20080807/07=
6027f4/accessor.obj
-------------- next part --------------
A non-text attachment was scrubbed...
Name: accessor-fix.patch
Type: application/octet-stream
Size: 501 bytes
Desc: not available
Url : http://lists.scsys.co.uk/pipermail/dbix-class/attachments/20080807/07=
6027f4/accessor-fix.obj


More information about the DBIx-Class mailing list