Tim Bunce wrote:

On Wed, Aug 03, 2005 at 05:29:28PM -0700, Dean Arnold wrote:

Since I've forgotten about this only a few dozen times now,
I'll offer this bit of text for future inclusion in the
DBI POD (where to put it, and the exact text, I'll leave
to the keepers):

B<Note> that DBI subclasses are not strictly inherited
subclasses in the classic OO sense. Your subclassed driver,
connection, and statement objects B<must> be derived
through the DBI at some point in order to acquire some
neccesary "magic" needed for any methods not explicitly
overridden in your subclass, or for any methods invoked on
the SUPER class. If you see errors like the following:

        SV = PVMG(0x39ca0a4) at 0x1d1d8f0
          REFCNT = 1
          FLAGS = (ROK)
          IV = 0
          NV = 0
          RV = 0x24b24b8
          PV = 0x24b24b8 ""
          CUR = 0
          LEN = 0
        dbih_getcom handle MyDBI::db=HASH(0x24b24b8) is not a DBI handle
        (has no magic) at ....

your object probably hasn't been derived through the appropriate
base class.


Could you make that a little more explicit? Including how to fix it.

Expressing it as a clarification/extension of the "Subclassing the DBI"
section of the docs would be good:
  http://search.cpan.org/~timb/DBI/DBI.pm#Subclassing_the_DBI

Tim.

p.s. I'm not making any suggestions here to avoid distorting your thinking :)


Distort away!

As to a fix: it would probably help if there were some API provided
so I could "conjure" my objects such that the above error didn't
occur when base class methods were invoked - assuming the magic is not too
heavyweight. My particular problem is that DBIx::Threaded objects need
to be curse()'d and redeem()'d between threads, so they need to be
fairly lightweight. Plus, I never call a SUPER::connect or SUPER::prepare
when manufacturing objects. If I can just "$self->SUPER::conjure()"
at new() and redeem() time to recover the magic (this is starting to sound like
a scene from LOTR...), that would be great.

As to the docs: Not certain what to say. My example of classic OO
inheritance is

package BaseClass;

sub new {
        return bless {}, shift;
}

sub over_ride {
        my $self = shift;
        return $self->do_something();
}

package SubClass;

use base qw(BaseClass);

sub new {
        return bless (), shift;
}

sub over_ride {
        my $self = shift;
        $self->SUPER::over_ride();
        return $self->do_something_else();
}

package main;

my $subclass = SubClass->new();

$subclass->over_ride();

__END__

Note that SubClass's constructor never has to explicitly
touch SUPER. For DBI subclasses, that is not currently the case,
since the objects need to acquire DBI magic. So when I
applied the usual subclassing for DBIx::Threaded, using
my own constructors for dr/db/st, I ran into the aforementioned
problems when invoking SUPER methods.

So I guess maybe the following exemplar would work:

WRONG SUBCLASS:

package MyDBI::dr;

use base qw(DBI::dr);

sub new {
#
#       doesn't acquire DBI magic!
#
        my $class = shift;
        return bless { }, $class;
}

sub connect {
        my $dr = shift;
        return MyDBI::db->new(@_);
}

package MyDBI::db;

use base qw(DBI::dr);

sub new {
        my ($class, $dsn, $user, $pass, $attrs) = @_;
#
#       doesn't acquire DBI magic!
#
        my $dbh = {};
        bless $dbh, $class;
        ...do connect() stuff...
        return $dbh;
}

RIGHT SUBCLASS:

<insert existing POD example here>

Reply via email to