[Dbix-class] create without setting a nullable foreign key,
then accessing relationship
Adam Sjøgren
adsj at novozymes.com
Wed Jun 11 12:35:57 BST 2008
Hi.
If I create a new row in the database, in a table that has an optional
foreign key, which isn't filled in in the create-call, and then call the
belongs_to relationship accessor on the resulting object, I get an
object back for the foreign key, when I use DBIx::Class 0.08008; I
didn't in 0.08007.
I am wondering whether this is expected behaviour?
Abbreviated example:
# fleet_id not filled in when calling create:
my $car2=$schema->resultset('CarDB::Car')->create({
id=>2,
plate=>'BBB 202',
});
my $fleet2=$car2->fleet; # Searches fleet table with no WHERE clause
print defined $fleet2 ? "Fleet returned, car2\n" : "No fleet returned, car2\n";
prints "Fleet returned, car2" (full example below).
I have bisected my way to r3804 introducing this change, but I am not
exactly sure what the correct cure is, if it is indeed wrong.
This has been discussed on the mailinglist before, Damon Snyder asked
about it in:
<http://article.gmane.org/gmane.comp.lang.perl.modules.dbix-class/5331>
and mike provided a test-patch in:
<http://article.gmane.org/gmane.comp.lang.perl.modules.dbix-class/5443>.
The test-patch broke some other patches, so I posted an updated patch
that doesn't:
<http://article.gmane.org/gmane.comp.lang.perl.modules.dbix-class/5653>
It probably went unnoticed because of the age of the thread.
Here is the output of the full example included below with different
versions of DBIx::Class:
0.08007
Fleet returned, car1
No fleet returned, car2
What I expected.
0.08008
Fleet returned, car1
Fleet returned, car2
Not what I expected. Finally, latest svn 0.08/trunk:
0.0809902
Fleet returned, car1
DBIx::Class::Relationship::Accessor::__ANON__(): Query returned more than one row. SQL that returns multiple rows is DEPRECATED for ->find and ->single at test.pl line 26
Fleet returned, car2
Now with a warning.
Example files:
test.pl:
--------
#!/usr/bin/perl
use warnings;
use strict;
use CarDB;
print $DBIx::Class::VERSION . "\n";
my $schema=CarDB->connect('dbi:Pg:dbname=cardb', 'adsj', 'adsj', { AutoCommit=>1 });
my $car1=$schema->resultset('CarDB::Car')->create({
id=>1,
plate=>'AAA 101',
fleet_id=>1,
});
my $fleet1=$car1->fleet;
print defined $fleet1 ? "Fleet returned, car1\n" : "No fleet returned, car1\n";
my $car2=$schema->resultset('CarDB::Car')->create({
id=>2,
plate=>'BBB 202',
});
my $fleet2=$car2->fleet;
print defined $fleet2 ? "Fleet returned, car2\n" : "No fleet returned, car2\n";
run (I am using PostgreSQL):
----------------------------
#!/bin/sh
dropdb -U adsj cardb 2> /dev/null
createdb -U adsj cardb 2> /dev/null
psql -U adsj cardb < init.sql 2> /dev/null > /dev/null
perl test.pl
init.sql:
---------
CREATE TABLE fleet (
id integer NOT NULL,
company text NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE car (
id integer NOT NULL,
plate text NOT NULL,
fleet_id integer REFERENCES fleet, -- optional foreign key
PRIMARY KEY (id)
);
INSERT INTO fleet (id, company) VALUES (1, 'Hertz');
INSERT INTO fleet (id, company) VALUES (2, 'Avis');
CarDB.pm:
---------
package CarDB;
use strict;
use warnings;
use base qw(DBIx::Class::Schema);
__PACKAGE__->load_classes();
1;
CarDB/Car.pm:
-------------
package CarDB::Car;
use strict;
use warnings;
use base qw(DBIx::Class);
__PACKAGE__->load_components('PK::Auto', 'Core');
__PACKAGE__->table('car');
__PACKAGE__->add_columns(qw(id plate fleet_id));
__PACKAGE__->set_primary_key('id');
# fleet_id may be NULL (car does not belong to any fleet, yet):
__PACKAGE__->belongs_to(fleet=>'CarDB::Fleet', 'fleet_id');
1;
CarDB/Fleet.pm:
---------------
package CarDB::Fleet;
use strict;
use warnings;
use base qw(DBIx::Class);
__PACKAGE__->load_components('PK::Auto', 'Core');
__PACKAGE__->table('fleet');
__PACKAGE__->add_columns(qw(id company));
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many(cars=>'CarDB::Car', 'fleet_id');
1;
Best regards,
Adam
--
Adam Sjøgren
adsj at novozymes.com
More information about the DBIx-Class
mailing list