/usr/local/CPAN/Alister-Base-Sums/Alister/Base/Sums.pm
package Alister::Base::Sums;
use strict;
use vars qw($VERSION $TABLE_NAME $SQL_LAYOUT @ISA @EXPORT_OK %EXPORT_TAGS); #$sth1 $sth0
use Exporter;
use LEOCHARRE::Debug;
use Carp;
$VERSION = sprintf "%d.%02d", q$Revision: 1.5 $ =~ /(\d+)/g;
@EXPORT_OK = qw/sum_add sum_update sum_get sum_delete validate_argument_sum validate_argument_id table_reset_sums/;
%EXPORT_TAGS = ( all => \@EXPORT_OK );
@ISA = qw/Exporter/;
$TABLE_NAME = 'sums';
$SQL_LAYOUT ="CREATE TABLE $TABLE_NAME (
id int(20) AUTO_INCREMENT PRIMARY KEY,
sum varchar(32) NOT NULL UNIQUE );";
sub table_create_sums { _dbh_do_sql_layout( $_[0], $SQL_LAYOUT ) }
sub table_reset_sums { $_[0]->do("DROP TABLE IF EXISTS $TABLE_NAME"); table_create_sums($_[0]) }
sub _dbh_do_sql_layout {
my ($dbh, $layout) = @_;
$layout =~s/\t+| {2,}/ /g;
for my $sql ( split( /\;/, $layout) ){
$sql=~/\w/ or next;
debug("layout [$sql]\n");
debug('-');
$dbh->do($sql)
or die($dbh->errstr);
}
debug("Done.");
#$self->dbh->commit; should commit at script level instead
1;
}
# reset
#*sum_add = \&_sum_add_mod;
*sum_add = \&_sum_add_original;
sub _sum_add_original {
my $dbh = $_[0];
my $sum = validate_argument_sum($_[1])
or warn("Argument 2 to sum_add() must be a sum digest string")
and return;
# NOTE do NOT use REPLACE INTO, that works but it changes the sum_id
# which is the whole keystone of this whole operation!
my $sth = $dbh->prepare("INSERT INTO $TABLE_NAME (sum) VALUES (?)")
or confess($dbh->errstr);
local $sth->{RaiseError}; # stop dying if insert fails
local $sth->{PrintError}; # stop telling if insert fails
my $result = $sth->execute($sum);
$sth->finish;
!defined $result # then already in.. likely
and return (
_dbh_fetch_one( $dbh, "SELECT id FROM $TABLE_NAME WHERE sum = ?", $sum)
|| die("Could not insert sum:'$sum', and could not fetch either! Something is wrong."));
($result eq '0E0')
and confess("could not register sum:'$sum',".$dbh->errstr);
defined wantarray
? ( $dbh->last_insert_id( undef, undef, $TABLE_NAME, undef )
|| confess("can't get last insert id for sum table") )
: 1;
}
sub sum_delete {
my ($id, $sql, $dbh, $arg)=(undef,undef,$_[0], $_[1]);
$arg or confess('missing arg');
$sql =
validate_argument_sum($arg)
? "DELETE FROM $TABLE_NAME WHERE sum = ?"
: validate_argument_id($arg)
? "DELETE FROM $TABLE_NAME WHERE id = ?"
: confess("What is argument '$arg'? Not sum or id");
my $sth = $dbh->prepare($sql) or die($dbh->errstr);
my $affected = $sth->execute($arg);
$sth->finish;
return ( $affected eq '0E0' ? 0 : $affected );
}
sub sum_get { # MASTER
my $dbh = $_[0];
validate_argument_sum($_[1])
? _dbh_fetch_one( $dbh, "SELECT id FROM $TABLE_NAME WHERE sum = ?", $_[1] )
: validate_argument_id($_[1])
? _dbh_fetch_one( $dbh, "SELECT sum FROM $TABLE_NAME WHERE id = ? LIMIT 1", $_[1] )
: confess("Argument is not a sum or sum id '$_[1]'");
}
sub sum_update {
# what if we try to change to a md5um that already exists!
my ($dbh, $arg, $new_sum )= @_;
# first thing.. the sum must be valid.
validate_argument_sum($new_sum) or warn("argument is not a real sum: '$arg'") and return;
no warnings;
if ( validate_argument_sum($arg) ){
my $sth = $dbh->prepare("UPDATE $TABLE_NAME SET sum = ? WHERE sum = ?");
my $r = $sth->execute($new_sum, $arg);
$sth->finish;
debug("result '$r'") if $r;
return (($r and $r eq '0E0') ? 0 : $r);
}
elsif( validate_argument_id($arg) ){
my $sth = $dbh->prepare("UPDATE $TABLE_NAME SET sum = ? WHERE id = ?");
my $r = $sth->execute($new_sum, $arg);
$sth->finish;
debug("result '$r'") if $r;
return (($r and $r eq '0E0') ? 0 : $r);
}
else {
confess("Argument is neither sum or id");
}
}
sub validate_argument_id { ( $_[0] and $_[0]=~/^\d+$/) ? $_[0] : undef } # because can't be '0' for an id
sub validate_argument_sum { ($_[0] and $_[0]=~/^[0-9a-f]{32}$/) ? $_[0] : undef }
sub _dbh_fetch_one {
my $dbh = shift;
my $statement = shift;
my @args = @_;
my $sth = $dbh->prepare($statement);
my $result = $sth->execute(@args); # dies if error
if ($result eq '0E0'){ # would mean no results
$sth->finish;
return;
}
my $val = $sth->fetch->[0];
$sth->finish;
$val;
}
1;
__END__
# see lib/Alister/Base/Sums.pod
sub _sum_add_mod { # slightly faster, might not be worth the code maintenance
my $dbh = $_[0];
my $sum = validate_argument_sum($_[1])
or warn("Argument 2 to sum_add() must be a sum digest string")
and return;
# NOTE do NOT use REPLACE INTO, that works but it changes the sum_id
# which is the whole keystone of this whole operation!
#my $sth = $dbh->prepare("INSERT INTO $TABLE_NAME (sum) VALUES (?)")
# or confess($dbh->errstr);
$sth0 ||= $dbh->prepare("INSERT INTO $TABLE_NAME (sum) VALUES (?)")
or confess($dbh->errstr);
local $sth0->{RaiseError}; # stop dying if insert fails
local $sth0->{PrintError}; # stop telling if insert fails
my $result = $sth0->execute($sum);
$sth0->finish;
if (!defined $result){ # then already in.. likely
$sth1 ||= $dbh->prepare("SELECT id FROM $TABLE_NAME WHERE sum = ?");
my $r = $sth1->execute($sum);
if ($r eq '0E0'){ # would mean no results
$sth1->finish;
die("Could not insert sum:'$sum', and could not fetch either! Something is wrong.");
}
else {
my $val =$sth1->fetch->[0];
$sth1->finish;
return $val
}
}
($result eq '0E0')
and confess("could not register sum:'$sum',".$dbh->errstr);
defined wantarray
? ( $dbh->last_insert_id( undef, undef, $TABLE_NAME, undef )
|| confess("can't get last insert id for sum table") )
: 1;
}