Front page | perl.perl5.porters |
Postings from April 2011
various DBM bugs
From:
Tom Christiansen
Date:
April 22, 2011 14:03
Subject:
various DBM bugs
Message ID:
1487.1303506187@chthon
What's the deal with GDBM_File? It's in ext/, but it doesn't
bother to build. And you can't get it to install with
perl -MCPAN -e 'install GDBM_File', either.
The AnyDBM_File manpage claims:
Here's a partial table of features the different packages offer:
odbm ndbm sdbm gdbm bsd-db
---- ---- ---- ---- ------
Linkage comes w/ perl yes yes yes yes yes
Src comes w/ perl no no yes no no
Comes w/ many unix os yes yes[0] no no no
Builds ok on !unix ? ? yes yes ?
Code Size ? ? small big big
Database Size ? ? small big? ok[1]
Speed ? ? slow ok fast
FTPable no no yes yes yes
Easy to build N/A N/A yes yes ok[2]
Size limits 1k 4k 1k[3] none none
Byte-order independent no no no no yes
Licensing restrictions ? ? no yes no
I guess it must look for the library and if it is there, use it.
Is that right?
% perl -Mwarnings=FATAL,all -Mautodie -le 'dbmopen(%db, "/tmp/dbtest", 0666); $db{"\x{3b1}"} = 1; dbmclose %db'
Wide character in subroutine entry at -e line 1.
Exit 255
Um, *what* subroutine entry?
% perl -Mdiagnostics -Mwarnings=FATAL,all -Mautodie -le 'dbmopen(%db, "/tmp/dbtest", 0666); $db{"\x{3b1}"} = 1; dbmclose %db'
Wide character in subroutine entry at -e line 1 (#1)
(S utf8) Perl met a wide character (>255) when it wasn't expecting
one. This warning is by default on for I/O (like print). The easiest
way to quiet this warning is simply to add the :utf8 layer to the
output, e.g. binmode STDOUT, ':utf8'. Another way to turn off the
warning is to add no warnings 'utf8'; but that is often closer to
cheating. In general, you are supposed to explicitly mark the
filehandle with an encoding, see open and perlfunc/binmode.
Uncaught exception from user code:
Wide character in subroutine entry at -e line 1.
at -e line 1
Exit 255
I believe that is an inappropriate error message. Nothing there tells
anybody what they have to do to make it happy. How in the world would ever guess you have
to do this:
% perl -Mdiagnostics -Mwarnings=FATAL,all -Mautodie -MEncode -le 'dbmopen(%db, "/tmp/dbtest", 0666); $db{encode("UTF-8", "\x{3b1}")} = 1; dbmclose %db'
Also, interestingly, I get one of these without having asked for it:
% file /tmp/dbtest*
/tmp/dbtest.db: Berkeley DB 1.85 (Hash, version 2, native byte-order)
That's on a Mac, which, like any other BSD system, of course comes
with DB_File. I suggest that the AnyDBM_File manpage be updated
to state this. (And yes, BerkeleyDB and DB_File are different.)
But why isn't that an ndbm file? Weird.
Speaking of AnyDBM_File, the reason this is happening is because
it gets autmagically demand-loaded by the first call the dbmopen.
But this isn't admitted to in the dmmopen or AnyDBM_File manpages,
and it should be:
=item dbmopen HASH,DBNAME,MASK
X<dbmopen> X<dbm> X<ndbm> X<sdbm> X<gdbm>
[This function has been largely superseded by the C<tie> function.]
This binds a dbm(3), ndbm(3), sdbm(3), gdbm(3), or Berkeley DB file to a
hash. HASH is the name of the hash. (Unlike normal C<open>, the first
argument is I<not> a filehandle, even though it looks like one). DBNAME
is the name of the database (without the F<.dir> or F<.pag> extension if
any). If the database does not exist, it is created with protection
specified by MASK (as modified by the C<umask>). If your system supports
only the older DBM functions, you may make only one C<dbmopen> call in your
program. In older versions of Perl, if your system had neither DBM nor
ndbm, calling C<dbmopen> produced a fatal error; it now falls back to
sdbm(3).
Also, it really seems like you should be able to know what DBM you're
getting.
our @ISA = qw(NDBM_File DB_File GDBM_File SDBM_File ODBM_File) unless @ISA;
my $mod;
for $mod (@ISA) {
if (eval "require $mod") {
@ISA = ($mod); # if we leave @ISA alone, warnings abound
return 1;
}
}
Oh, ok. So it just gets the first one it loads.
DB<2>
NDBM_File::(/usr/local/lib/perl5/5.12.3/darwin-thread-multi-2level/NDBM_File.pm:14):
14: 1;
DB<2>
AnyDBM_File::(/usr/local/lib/perl5/5.12.3/AnyDBM_File.pm:10):
10: @ISA = ($mod); # if we leave @ISA alone, warnings abound
DB<2>
AnyDBM_File::(/usr/local/lib/perl5/5.12.3/AnyDBM_File.pm:11):
11: return 1;
DB<2> p @AnyDBM_File::ISA
NDBM_File
Huh? It claims NDBM_File, but makes a DB_File file!
Cuuurious.
Lots of non-obviousness going on here.
--tom
-
various DBM bugs
by Tom Christiansen