Class::DBI, Postgrsql and mod_perl
Recently I tried to use Class::DBI – one of the best Perl frameworks to create a persistent objects – with Postgresql and I faced with big problem. After the second or third request to the database it gave me an error:
Can't use an undefined value as an ARRAY reference at Class/DBI.pm line 1125
It was very strange for me because I used Class::DBI with Mysql in the three projects and I didn’t have any problems with Class::DBI. I made a search of this error and I was very surprised because I found just a couple of pages in Google. It seems that Class::DBI and Postgresql are used together rarely.
However, the suggestions of Perrin Harkins helped me to solve my problem. As I understand Class::DBI cannot work properly together with Apache::DBI in case transaction database.
To use Class::DBI into your classes you have to create a base class which inherits Class::DBI, inherited by all your classes and defined connection to the database:
__PACKAGE__->set_db('Main',
'dbi:' . $config->{'database'}->{'dbtype'} . ':database=' . $config->{'database'}->{'database'},
$config->{'database'}->{'username'},
$config->{'database'}->{'password'}, $attrs
);
In case of using Postgresql the base class should override the method db_Main from class Ima::DBI to avoid the conncetion error:
# Connection attributes
my $attrs = {
PrintError => 0,
RaiseError => 1,
AutoCommit => 1,
timeout => 1000,
};
sub db_Main {
my $dbh;
if ( $ENV{'MOD_PERL'} and !$Apache::ServerStarting ) {
$dbh = Apache2::RequestUtil->request->pnotes('dbh');
}
if ( !$dbh ) {
$dbh = DBI->connect_cached(
'dbi:' . $config->{'database'}->{'dbtype'} . ':database=' . $config->{'database'}->{'database'},
$config->{'database'}->{'username'},
$config->{'database'}->{'password'}, $attrs
);
if ( $ENV{'MOD_PERL'} and !$Apache::ServerStarting ) {
Apache2::RequestUtil->request->pnotes( 'dbh', $dbh );
}
}
return $dbh;
}
Note: calling the method set_db() is not needed in the base class!
Also, you should override dbi_commit():
sub dbi_commit {
my $self = shift;
$self->db_Main()->commit();
}
and dbi_rollback()
sub dbi_rollback {
my $self = shift;
$self->db_Main()->rollback();
}
because Ima::DBI nothing knows about them.