package CodeRefObj;
use strict;
use warnings;
sub create {
my $properties = shift;
my $methods = shift;
my $closure = sub {
my $magick = shift;
# first resolve any property sets or gets
if (exists $properties->{$magick}) {
$properties->{$magick} = shift if @_;
return $properties->{$magick};
} # next resolve any method calls, making
# sure to include a ref to the %properties hash
elsif (exists $methods->{$magick}) {
return &{ $methods->{$magick} }($properties, @_);
}
else {
die "Magick $magick not defined";
}
};
return $closure;
}
1;
####
package AccessDB::Impl;
use strict;
use Win32::OLE;
use Win32::OLE::Const 'Microsoft ActiveX Data Objects 2.7';
use Win32::OLE::Variant qw(:DEFAULT nothing);
use CodeRefObj;
use Hash::Util qw/lock_keys lock_hash lock_value unlock_value/;
my @prop_names = qw/mdb_file state conn/;
my %methods = (
'open'=>\&open,
'close'=>\&close,
'execute'=>\&execute,
'getConnString'=>\&getConnString,
'free_resources'=>\&free_resources);
my $conn_string1 = "Provider=MSDataShape;Data Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;Data Source=";
my $conn_string2 = ";Mode=Share Deny None;Jet OLEDB:System database='';Jet OLEDB:Database Password=''";
sub init {
my $file_name = shift;
my (%properties);
lock_keys(%properties, @prop_names);
$properties{'state'} = 0;
lock_value(%properties, 'state');
$properties{'conn'} = Win32::OLE->new('ADODB.Connection');
lock_value(%properties, 'conn');
$properties{'mdb_file'} = $file_name || '';
lock_hash(%methods);
return CodeRefObj::create(\%properties, \%methods);
}
sub open {
my $props = shift;
$props->{'mdb_file'} = shift if @_;
die "no mdb_file specified" unless $props->{'mdb_file'};
my $connection = join('', $conn_string1, $props->{'mdb_file'}, $conn_string2);
$props->{'conn'}->Open($connection) unless $props->{'conn'}->{State};
die Win32::OLE->LastError() if Win32::OLE->LastError();
unlock_value(%{$props}, 'state');
$props->{'state'} = $props->{'conn'}->{State};
lock_value(%{$props}, 'state');
}
sub close {
my $props = shift;
$props->{'conn'}->Close() if $props->{'conn'}->{State};
unlock_value(%{$props}, 'state');
$props->{'state'} = $props->{'conn'}->{State};
lock_value(%{$props}, 'state');
}
sub execute {
my $props = shift;
my $sql = shift;
$props->{'conn'}->Execute($sql);
die "$sql" if Win32::OLE->LastError();
}
sub getConnString {
my $props = shift;
return join('', $conn_string1, $props->{'mdb_file'}, $conn_string2);
}
sub free_resources {
my $props = shift;
unlock_value(%{$props}, 'conn');
$props->{'conn'}->Close() if $props->{'conn'}->{State};
$props->{'conn'} = nothing;
}
1;
####
package AccessDB::Interface;
use strict;
use AccessDB::Impl;
# Constructor AccessDB::Interface->create([$file_name])
sub create {
my $class = shift;
my $code_ref_obj = AccessDB::Impl::init(@_);
return bless ($code_ref_obj, $class);
}
# Properties
# mdb_file is read-write,
# returns/sets full path of file
# $obj->mdb_file([$file_name])
sub mdb_file {
my $code_ref_obj = shift;
return $code_ref_obj->('mdb_file', @_);
}
# state is read-only and ignores any parameters
# returns either 0 for closed or 1 for open
# $obj->state()
sub state {
my $code_ref_obj = shift;
return $code_ref_obj->('state');
}
# conn is read only
# returns the connection object
# $obj->conn()
sub conn {
my $code_ref_obj = shift;
return $code_ref_obj->('conn');
}
# Methods
# $obj->open([$filename])
sub open {
my $code_ref_obj = shift;
$code_ref_obj->('open', @_);
}
# obj->execute($sql)
sub execute {
my $code_ref_obj = shift;
$code_ref_obj->('execute', @_);
}
# $obj->close()
sub close {
my $code_ref_obj = shift;
$code_ref_obj->('close');
}
# $obj->getConnString()
# returns the connection string
sub getConnString {
my $code_ref_obj = shift;
return $code_ref_obj->('getConnString');
}
# DESTROY gets called by system
# and then calls free_resources
sub DESTROY {
my $code_ref_obj = shift;
$code_ref_obj->('free_resources');
}
1;
####
#!/usr/local/bin/perl
use strict;
use warnings;
use AccessDB::Interface;
my $file = 'e:\Base\test.mdb';
my $adb = AccessDB::Interface->create($file);
$adb->open();
print "State is ", $adb->state(), "\n";
my $sql = <<"end_of_sql";
INSERT INTO tstTable (Entry, Name)
VALUES ('Blather', 'John Q Publik')
end_of_sql
$adb->execute($sql);
$adb->close();