develooper Front page | perl.perl5.porters | Postings from November 2003

DBI and UNIVERSAL::AUTOLOAD (was Re: [5.8.12] Proposal for changing UNIVERSAL semantics)

Thread Previous | Thread Next
From:
Michael G Schwern
Date:
November 4, 2003 14:21
Subject:
DBI and UNIVERSAL::AUTOLOAD (was Re: [5.8.12] Proposal for changing UNIVERSAL semantics)
Message ID:
20031104222012.GA15406@localhost.comcast.net
On Tue, Nov 04, 2003 at 03:26:16PM +0000, Tim Bunce wrote:
> I'm not convinced. Here's the code for can() that's embedded into the DBI
> dispatcher:

The existence of UNIVERSAL::AUTOLOAD is definately interfering.  Here's an 
example of running the test with a UNIVERSAL::AUTOLOAD that should be 
transparent.

$ cat /tmp/lib/Foo.pm
package Foo;

use Carp;
sub UNIVERSAL::AUTOLOAD {
    my $proto = shift;
    my $class = ref $proto || $proto;
    my($method) = $UNIVERSAL::AUTOLOAD =~ /([^:]+)$/;
    croak qq{Can't locate object method "$method" via package "$class"};
}

1;

$ perl5.8.1 -I/tmp/lib -MFoo -Mblib -w t/01basic.t
1..43
ok 1 at line 32
ok 2 at line 33
ok 3 at line 37
        (in cleanup) Can't locate object method "DESTROY" via package "IO::Handle" at t/01basics.t line 39
ok 4 at line 40
ok 5 at line 41
        (in cleanup) Can't locate object method "DESTROY" via package "IO::Handle" at t/01basics.t line 44
ok 6 at line 45
...normal test output...
ok 39 at line 104
        (in cleanup) Can't locate object method "DESTROY" via package "IO::Handle" at /usr/local/src/CPAN/DBI-1.38/blib/lib/DBI.pm line 930
ok 40 at line 108
ok 41 at line 109
        (in cleanup) Can't locate object method "DESTROY" via package "IO::Handle" at /usr/local/src/CPAN/DBI-1.38/blib/lib/DBI.pm line 930
ok 42 at line 111
ok 43 at line 112
Can't locate object method "disconnect_all" via package "DBI::dr" at /usr/local/src/CPAN/DBI-1.38/blib/lib/DBI.pm line 653
END failed--call queue aborted.
        (in cleanup) Can't locate object method "DESTROY" via package "DBI::dr" at t/01basics.t line 0
        (in cleanup) Can't locate object method "DESTROY" via package "DBI::var" at t/01basics.t line 0
        (in cleanup) Can't locate object method "DESTROY" via package "IO::Handle" at t/01basics.t line 0


The simplest bit to debug is the "disconnect_all" error.  Simply fire up
the test with the debugger and "c DBI::disconnect_all".  Once there
you can notice that can() says this:

DBI::disconnect_all(/usr/local/src/CPAN/DBI-1.38/blib/lib/DBI.pm:653):
653:            $drh->disconnect_all() if ref $drh;
  DB<2> x $drh->can('disconnect_all')
0  CODE(0x52387c)
   -> &CODE(0x52387c) in ???

and that code ref isn't the UNIVERSAL::AUTOLOAD

  DB<3> x $drh->can('AUTOLOAD')
0  CODE(0x2d70ec)
   -> &UNIVERSAL::AUTOLOAD in /tmp/lib/Foo.pm:4-9

but when we step into $drh->disconnect_all()...

  DB<4> s
UNIVERSAL::AUTOLOAD(/tmp/lib/Foo.pm:5):
5:          my $proto = shift;
  DB<4> T
$ = UNIVERSAL::AUTOLOAD(ref(DBI::dr)) called from file `/usr/local/src/CPAN/DBI-1.38/blib/lib/DBI.pm' line 653
$ = DBI::disconnect_all('DBI') called from file `/usr/local/src/CPAN/DBI-1.38/blib/lib/DBI.pm' line 477
$ = DBI::END() called from file `t/01basics.t' line 0
$ = eval {...} called from file `t/01basics.t' line 0

So something funky is going on.  can() says there's a method defined but
when you actually call it it goes into AUTOLOAD.  That ain't right.

Perhaps DBI's can() is reporting the empty disconnect_all() method but
your hacked^Waltered ;) method dispatcher is ignoring the empty subroutine 
and falling back to AUTOLOAD?


-- 
Michael G Schwern        schwern@pobox.com  http://www.pobox.com/~schwern/
If it's stupid, but it works, it isn't stupid.

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About