[Melbourne-pm] Subclassing DBI

Jacinta Richardson jarich at perltraining.com.au
Sat Feb 11 20:11:09 PST 2006

> When I run the driver that uses TestLib::DBConn I get an error:
> DBI subclasses 'TestLib::DBConn::db' and ::st are not setup, RootClass
> ignored at ./test.pl line 98
> Any ideas as to how I could fix this?

The relevant code you're hitting is as follows:

# handle basic RootClass subclassing:
my $rebless_class = $attr->{RootClass} || ($class ne 'DBI' ? $class : '');
if ($rebless_class) {
    no strict 'refs';
    if ($attr->{RootClass}) {	# explicit attribute (rather than static call)
	delete $attr->{RootClass};
	DBI::_load_class($rebless_class, 0);
    unless (@{"$rebless_class\::db::ISA"} && @{"$rebless_class\::st::ISA"}) {
	Carp::carp("DBI subclasses '$rebless_class\::db' and ::st are not setup,
RootClass ignored");
	$rebless_class = undef;
	$class = 'DBI';
    else {
	$dbh->{RootClass} = $rebless_class; # $dbh->STORE called via plain DBI::db
	DBI::_set_isa([$rebless_class], 'DBI');     # sets up both '::db' and '::st'
	DBI::_rebless($dbh, $rebless_class);        # appends '::db'

sorry about the wrapping.  This means that DBI doesn't think that you've
subclassed it correctly.

Further, from the documentation at:
http://cpan.uwinnipeg.ca/htdocs/DBI/DBI.pm.html (Subclassing the DBI)

DBI can be subclassed and extended just like any other object oriented module.
Before we talk about how to do that, it's important to be clear about how the
DBI classes and how they work together.

By default $dbh = DBI->connect(...) returns a $dbh blessed into the DBI::db
class. And the $dbh->prepare method returns an $sth blessed into the DBI::st
class (actually it simply changes the last four characters of the calling handle
class to be ::st).

The leading 'DBI' is known as the 'root class' and the extra '::db' or '::st'
are the 'handle type suffixes'. If you want to subclass the DBI you'll need to
put your overriding methods into the appropriate classes. For example, if you
want to use a root class of MySubDBI and override the do(), prepare() and
execute() methods, then your do() and prepare() methods should be in the
MySubDBI::db class and the execute() method should be in the MySubDBI::st class.

So, your changes to connect should be in TestLib::DBConn::db.  If you don't want
to make any changes to DBI::st, just subclass it to get the name right.

If you have any other questions that aren't answered by that documentation, feel
free to ask!


   ("`-''-/").___..--''"`-._          |  Jacinta Richardson         |
    `6_ 6  )   `-.  (     ).`-.__.`)  |  Perl Training Australia    |
    (_Y_.)'  ._   )  `._ `. ``-..-'   |      +61 3 9354 6001        |
  _..`--'_..-_/  /--'_.' ,'           | contact at perltraining.com.au |
 (il),-''  (li),'  ((!.-'             |   www.perltraining.com.au   |

More information about the Melbourne-pm mailing list