I'm having a little trouble with subclassing DBI
when used with Oracle. After upgrading DBI and DBI::Oracle
the other day, some code I was working on no longer worked.
I'm rather new to using Perl in an OOP way, and am doing
so only at the simplest levels rigth now.
Below is some code from a module that I am using to subclass
the DBI::connect method when used with Oracle.
This code has been reduced to just the relevant bits. Sorry
if it's still kind of large. The problems I'm having with it
are detailed in the comments, and more text below the code.
...
require DBI;
@ISA=qw(DBI DBI::db DBI::st);
use Carp;
use strict;
use warnings;
use diagnostics;
sub new {
my $pkg = shift;
my $class = ref($pkg) || $pkg;
my ( %args ) = @_;
my $connectionMode = 0;
if ( exists( $args{MODE} )) {
if ( $args{MODE} eq 'SYSOPER') { $connectionMode = 4 }
if ( $args{MODE} eq 'SYSDBA' ) { $connectionMode = 2 }
}
my $dbh = $class->SUPER::connect(
'dbi:Oracle:' . $args{DATABASE},
$args{USERNAME}, $args{PASSWORD},
{
RaiseError => 1, AutoCommit => 0 ,
ora_session_mode => $connectionMode
}
);
croak "Connect to $args{USERNAME} failed \n" unless $dbh;
# blessing $dbh into a class works with
# DBI 1.13 and DBD::Oracle 1.08
# works as expected.
# when DBI is upgraded to 1.20 and DBD::Oracle to 1.12,
# this no longer works and you must just return the dbh
# handle. Do not know why yet.
# DBI 1.13; DBD::Oracle 1.08
my $connection = bless $dbh, $class;
return $connection;
# works with all, and the only way to do it
# with DBI 1.20 and DBD::Oracle 1.08 and newer
#return $dbh;
}
Here's an example of making a connection with this method
and then disconnecting:
my $dbh = new PDBA::CM(
DATABASE => 'ts01',
USERNAME => 'scott',
PASSWORD => 'tiger',
);
$dbh->disconnect;
This worked fine on older versions of DBI 1.13 and DBD::Oracle 1.08
With DBI 1.20 and DBD::Oracle 1.12 however, the following error message
is thrown upon disconnect when the connection module returns a blessed
$connection:
Uncaught exception from user code:
DBI->disconnect is not a DBI method. Read the DBI manual. at test.pl line
37
Carp::croak('DBI->disconnect is not a DBI method. Read the DBI manual.')
called at /usr/lib/perl5/site_perl/5.6.0/i586-linux/DBI.pm line 474
DBI::disconnect('PDBA::CM=HASH(0x83520ac)') called at test.pl line 37
Issuing rollback() for database handle being DESTROY'd without explicit
disconnect() at /usr/lib/perl5/5.6.0/Carp.pm line 119.
make: *** [test_dynamic] Error 255
The workaround for this is to return the handle $dbh rather than the
blessed handle as I had done before, which interestingly enough seems
to work for all versions of DBI/DBD::Oracle that I have tried.
If I'm just doing something wrong here, I'm sure someone will take
the opportunity to correct me. :)
TIA
Jared