I am writing a wrapper class that wraps DBI and adds additional functionality. I'd like it to have all the methods of a database handle; since those aren't directly in the DBI module, inheritance seems like the wrong approach (though I'd be happy to learn otherwise).

So, I've been cutting my teeth on AUTOLOAD. Here's a super-simple chunk of code:

package TestModule; require DBI; use AutoLoader; use base 'Class::Base'; sub AUTOLOAD { my $op = $AUTOLOAD; $op =~ s/^.*:://; if ( DBI::db->can($op) ) { eval "sub $op { my \$self=shift; $self->{DBH}->$op(\@_); }"; } else { eval "sub $op { return shift->error('Cannot autoload $op'); }" +; } } sub new { # new ( $dsn[, $user[, $pass]] ) my $self = shift; return undef unless @_; my @args = @_; my $obj = {}; eval { $obj->{DBH} = DBI->connect(@args); }; if ($@) { return $self->error("Unable to connect to DB: $@"); } bless $obj, $self; }

However, the following fails (I connect to a real DB for this test, and the SQL is valid):

use Test::More tests => 9; # ... snipped setup of $obj = new & etc. my $sth = $obj->prepare('SELECT * FROM test_table'); can_ok($obj, 'prepare'); #succeeds! # this fails: isnt ($sth, undef, 'prepare creates statement handle');

This suggests that AUTOLOAD's actually creating a sub prepare with stuff in it, but that it isn't working. When I manually create a prepare sub (i.e. bypass AUTOLOAD) with the same content, it works fine.

At this point, I don't even understand where I'm going wrong. Any help with this (including simpler approaches, etc.) would be most welcome. What I want to avoid, though, is having to write a myriad little subs that wrap the equivalent database handle methods.

Also, even if AUTOLOAD isn't the correct solution for this problem, I'd still like to know how to wield it, so any tips in that direction will be welcome regardless.

Thanks in advance!

Update: yosefm weighed in quickly, and with the correct answer! My new AUTOLOAD sub:

sub AUTOLOAD { my $op = $AUTOLOAD; $op =~ s/^.*:://; if ( DBI::db->can($op) ) { eval "sub $op { return shift->{DBH}->$op(\@_); }"; $op->(@_); } else { eval "sub $op { return shift->error('Cannot autoload $op'); }" +; } }

The above had bugs, here's what works today:

# sets up autoload subs that 'inherit' DBI's DBH methods sub AUTOLOAD { my $op = $AUTOLOAD; my $self = shift; $op =~ s/^.*:://; if ( DBI::db->can($op) ) { # create a wrapper for a DBH method eval "sub $op { return shift->{DBH}->$op(\@_); }"; $op->($self, @_); } elsif ( $op =~ /^_/ ) { # return the appropriate attribute $op =~ s/^_//; exists $self->{$op} && return $self->{$op}; return $self->error("Can't autoload for attribute _$op"); } else { return $self->error("Cannot autoload $op"); } }

It helps to actually call the subroutine after creating it... big D'OH for me.

Updates:

<-radiant.matrix->
A collection of thoughts and links from the minds of geeks
The Code that can be seen is not the true Code
"In any sufficiently large group of people, most are idiots" - Kaa's Law

In reply to Using AUTOLOAD to create class methods by radiantmatrix

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.