(D:/Yada.SQLite - database on a "spinner"):
the code took:789 wallclock secs ( 6.38 usr + 17.17 sys = 23.55 CPU)
(C:/Yada.SQLite - database on a 'SSD'):
the code took:101 wallclock secs ( 3.70 usr + 16.78 sys = 20.49 CPU)
(RAM drive - database on a 10 gig RAM drive)
the code took: 14 wallclock secs ( 2.89 usr + 9.47 sys = 12.36 CPU)
####
(D:/Yada.SQLite)
the code took: 2 wallclock secs ( 1.41 usr + 0.00 sys = 1.41 CPU)
(C:/Yada.SQLite)
the code took: 1 wallclock secs ( 1.31 usr + 0.00 sys = 1.31 CPU)
(R:/Yada.SQlite - RAM drive)
the code took: 2 wallclock secs ( 1.36 usr + 0.00 sys = 1.36 CPU)
##
##
package Log::Log4perl::Appender::DBI_eeks v0.00.01;
# Purpose : Just to see how subclassing Log::Log4perl::Appender::DBI is done
# Keywords : SQLite in-memory,
# NB :
# Notes : Note use of supplemental DBI::db::
# : Note the above superceded by inlining the code for _setup, _teardown
## no critic (EmptyQuotes,ProhibitParensWithBuiltins,ProhibitPostfixControls,ProhibitUnlessBlocks,PostfixControls,RequireCarping)
## no critic (RequireDotMatchAnything,RequireExtendedFormatting,RequireLineBoundaryMatching,RequirePodSections)
use 5.032001;
use warnings;
use parent 'Log::Log4perl::Appender::DBI';
use Benchmark;
use Carp;
use Data::Alias;
use Data::Dumper;
use DBI;
use English qw(-no_match_vars);
use Readonly;
Readonly my $FALSE => !!0;
Readonly my $THREE => 3;
Readonly my $TRUE => !!1;
use Syntax::Keyword::Try qw( try :experimental(typed) );;
use Time::HiRes;
my ($MASTER);
my ($error,$sql,@tablename_a);
sub _init { ;my $subname=(caller 0)[$THREE];
;warn "$subname called.";
#;warn Data::Dumper->new([\@_],[qw(*_)])->Deepcopy(1)->Indent(1)->Maxdepth(3)->Sortkeys(1)->Dump(),q{ };
my $self=shift;
my %params = @_;
if ($params{dbh}) {
$self->{dbh}=$params{dbh};
}
elsif ($params{datasource} !~ m{\Qdbi:SQLite:dbname=\E(?.*)$}i) { # Not OUR speciality
$self->SUPER::_init(@_);
}
else { # OUR speciality
my $t0=Benchmark->new;
#;warn Data::Dumper->new([\%LAST_PAREN_MATCH],[qw(*+)])->Deepcopy(1)->Indent(1)->Maxdepth(3)->Sortkeys(1)->Dump(),q{ };
$MASTER=$LAST_PAREN_MATCH{dbfile};
substr($params{datasource},$LAST_MATCH_START[1])=q{:memory:};
$self->{connect}=sub {
DBI->connect(@params{qw(datasource username password)},
{PrintError => 0, $params{attrs} ? %{$params{attrs}} : ()})
or croak "Log4perl: $DBI::errstr";
};
$self->{dbh}=$self->{connect}->();
##########################################################################
#$self->{dbh}->_setup();
try { # Replicating the schema of $MASTER
# Attach master database
$self->{dbh}->do($sql=<<"_ATTACH_");
ATTACH DATABASE '$MASTER' as master;
_ATTACH_
# replicate tables
(my $sth=$self->{dbh}->prepare($sql=<<"_SELECT_"))->execute();
SELECT * FROM master.sqlite_schema; -- WHERE type = 'table';
_SELECT_
my $field_aref=$sth->{NAME};
my %_h;
while (my $value_aref=$sth->fetchrow_arrayref()) {
@_h{@{$field_aref}}=@{$value_aref};
$self->{dbh}->do($sql=$_h{sql});
push @tablename_a,$_h{tbl_name}
if ($_h{type} =~ m{table$});
};
$sth->finish();
}
catch ($error) {
confess $error;
};
##########################################################################
$self->{_RAM}=1;
warn "$subname took: ",timestr(timediff(Benchmark->new,$t0)),"\n";
};
return;
}; # sub _init: ok.
sub DESTROY { ;my $subname=(caller 0)[$THREE];
;warn "$subname called.";
my $self=shift;
no warnings ('experimental::lexical_subs');
my sub _verify_integrity { ;my $subname=(caller 0)[$THREE];
use warnings;
;warn "$subname called.";
Data::Alias::alias my $dbh=$self->{dbh};
(my $sth=$dbh->prepare('PRAGMA integrity_check'))->execute();
my $row;
while (my $_aref=$sth->fetchrow_arrayref()) {
#=# TRACE [ IntegrityOK=>\$_aref ];
return $TRUE
if (++$row == 1 && $_aref->[0] eq 'ok');
};
warn 'Database integrity could NOT be validated --- backup will not be updated!';
return $FALSE;
}; # sub _verify_integrity:
unless ($self->{_RAM} && $self->{dbh}) { # Not our speciality
$self->SUPER::DESTROY(@_);
}
else { # Our speciality
my $t0=Benchmark->new;
##########################################################################
#$self->{dbh}->_teardown();
try {
_verify_integrity();
# Attach
$sql=<<"_ATTACH_";
-- NB: since \$MASTER might have a [.] \$MASTER must be quoted!
-- ATTACH DATABASE '$MASTER' AS master;
BEGIN TRANSACTION;
_ATTACH_
# insert then delete
$sql.=<<"_INSERT_"
INSERT INTO master.$_ SELECT * FROM main.$_;
_INSERT_
for (@tablename_a);
$sql.=<<"_DELETE_"
DELETE FROM main.$_;
_DELETE_
for (@tablename_a);
$sql.=<<"_DETACH_";
END TRANSACTION;
DETACH DATABASE master;
_DETACH_
$self->{dbh}->{sqlite_allow_multiple_statements}=1;
$self->{dbh}->do($sql);
$self->{dbh}->{sqlite_allow_multiple_statements}=0;
}
catch ($error) {
confess $error;
};
##########################################################################
$self->{dbh}->disconnect;
delete $self->{_RAM};
warn "$subname took: ",timestr(timediff(Benchmark->new,$t0)),"\n";
};
return;
}; # sub DESTROY: ok.
unless (caller) {
...;
}
else {
0**0;
};
=scratch
=cut
__DATA__