[Dbix-class] Bug with relationships on new objects.

brett gardner brett at clientcomm.com.au
Fri Jan 25 01:41:55 GMT 2008


Matt S Trout wrote:
> Which is, as I said, nothing to do with new vs. inflate_result.
>
> If you pass 'col =3D> undef' to new(), you get the fk =3D NULL.
>
> If you use the 'columns' resultset attr to restrict the col set to not
> include the column, you get the 'column does not exist'[0] behaviour.
>
> But all this is academic; if !has_column_loaded we should just be throwing
> an exception, not creating the resultset anyway.
>
> Who fancies having a go at a patch? :)
>
> [0] which you call 'column is not set', which is almost accurate but not
> quite :)
>
>   =

Right, well I wrote a patch (attached) that fixes the problem, but then =

running the test harness showed a problem as it breaks the behaviour.

my $artist =3D $schema->resultset('Artist')->create({
    name=3D>'foo',
    cds=3D>[
     {title=3D>'foo',year=3D>2000},
     {title=3D>'bar',year=3D>2000},
    ]
);

The "new" method in "Row.pm" creates a new "Artist" and calls =

"new_related" for each of the "cds". Then when "insert" is called on the =

"Artist", it updates the related objects' "artistid" column and calls =

"insert" on each related object.

So the patch breaks this behaviour.

Brett


-------------- next part --------------
Index: 0.09/trunk/t/66relationship.t
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- 0.09/trunk/t/66relationship.t	(revision 3972)
+++ 0.09/trunk/t/66relationship.t	(working copy)
@@ -7,7 +7,7 @@
 =

 my $schema =3D DBICTest->init_schema();
 =

-plan tests =3D> 62;
+plan tests =3D> 63;
 =

 # has_a test
 my $cd =3D $schema->resultset("CD")->find(4);
@@ -211,6 +211,10 @@
 is($def_artist_cd->has_column_loaded('artist'), 1, 'FK loaded');
 is($def_artist_cd->search_related('artist')->count, 0, 'closed search on n=
ull FK');
 =

+my $undef_artist =3D $schema->resultset('Artist')->new_result({name=3D>'fo=
o'});
+eval{$undef_artist->search_related('cds')};
+ok($@,'search_related where relationship requires primary key to be set th=
rows exception');
+
 # test undirected many-to-many relationship (e.g. "related artists")
 my $undir_maps =3D $schema->resultset("Artist")->find(1)->artist_undirecte=
d_maps;
 is($undir_maps->count, 1, 'found 1 undirected map for artist 1');
Index: 0.09/trunk/lib/DBIx/Class/ResultSource.pm
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- 0.09/trunk/lib/DBIx/Class/ResultSource.pm	(revision 3972)
+++ 0.09/trunk/lib/DBIx/Class/ResultSource.pm	(working copy)
@@ -778,7 +778,7 @@
 =

 sub resolve_condition {
   my ($self, $cond, $as, $for) =3D @_;
-  #warn %$cond;
+
   if (ref $cond eq 'HASH') {
     my %ret;
     foreach my $k (keys %{$cond}) {
@@ -789,8 +789,16 @@
       $v =3D~ s/^self\.// ||
         $self->throw_exception("Invalid rel cond val ${v}");
       if (ref $for) { # Object
+        my $loaded =3D $for->has_column_loaded($v);
+        if (! $loaded){
+            for ($for->result_source->primary_columns){
+                if ($v eq $_){
+                    $self->throw_exception('Calling a relationship on a ro=
w with no primary key');
+                }
+            }
+        }
         #warn "$self $k $for $v";
-        $ret{$k} =3D $for->get_column($v) if $for->has_column_loaded($v);
+        $ret{$k} =3D $for->get_column($v) if $loaded;
         #warn %ret;
       } elsif (!defined $for) { # undef, i.e. "no object"
         $ret{$k} =3D undef;


More information about the DBIx-Class mailing list