Class::DBI::Loader suggestion

[prev] [thread] [next] [Date index for 2004/06/30]

From: Gabriel Horner
Subject: Class::DBI::Loader suggestion
Date: 06:36 on 30 Jun 2004
To whomever uses Class::DBI::Loader,
    I, like a few other Postgres users, came across two stumbling blocks
when trying to use  Class::DBI::Loader. While fixing them (I'll send a
patch soon), I noticed that CDBI::Loader tries loading all tables in a database.
Wouldn't it be more helpful if you could specify only certain tables to load?
This not only would help the probability of more successful installs but would also help
for cases where one has many tables in a database or has a few Class::DBI uncompliant tables
in a database.

Here's what you'd have to do to implement this:
1. Add an extra tables_to_load attribute to the CDBI::Loader::Generic object
2. Change the logic of the subclassed modules' _load_classes() so that 
it iterates over specific tables if they're defined.

I'm sending this to the author as well but am wondering if others' would like to see something like
this.

I'm including a script below which does allow defining only certain tables.
I also redefined _load_classes() so that it could be called from the script to load
additional tables when needed.
I could give the changes in patch form if we'll upgrade the modules but I
thought it'd be easier to run this script than patch and unpatch CDBI::Loader

Later,
Gabriel

        -- 
        my looovely website -- http://www.chwhat.com
BTW, IF chwhat.com goes down email me at gabriel.horner@xxxx.xx


#!/usr/bin/perl

#overload Class::DBI::Loader so that new() will call local class
package CDBIL;
sub new {
	my($class, %args) = @_;
	my $dsn = $args{dsn};
	my($driver) = $dsn =~ m/^dbi:(\w*?)(?:\((.*?)\))?:/i;
	#changed to local class
	my $impl = "CDBIL::". $driver;
	eval qq/use $impl/;
	return $impl->new(%args);
}

#overload _load__classes and new
package CDBIL::Pg;
use base 'Class::DBI::Loader::Pg';
#new() should be redefined in Class::DBI::Loader::Generic
sub new {
    my($class, %args) = @_;
    my $self = bless {
	_datasource => [ $args{dsn}, $args{user}, $args{password}, $args{options}],
	_namespace => $args{namespace},
	CLASSES => {},
	#extra property
	tables_to_load=>$args{tables}
    }, $class;
    $self->_load_classes(@{$self->{tables_to_load}});
    $self;
}

#function can now be called from script to load more functions later
sub _load_classes {
    my ($self,@tables) = @_;
    my $dbh = DBI->connect(@{$self->_datasource}) or _croak($DBI::errstr);
    #if no tables given then default behavior is to load all tables in a database  
    @tables = (exists $tables[0]) ? @tables : $dbh->tables;

    foreach my $table(@tables) {
	#avoid calling inner postgres tables
	next if ($table =~/^pg_catalog/);	    
	#make table name compatible with Class::DBI::Pg
	$table =~ s/^public\.//g;
	#print "t: $table\n";
	my $class = $self->_table2class($table);
	no strict 'refs';
	@{"$class\::ISA"} = qw(Class::DBI::Pg);
	$class->set_db(Main => @{$self->_datasource});
	$class->set_up_table($table);
	$self->{CLASSES}->{$table} = $class;
    }
    $dbh->disconnect;
}


package main;

my $loader = CDBIL->new(
	dsn => "dbi:Pg:dbname=useful",
	user => "bozo",
	password => "bozo",
	tables=>[qw/cmds bmark/],
	namespace => "Data",
);
print "loaded tables are ",join(',',$loader->tables),"\n";
$loader->_load_classes('files');
print "loaded tables are ",join(',',$loader->tables),"\n";

Class::DBI::Loader suggestion
Gabriel Horner 06:36 on 30 Jun 2004

Re: Class::DBI::Loader suggestion
Andreas Fromm 07:11 on 30 Jun 2004

Generated at 11:34 on 01 Dec 2004 by mariachi v0.52