Author: jzucker
Date: Thu Mar 4 12:32:12 2004
New Revision: 182
Modified:
dbi/trunk/lib/DBD/DBM.pm
dbi/trunk/lib/DBD/File.pm
Log:
new DBM and File
Modified: dbi/trunk/lib/DBD/DBM.pm
==============================================================================
--- dbi/trunk/lib/DBD/DBM.pm (original)
+++ dbi/trunk/lib/DBD/DBM.pm Thu Mar 4 12:32:12 2004
@@ -22,7 +22,6 @@
package DBD::DBM;
#################
use DBD::File ();
-use Carp;
use vars qw($VERSION $ATTRIBUTION $methods_already_installed);
use base qw( DBD::File );
$VERSION = '0.01'; # CHANGE THIS !
@@ -78,21 +77,16 @@
# attempts to set non-valid attrs in connect() or
# with $dbh->{attr} will throw errors
#
- # the attrs here *must* start with dbm_ or foo_ or f_
+ # the attrs here *must* start with dbm_ or foo_
#
- $this->{f_valid_attrs} = my $valid_attrs = {
- dbm_tables => 1 # per-table information
- , dbm_type => 1 # the global DBM type e.g. SDBM_File
- , dbm_mldbm => 1 # the global MLDBM serializer
- , dbm_cols => 1 # the global column names
- , dbm_version => 1 # verbose DBD::DBM version
- , dbm_ext => 1 # file extension
+ $this->{dbm_valid_attrs} = {
+ dbm_tables => 1 # per-table information
+ , dbm_type => 1 # the global DBM type e.g. SDBM_File
+ , dbm_mldbm => 1 # the global MLDBM serializer
+ , dbm_cols => 1 # the global column names
+ , dbm_version => 1 # verbose DBD::DBM version
+ , dbm_ext => 1 # file extension
, dbm_store_metadata => 1 # column names, etc.
- , sql_handler => 1 # Nano or S:S
- , sql_nano_version => 1 # Nano version
- , sql_statement_version => 1 # S:S version
- , f_version => 1 # DBD::File version
- , f_dir => 1 # base directory
};
my($var, $val);
@@ -108,20 +102,17 @@
$var = $1;
($val = $2) =~ s/\\(.)/$1/g;
- # Add dbm_ prefix to attributes that need it
- # (attributes for DBD::Foo in the Driver DSN portion
- # of the DSN string are allowed to skip the "foo_" prefix)
- $var = 'dbm_' . $var if !$valid_attrs->{$var}
- && $valid_attrs->{"dbm_$var"};
-
- # place the attribute in $attr (possibly replacing an exiting value)
- # so DBI->connect will then call our STORE on it for us.
- # Our STORE method (inherited from DBD::File's) should validate it
- $attr->{$var} = $val;
+ # in the connect string the attr names
+ # can either have dbm_ (or foo_) prepended or not
+ # this will add the prefix if it's missing
+ #
+ $var = 'dbm_' . $var unless $var =~ /^dbm_/
+ or $var eq 'f_dir';
+ $this->{$var} = $val;
}
}
$this->{f_version} = $DBD::File::VERSION;
- $this->{dbm_version} = $DBD::File::VERSION;
+ $this->{dbm_version} = $DBD::DBM::VERSION;
for (qw( nano_version statement_version)) {
$this->{'sql_'.$_} = $DBI::SQL::Nano::versions->{$_}||'';
}
@@ -144,6 +135,60 @@
$DBD::DBM::db::imp_data_size = 0;
@DBD::DBM::db::ISA = qw(DBD::File::db);
+# the ::db::STORE method is what gets called when you set
+# a lower-cased database handle attribute such as $dbh->{somekey}=$someval;
+#
+# STORE should check to make sure that "somekey" is a valid attribute name
+# but only if it is really one of our attributes (starts with dbm_ or foo_)
+# You can also check for valid values for the attributes if needed
+# and/or perform other operations
+#
+sub STORE ($$$) {
+ my ($dbh, $attrib, $value) = @_;
+
+ # use DBD::File's STORE unless its one of our own attributes
+ #
+ return $dbh->SUPER::STORE($attrib,$value) unless $attrib =~ /^dbm_/;
+
+ # throw an error if it has our prefix but isn't a valid attr name
+ #
+ if ( $attrib ne 'dbm_valid_attrs' # gotta start somewhere :-)
+ and !$dbh->{dbm_valid_attrs}->{$attrib} ) {
+ return $dbh->set_err( 1,"Invalid attribute '$attrib'!");
+ }
+ else {
+
+ # check here if you need to validate values
+ # or conceivably do other things as well
+ #
+ $dbh->{$attrib} = $value;
+ return 1;
+ }
+}
+
+# and FETCH is done similar to STORE
+#
+sub FETCH ($$) {
+ my ($dbh, $attrib) = @_;
+
+ return $dbh->SUPER::STORE($attrib) unless $attrib =~ /^dbm_/;
+
+ # throw an error if it has our prefix but isn't a valid attr name
+ #
+ if ( $attrib ne 'dbm_valid_attrs' # gotta start somewhere :-)
+ and !$dbh->{dbm_valid_attrs}->{$attrib} ) {
+ return $dbh->set_err( 1,"Invalid attribute '$attrib'!");
+ }
+ else {
+
+ # check here if you need to validate values
+ # or conceivably do other things as well
+ #
+ return $dbh->{$attrib};
+ }
+}
+
+
# this is an example of a private method
# these used to be done with $dbh->func(...)
# see above in the driver() sub for how to install the method
@@ -235,22 +280,25 @@
$dbh->{dbm_tables}->{$file}->{dbm_type} = $dbm_type;
my $serializer = $dbh->{dbm_tables}->{$file}->{mldbm}
- || $dbh->{mldbm}
+ || $dbh->{dbm_mldbm}
|| '';
$serializer = 'Storable' if $serializer =~ /^S$/i;
$serializer = 'FreezeThaw' if $serializer =~ /^F$/i;
$serializer = 'Data::Dumper' if $serializer =~ /^D$/i;
$dbh->{dbm_tables}->{$file}->{mldbm} = $serializer if $serializer;
- my $ext = $dbh->{dbm_tables}->{$file}->{ext}
- || $dbh->{dbm_ext}
- || '.pag';
- # add code to define extension by dbm_type
- # when I get the info to do so
+ my $ext = $dbh->{dbm_tables}->{$file}->{ext};
+ $ext = $dbh->{dbm_ext} unless defined $ext;
+ $ext = '' unless defined $ext;
+ $ext = '' if $dbm_type eq 'GDBM_File'
+ or $dbm_type eq 'DB_File';
+ $ext = '.pag' if $dbm_type eq 'NDBM_File'
+ or $dbm_type eq 'SDBM_File'
+ or $dbm_type eq 'ODBM_File';
die "Cannot CREATE '$file$ext', already exists!"
if $createMode and (-e "$file$ext");
- die "Cannot open '$file', file not found!"
+ die "Cannot open '$file$ext', file not found!"
if !$createMode
and !($self->{command} eq 'DROP')
and !(-e "$file$ext");
@@ -271,6 +319,7 @@
require "$dbm_type.pm";
$tie_type = $dbm_type;
}
+
eval { tie(%h, $tie_type, $file, $open_mode, 0666) }
unless $self->{command} eq 'DROP';
die "Cannot tie file '$file': $@" if $@;
@@ -280,7 +329,7 @@
$store = 1 unless defined $store;
$dbh->{dbm_tables}->{$file}->{store_metadata} = $store;
- my $col_names = $h{"_metadata"} if $store;
+ my $col_names = $h{"_metadata \0"} if $store;
$col_names ||= $dbh->{dbm_tables}->{$file}->{c_cols}
|| $dbh->{dbm_tables}->{$file}->{cols}
|| $dbh->{dbm_cols}
@@ -400,14 +449,12 @@
#
sub fetch_row ($$$) {
my($self, $data, $row) = @_;
- my @ary = each %{$self->{hash}};
-
- # to prevent treating the column names row as data
- # is this too expensive?
+ # fetch with %each
#
+ my @ary = each %{$self->{hash}};
@ary = each %{$self->{hash}} if $self->{store_metadata}
and $ary[0]
- and $ary[0] eq "_metadata";
+ and $ary[0] eq "_metadata \0";
return undef unless defined $ary[0];
if (ref $ary[1] eq 'ARRAY') {
@@ -415,6 +462,26 @@
}
return (@ary) if wantarray;
return [EMAIL PROTECTED];
+=pod
+ # fetch without %each
+ #
+ $self->{keys} = [sort keys %{$self->{hash}}] unless $self->{keys};
+ my $key = shift @{$self->{keys}};
+ $key = shift @{$self->{keys}} if $self->{store_metadata}
+ and $key
+ and $key eq "_metadata \0";
+ return undef unless defined $key;
+ my @ary;
+ $row = $self->{hash}->{$key};
+ if (ref $row eq 'ARRAY') {
+ @ary = ( $key, @{$row} );
+ }
+ else {
+ @ary = ($key,$row);
+ }
+ return (@ary) if wantarray;
+ return [EMAIL PROTECTED];
+=cut
}
# you must define push_row
@@ -438,7 +505,7 @@
sub push_names ($$$) {
my($self, $data, $row_aryref) = @_;
$data->{Database}->{dbm_tables}->{$self->{file}}->{c_cols} = $row_aryref;
- $self->{hash}->{"_metadata"} = join(',',@{$row_aryref})
+ $self->{hash}->{"_metadata \0"} = join(',',@{$row_aryref})
if $self->{store_metadata};
}
@@ -461,6 +528,9 @@
my($self,$data,$aryref) = @_;
my $key = shift @$aryref;
return undef unless defined $key;
+ if( ref $aryref->[0] eq 'ARRAY'){
+ return $self->{hash}->{$key}=$aryref;
+ }
$self->{hash}->{$key}=$aryref->[0];
}
@@ -470,6 +540,7 @@
sub DESTROY ($) {
my $self=shift;
# code to release lock goes here
+ untie %{$self->{hash}} if $self->{hash};
}
# truncate() and seek() must be defined to satisfy DBI::SQL::Nano
@@ -800,7 +871,7 @@
=head1 ACKNOWLEDGEMENTS
-Thanks to Tim Bunce for prodding me to write this, for copious and for patient
suggestions all along the way. Thanks to Bob Walton for looking over a draft version.
+Many, many thanks to Tim Bunce for prodding me to write this, and for copious, wise,
and patient suggestions all along the way.
=head1 AUTHOR AND COPYRIGHT
Modified: dbi/trunk/lib/DBD/File.pm
==============================================================================
--- dbi/trunk/lib/DBD/File.pm (original)
+++ dbi/trunk/lib/DBD/File.pm Thu Mar 4 12:32:12 2004
@@ -105,6 +105,16 @@
$this->{$var} = $val;
}
}
+ $this->{f_valid_attrs} = {
+ f_version => 1 # DBD::File version
+ , f_dir => 1 # base directory
+ , f_tables => 1 # base directory
+ };
+ $this->{sql_valid_attrs} = {
+ sql_handler => 1 # Nano or S:S
+ , sql_nano_version => 1 # Nano version
+ , sql_statement_version => 1 # S:S version
+ };
}
return set_versions($this);
}
@@ -215,21 +225,10 @@
} elsif ($attrib eq (lc $attrib)) {
# Driver private attributes are lower cased
- # Error-check If driver maintains registry of valid attributes
- # But, hmm, maybe I shouldn't do this in case other
- # things DBIx or whatever try to set things ???
+ # Error-check for valid attributes
+ # not implemented yet, see STORE
#
- if ($attrib !~ /^dbi/ and $dbh->{f_valid_attrs}) {
- if ( $dbh->{f_valid_attrs}->{$attrib} ) {
- return $dbh->{$attrib};
- }
- else {
- return $dbh->set_err(1,"Invalid attribute '$attrib'!");
- }
- }
- else {
- return $dbh->{$attrib};
- }
+ return $dbh->{$attrib};
}
# else pass up to DBI to handle
return $dbh->DBD::_::db::FETCH($attrib);
@@ -237,31 +236,38 @@
sub STORE ($$$) {
my ($dbh, $attrib, $value) = @_;
+
if ($attrib eq 'AutoCommit') {
return 1 if $value; # is already set
die("Can't disable AutoCommit");
} elsif ($attrib eq (lc $attrib)) {
# Driver private attributes are lower cased
- # Error-check If driver maintains registry of valid attributes
- # But, hmm, maybe I shouldn't do this in case other
- # things DBIx or whatever try to set things ???
+=pod
+
+ # I'm not implementing this yet becuase other drivers may be
+ # setting f_ and sql_ attrs I don't know about
+ # I'll investigate and publicize warnings to DBD authors
+ # then implement this
+ #
+ # return to implementor if not f_ or sql_
+ # not implemented yet
+ # my $class = $dbh->FETCH('ImplementorClass');
#
- if ($attrib !~ /^dbi/ and $dbh->{f_valid_attrs}) {
- if ( $dbh->{f_valid_attrs}->{$attrib} ) {
- if ($attrib eq 'f_dir') {
- return $dbh->set_err( 1,"No such directory '$value'!")
- unless -d $value;
- }
- $dbh->{$attrib} = $value;
- }
- else {
- return $dbh->set_err( 1,"Invalid attribute '$attrib'!");
- }
+ if ( !$dbh->{f_valid_attrs}->{$attrib}
+ and !$dbh->{sql_valid_attrs}->{$attrib}
+ ) {
+ return $dbh->set_err( 1,"Invalid attribute '$attrib'!");
}
else {
$dbh->{$attrib} = $value;
}
+=cut
+ if ($attrib eq 'f_dir') {
+ return $dbh->set_err( 1,"No such directory '$value'!")
+ unless -d $value;
+ }
+ $dbh->{$attrib} = $value;
return 1;
}
return $dbh->DBD::_::db::STORE($attrib, $value);
@@ -408,17 +414,6 @@
0;
}
-sub f_versions {
- my $dbh = shift;
- printf "%s %s\n%s %s\n%s %s\n",
- , 'DBD::File' , $DBD::File::VERSION,
- , 'DBI::SQL::Nano' , $dbh->{sql_nano_version}
- ;
- printf "%s %s\n",
- , 'SQL::Statement' , $dbh->{sql_statement_version}
- if $dbh->{sql_handler} eq 'SQL::Statement';
-}
-
package DBD::File::st; # ====== STATEMENT ======
$DBD::File::st::imp_data_size = 0;