Subject: | Object not stored in objct index when created if PK comes from a sequence. |
This is from a mail I sent to the CDBI mailing list yesterday.
Hello,
a while back I posted a test script (attached) that showed up a bug in
the object index that means that a new row whose PK comes from a
sequence is not added to the index correctly, although this may only
affect users of postgres. In the thread that followed a solution came
to light that fixes this problem in 3.0.12:
# Line 578 or so of Class/DBI.pm 3.0.14
# now that we have a complete primary key, add this to the
# object index
if ( $Weaken_Is_Available ) {
$self = $class->_init( $self );
}
Could this fix be added to the next release. Currently it very
difficult to work with CDBI and new objects, especially in tests where
you create one, change it and then find that it does not work.
The previous discussion is archived here:
http://lists.digitalcraftsmen.net/pipermail/classdbi/2005-November/000514.html
Cheers,
Edmund.
Subject: | class-dbi-sequence-object-index-bug.t |
# This is a test to show unexpected behaviour with relation to 'only
# one object in memory'. If a row is added to the database and the
# value of it's primary key comes from a sequence then it is not
# fetched properly from the object cache. The same behaviour is not
# shown if a value is explicitly given for the primary key. I think
# this is the problem anyway...
# The tests below assume that there is a postgres database 'cdbi_test'
# - SQLite does not have sequences and so I don't think that these
# tests can be run against it.
# Please let me know if there is anything else that I can do to help
# you withthis bug ( at least I think it is a bug ).
# Edmund von der Burg
# evdb@ecclestoad.co.uk
# http://ecclestoad.co.uk
# see:
# http://lists.digitalcraftsmen.net/pipermail/classdbi/2005-November/000514.html
# for more details.
use strict;
use warnings;
use Data::Dumper;
use Test::More 'no_plan';
############################################################################
package CDBI;
use base 'Class::DBI';
CDBI->connection("dbi:Pg:dbname=cdbi_test");
CDBI->sequence('cdbi_id_seq');
############################################################################
package Parent;
use base 'CDBI';
use Data::Dumper;
Parent->table('parents');
Parent->columns( Primary => qw(cdbi_id) );
Parent->columns( Others => qw(name) );
Parent->has_many( children => 'Child' );
sub create_sql { '' }
############################################################################
package Child;
use base 'CDBI';
Child->table('children');
Child->columns( Primary => qw/cdbi_id/ );
Child->columns( Others => qw/parent/ );
Child->has_a( parent => 'Parent' );
sub create_sql { '' }
############################################################################
package main;
diag "\$Class::DBI::VERSION: '" . $Class::DBI::VERSION . "'";
create_tables();
for my $cdbi_id ( 1_000_000, undef ) {
diag "";
diag "using cdbi_id: ", defined $cdbi_id ? $cdbi_id : 'undef';
diag "";
# create a test parent.
my $parent =
Parent->create( { cdbi_id => $cdbi_id, name => 'test parent' } );
ok $parent, 'create test parent';
# create a test child.
my $child = Child->create( { parent => $parent, } );
ok $child, 'create test child';
# do a test to see if an update to the parent is reflected in the
# child's parent.
is $parent->name, $child->parent->name, "names the same";
ok $parent->name('new name'), "change name";
is $parent->name, $child->parent->name, "names the same";
ok $parent->update, "update";
is $parent->name, $child->parent->name, "names the same";
ok $parent->dbi_commit, "dbi_commit";
is( $parent->name, $child->parent->name, "names the same" )
|| diag Dumper {
'$parent' => $parent,
'$child->parent' => $child->parent
};
# Cleanup.
$parent->delete;
Parent->dbi_commit;
}
delete_tables();
CDBI->dbi_commit;
############################################################################
sub create_tables {
my $dbh = CDBI->db_Main;
$SIG{__WARN__} = sub { warn @_ unless $_[0] =~ m/^NOTICE/ };
# diag "Creating tables and sequence";
$dbh->do( <<"" );
create sequence cdbi_id_seq
$dbh->do( <<"" );
create table parents (
cdbi_id int8 primary key,
name text not null
)
$dbh->do( <<"" );
create table children (
cdbi_id int8 primary key,
parent int8 not null references parents
)
}
sub delete_tables {
my $dbh = CDBI->db_Main;
# diag "Destroying tables and sequence";
$dbh->do("drop table $_") for qw( children parents );
$dbh->do("drop sequence cdbi_id_seq");
}