[Dbix-class] inheritance problem?

Rob Kinyon rob.kinyon at gmail.com
Tue Sep 26 02:45:45 CEST 2006


On 9/25/06, Alan Humphrey <alan.humphrey at comcast.net> wrote:
> Actually, looking at this again, I'm pretty sure it's right: neither
> DBIx::Class::Storage::DBI::Sybase::MSSQL nor its parent classes
> override _execute.
>
> NoBindVars does its work in _prep_for_execute, so I'd expect that a
> ->can on that would refer there.
>
> >>
> I found the problem, but I don't know what the solution is.
>
> The problem is in the multiple inheritance of Sybase::MSSQL:
>
> use base qw/DBIx::Class::Storage::DBI::MSSQL
> DBIx::Class::Storage::DBI::Sybase/;
>
> When _execute is called (which is what NoBindVars overrides) Perl looks
> first in DBI::MSSQL.  Having no luck there, Perl goes *up* a level to DBI
> finds the method and stops.  (Thanks to Conway's "Object Oriented Perl" for
> pointing this out.  He says it's "left-most ancestor wins".)
>
> If you swap the class names in the use statement:
>
> use base qw/DBIx::Class::Storage::DBI::Sybase
> DBIx::Class::Storage::DBI::MSSQL/;
>
> Then the correct _execute is found.  However, you now get the wrong version
> of last_insert_id and build_datetime_parser (methods overridden by
> DBI::MSSQL).
>
> So now the question is: how do you do multiple inheritance in Perl such that
> both parent classes can override the grandparent?

You're looking for C3 inheritance which works using Manhattan distance
vs. left-most-ancestor.

Alternately, create an intermediary baseclass that aliases (using
globbing*) the appropriate methods to the right parent class methods.
@ISA (which is what "use base" manipulates) is not going to be the
right solution here.

Rob

* An example of this would be:

    *execute = \&DBIx::Class::DBI::Sybase::execute;
    *last_insert_id = \&DBIx::Class::DBI::MSSQL::last_insert_id;

This is not very resistant to change, but is worth looking into for
relatively static scenarios.



More information about the Dbix-class mailing list