/usr/local/CPAN/DBR/DBR/Sandbox.pm
package DBR::Sandbox;
use strict;
use DBR;
use DBR::Util::Logger;
use DBR::Config::ScanDB;
use DBR::Config::SpecLoader;
use DBR::Config::Schema;
use Scalar::Util 'blessed';
use File::Path;
use Carp;
sub import {
my $pkg = shift;
my %params = @_;
my $dbr;
my ($callpack, $callfile, $callline) = caller;
if( $params{schema} ){
DBR::Sandbox->provision( %params );
}
}
my ($CONFDIR) = grep {-d $_ } ('schemas','example/schemas','../example/schemas');
sub provision{
$| = 1;
my $package = shift if blessed($_[0]) || $_[0] eq __PACKAGE__;
my %params = @_;
my $schema = $params{schema} or confess "schema is required";
my $sandbox = '_sandbox/' . $params{schema};
my $dbrconf = $params{writeconf} || "$sandbox/DBR.conf";
return if $params{reuse} && -e $dbrconf && -d $sandbox;
print STDERR "Provisioning Sandbox... " unless $params{quiet};
_ready_sandbox ( $sandbox );
my $metadb = _sqlite_connect( dbfile => "$sandbox/dbrconf.sqlite" );
my $maindb = _sqlite_connect( dbfile => "$sandbox/db.sqlite" );
_load_sqlfile ( "$CONFDIR/dbr_schema_sqlite.sql", $metadb );
_load_sqlfile ( "$CONFDIR/$schema/sql", $maindb );
_setup_metadb ( $sandbox, $schema, $metadb );
$metadb->disconnect();
$maindb->disconnect();
_write_dbrconf( $sandbox, $dbrconf );
my $logger = new DBR::Util::Logger( -logpath => '_sandbox/sandbox_setup.log', -logLevel => 'debug3' ) or die "logger create failed";
my $dbr = new DBR(
-logger => $logger,
-conf => $dbrconf,
-admin => 1,
-fudge_tz => 1,
) or die 'failed to create dbr object';
my $conf_instance = $dbr->get_instance('dbrconf') or die "No config found for confdb";
my $loader = DBR::Config::SpecLoader->new(
session => $dbr->session,
conf_instance => $conf_instance,
dbr => $dbr,
) or die "Failed to create spec loader";
my $spec = $loader->parse_file( "$CONFDIR/$schema/spec" ) or die "Failed to open $CONFDIR/$schema/spec";
$loader->process_spec( $spec ) or die "Failed to process spec data";
print STDERR "Done. \n\n" unless $params{quiet};
# returning DBR object to be used with test harnesses
return $dbr;
}
sub _ready_sandbox{
my $sandbox = shift;
File::Path::rmtree( $sandbox ) if -e $sandbox;
mkpath $sandbox or confess "failed to ready sandbox '$sandbox'";
}
sub _sqlite_connect {
my $attr = { @_ };
my $dbfile = delete $attr->{dbfile} || ':memory:';
my @params = ( "dbi:SQLite:dbname=$dbfile", '', '' );
if ( %$attr ) {
push @params, $attr;
}
my $dbh = DBI->connect( @params );
return $dbh;
}
sub _load_sqlfile{
my $file = shift;
my $dbh = shift;
my $fh;
open ($fh, "<$file") || return 0;
my $buff;
while (<$fh>){
$buff .= $_;
}
foreach my $part (split(';',$buff)){
next unless $part =~ /\S+/;
next if $part =~ /^\s*--/;
$dbh->do($part) or return 0;
}
return 1;
}
sub _setup_metadb{
my $sandbox = shift;
my $schema = shift;
my $dbh = shift;
$dbh->do("INSERT INTO dbr_schemas (schema_id,handle) values (1,'$schema')") or return 0;
$dbh->do("INSERT INTO dbr_instances (schema_id,handle,class,dbfile,module) values (1,'$schema','master','$sandbox/db.sqlite','SQLite')") or return 0;
return 1;
}
sub _write_dbrconf{
my $sandbox = shift;
my $dbrconf = shift;
my $fh;
open ($fh, "> $dbrconf") or return 0;
print $fh "# This DBR config file has been generated by the DBR::Sandbox library.\n";
print $fh "# This conf file defines DB instances, at least one of which (dbrconf) is\n";
print $fh "# required to have a starting point for fetching metadata. Defining other\n";
print $fh "# instances here is possible, but discouraged, as functionality will be\n";
print $fh "# dramatically degraded due to lack of metadata.\n\n";
print $fh "name=dbrconf; class=master; dbfile=$sandbox/dbrconf.sqlite; type=SQLite; dbr_bootstrap=1\n";
close $fh;
return 1;
}
1;