[ABE.pm] subclassing the DBI
Phil Lawrence
phil at five-lawrences.com
Sun Jun 11 20:51:07 PDT 2006
On May 22, 2006, at 9:09 PM, Faber J. Fedor wrote:
> ... What I was trying to do was to build on the $self
> object, i.e. my base class defines $self->{date}, $self->{template},
> etc. which all of the derived classes need. Then each derived class
> adds to $self the variables the derived class needs. This way I don't
> need to call '$dbh = get_dbh()' in every function that needs to do
> a SQL
> stmt (which are quite a few).
OK, I found an example of subclassing the DBI. Read the comments in
the connect method below.
package DBIx::DLM;
use strict;
use diagnostics;
use base DBI;
use File::Basename;
use DBD::CSV;
sub selectall_hashref
{
my $self = shift;
my $statement = shift or die;
my $key_field = shift or die;
# adjust self as necessary :-)
$self->_adjust( \$statement, shift() );
return $dbh->selectall_hashref( $statement, $key_field, undef, @_ );
}
sub connect
{
# Note that other classes may inherit and use this method only if
they also
# subclass DBIx::DLM::db and DBIx::DLM::st in the same manner that
DBIx::DLM
# subclasses DBI::db and DBI::st. See ./t/subclass.t in the DBI
install
# directory for the basic example of subclassing the DBI from which
this
# module was modelled.
my $proto = shift;
my $class = ref($proto) || $proto;
# Tell the DBI that $class is a new 'root class'. This enables DBI to
# bless our object for us. In other words, the constructor for our
class
# is in the DBI package!
$class->init_rootclass;
my $parm_href = shift;
# set defaults, unless invocant has alreay set them
# (see perldoc DBD::CSV for all possible attrs)
for
(
[ 'eol' => "\n" ]
, [ 'sep_char' => "\t" ]
, [ 'quote_char' => undef ]
, [ 'escape_char' => undef ]
, [ 'FetchHashKeyName' => undef ]
)
{
unless (defined $parm_href->{$_[0]})
{
$parm_href->{$_[0]} = $_[1] if defined $_[1];
}
}
# get default dbh
my $dbh = $class->connect('DBI:CSV:');
# turn on the trace first, if so requested
if (defined $parm_href->{trace})
{
$dbh->trace( $parm_href->{trace} );
}
# use any $parm key/value pairs (with scalar values) to set dbh
defaults
for (keys %{$parm_href})
{
# already took care of tracing
next if /trace/;
unless (ref $parm_href->{$_})
{
# since we'll blindly try any attr, we'll
# catch errors and just put them in the
# trace, then move on
eval { $dbh->{$_} = $parm->{$_} };
$dbh->trace( "Warning: $@") if $@;
}
}
return $dbh;
}
sub _adjust
{
my $self = shift;
my $statement = ${ shift };
my $parm_href = shift;
my ($select, $remaining) = split /FROM/i, $statement;
(my $from, $remaining) = split /WHERE/i, $remaining;
my @tables = split /,/, $from;
for (@tables)
{
# if any unusual characters
if (/\W/)
{
die "$_ not valid filename" unless (-f $_);
my ($name,$path,$suffix) = fileparse( $_, qr/\W.+/ );
die unless defined $name;
$parm_href->{table}{$name}{_pns}{path} = defined $path
? $path
: ''
;
$parm_href->{table}{$name}{_pns}{suffix} = defined $suffix
? $suffix
: ''
;
# use slimmed-down table name
$_ = $name;
}
else
{
$parm->{table}{$_}{_pns}{path} = '';
$parm->{table}{$_}{_pns}{suffix} = '';
}
}
# rebuild $statement with slimmed-down table names, instead of whatever
# was passed in (e.g. filenames with path)
$statement = $select . 'FROM' . join(',', at tables) . $remaining;
# override dbh defaults on a per table basis
for (keys %{$parm_href->{table}})
{
$dbh->{'csv_tables'}{$_}{file} = $parm_href->{table}{$_}{_pns}{path}
. $_
. $parm_href->{table}{$_}{_pns}{suffix}
;
# any of these default attrs may be overridden by invocant
for my $attr ($parm_href->{table}{$_})
{
# only non-ref attributes can be set. This
# distinguishes from the stuff we jam into
# $parm_href and those things the invocant
# has passed along.
next if ref $parm_href->{table}{$_}{$attr};
$dbh->{'csv_tables'}{$_}{$attr} = $parm_href->{table}{$_}{$attr}
unless defined $dbh->{'csv_tables'}{$_}
{$attr};
}
}
return $dbh;
}
#=======================================================================
========
package DBIx::DLM::db;
use DBI;
use vars qw( @ISA );
push @ISA, 'DBI::db';
#=======================================================================
========
package DBIx::DLM::st;
use DBI;
use vars qw( @ISA );
push @ISA, 'DBI::st';
1;
More information about the ABE-pm
mailing list