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

mike pulsation at gmail.com
Wed Apr 16 01:59:32 BST 2008


[ sorry for the CC, but my last attempt to post to the list never made it ]

On Sun, Apr 6, 2008 at 2:08 PM, Matt S Trout <dbix-class at trout.me.uk> wrote:
> 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:
>  >
>  > my $sms2 = $m->resultset('Smsmessages')->create(
>  >       {
>  >               subject => 'Some subject',
>  >               message => 'a message',
>  >               channel_id => $chan2->id,
>  >               #channel_keyword_id => undef,
>  >               inception => scalar localtime(time()),
>  >               expiration => scalar localtime(time() + (60*60*24)),
>  >               sent => 0,
>  >               retries => 0,
>  >               provider_id => $prov->id,
>  >       }
>  >       );
>  >
>  > If I leave out the channel_keyword_id => undef field, I will get a
>  > defined value for $sms2->channel_keyword. If I trace it, the following
>  > select ends up happening:
>  >
>  > SELECT me.id, me.okid, me.keyword, me.channel_id FROM channel_keywords
>  > me:
>  >
>  > Which returns a value that gets plugged the $sms2->channel_keyword
>  > field. Is this the expected behavior?  The default for this field is
>  > defined as undef below. If a value is not specified in the create()
>  > shouldn't it be given the default value (in this case NULL and not a
>  > random record)? I'm not quite sure I understand what is going on, but
>  > it seems like the new value is not getting an equivalent of NULL in
>  > the new object  unless I explicitly say channel_keyword_id => undef. I
>  > understand that it is good practice to set this value to NULL on
>  > creation, but I'm wondering if the behavior I'm seeing is to be
>  > expected.
>
>  That's very odd. Could you try and produce a minimal set of classes that
>  exhibit this or better still make it happen against the DBICTest schema
>  in the DBIx::Class dist?

i already sent a message regarding this back on 4/2.  from the looks of things,
it never made it to the list.  following is the text of the message
with the patch
included with the text/plain section, just in case messages with attachments
are rejected sans notification.

it doesn't matter if you use add_relationship or belongs_to.  it happens in
both scenarios.

-mike

--- snip --- snip --- snip ---

On Wed, Apr 2, 2008 at 3:52 PM, mike <pulsation at gmail.com> wrote:
> attached is a patch which includes a test that shows the broken single
>  accessor in DBIx::Class 0.08008 and 0.08010.  DBIx::Class 0.08009 was
>  not tested, but DBIx::Class 0.08007 works fine.  i'm not sure exactly
>  what's going on here, but this behavior has appeared in DBIx::Class
>  before.  it breaks the holy hell out of all of our applications in a
>  very nasty way.  with sharp, pointy teeth.  look at the bones!
>
>  in short, the aforementioned versions of DBIx::Class cause (at least
>  some) single accessors to return inflated objects for fields that are
>  NULL.
>
>  if we are using accessor => single in some obtuse way, education is
>  welcome; however, it would be in everyone's best interests if this
>  behavior didn't change between releases, so i highly recommend that
>  a similar version to this test be added to the default test suite.
>
>  -mike
>
>  --- output of test using 0.08007 from default library path ---
>
>  $ PERL5LIB=t/lib perl t/broken_single_accessor.t
>  1..2
>  ok 1 - genreid is NULL
>  ok 2 - genre accessor returns undef
>
>  --- output of test using DBIx::Class from svn ---
>
>  $ PERL5LIB=t/lib:lib/ perl t/broken_single_accessor.t
>  1..2
>  ok 1 - genreid is NULL
>  not ok 2 - genre accessor returns undef
>  #   Failed test 'genre accessor returns undef'
>  #   at t/broken_single_accessor.t line 17.
>  # Looks like you failed 1 test of 2.
>

--- snip --- snip --- snip ---

Index: t/broken_single_accessor.t
===================================================================
--- t/broken_single_accessor.t	(revision 0)
+++ t/broken_single_accessor.t	(revision 0)
@@ -0,0 +1,18 @@
+use strict;
+use warnings;
+
+use Test::More;
+use lib qw(t/lib);
+use DBICTest;
+
+plan tests => 2;
+
+my $schema = DBICTest->init_schema();
+
+my $artist = $schema->resultset('Artist')->create({ artistid => 666,
name => 'bad religion' });
+my $genre = $schema->resultset('Genre')->create({ name => 'disco' });
+my $cd = $schema->resultset('CD')->create({ cdid => 187, artist => 1,
title => 'how could hell be any worse?', year => 1982 });
+
+ok(!defined($cd->genreid), 'genreid is NULL');
+ok(!defined($cd->genre), 'genre accessor returns undef');
+
Index: t/lib/sqlite.sql
===================================================================
--- t/lib/sqlite.sql	(revision 4250)
+++ t/lib/sqlite.sql	(working copy)
@@ -90,10 +90,19 @@
   cdid INTEGER PRIMARY KEY NOT NULL,
   artist integer NOT NULL,
   title varchar(100) NOT NULL,
-  year varchar(100) NOT NULL
+  year varchar(100) NOT NULL,
+  genreid integer
 );

 --
+-- Table: genre
+--
+CREATE TABLE genre (
+  genreid INTEGER PRIMARY KEY NOT NULL,
+  name varchar(100) NOT NULL
+);
+
+--
 -- Table: bookmark
 --
 CREATE TABLE bookmark (
Index: t/lib/DBICTest/Schema/CD.pm
===================================================================
--- t/lib/DBICTest/Schema/CD.pm	(revision 4250)
+++ t/lib/DBICTest/Schema/CD.pm	(working copy)
@@ -20,6 +20,9 @@
     data_type => 'varchar',
     size      => 100,
   },
+  'genreid' => {
+    data_type => 'integer'
+  }
 );
 __PACKAGE__->set_primary_key('cdid');
 __PACKAGE__->add_unique_constraint([ qw/artist title/ ]);
@@ -45,4 +48,9 @@
     { order_by => 'producer.name' },
 );

+__PACKAGE__->add_relationship('genre', 'DBICTest::Schema::Genre',
+    { 'foreign.genreid' => 'self.genreid' },
+    { 'accessor' => 'single' }
+);
+
 1;
Index: t/lib/DBICTest/Schema/Genre.pm
===================================================================
--- t/lib/DBICTest/Schema/Genre.pm	(revision 0)
+++ t/lib/DBICTest/Schema/Genre.pm	(revision 0)
@@ -0,0 +1,11 @@
+package DBICTest::Schema::Genre;
+
+use strict;
+
+use base 'DBIx::Class::Core';
+
+__PACKAGE__->table('genre');
+__PACKAGE__->add_columns(qw/genreid name/);
+__PACKAGE__->set_primary_key('genreid');
+
+1;
Index: t/lib/DBICTest/Schema.pm
===================================================================
--- t/lib/DBICTest/Schema.pm	(revision 4250)
+++ t/lib/DBICTest/Schema.pm	(working copy)
@@ -11,6 +11,7 @@
   Employee
   CD
   FileColumn
+  Genre
   Link
   Bookmark
   #dummy

--- snip --- snip --- snip ---



More information about the DBIx-Class mailing list