The Perl distribution comes with a set of database management library files called DBM, short for database management. The concept of DBM files stems from the early days of UNIX and consists of a set of C library routines that allow random access to its records. DBM database files are stored as key/value pairs, an associative array that is mapped into a disk file. There are a number of flavors of DBM support, and they demonstrate the most obvious reasons for using tied hashes.
DBM files are binary. They can handle very large databases. The nice thing about storing data with DBM functions is that the data is persistent; that is, any program can access the file as long as the DBM functions are used. The disadvantage is that complex data structures, indexes, multiple tables, and so forth are not supported, and there is no reliable file locking and buffer flushing, making concurrent reading and updating risky.[2] File locking can be done with the Perl flock function, but the strategy for doing this correctly is beyond the scope of this book.[3]
[2] Although Perl's tief unction will probably replace the dbmopen function, for now we'll use this function because it's easier than tie.
[3] For details on file locking, see Descartes, A., and Bunce, T., Programming the Perl DBI, O'Reilly & Associates, 2000, p. 35.
So that you don't have to figure out which of the standard DBM packages to use, the AnyDBM_File.pm module will get the appropriate package for your system from the standard set in the standard Perl library. The AnyDBM_File module is also useful if your program will run on multiple platforms. It will select the correct libraries for one of five different implementations:
| odbm | "Old" DBM implementation found on UNIX systems and replaced by NDBM |
| ndbm | "New"DBM implementation found on UNIX systems |
| sdbm | Standard Perl DBM, provides cross-platform compatibility, but not good for large databases |
| gdbm | GNU DBM, a fast, portable DBM implementation; see www.gnu.org |
| bsd-db | Berkeley DB; found on BSD UNIX systems, most powerful of all the DBMs; see www.sleepycat.com |
The following table comes from the documentation for AnyDBM_FILE and lists some of the differences in the various DBM implementations. At your command-line prompt, type:
perldoc AnyDBM_File
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 noBefore a database can be accessed, it must be opened by using the dbmopen function or the tie function. This binds the DBM file to an associative array (hash). Two files will be created: one file contains an index directory and has .dir as its suffix; the second file, ending in .pag, contains all the data. The files are not in a readable format. The dbm functions are used to access the data. These functions are invisible to the user.
Data is assigned to the hash, just as with any Perl hash, and an element removed with Perl's delete function. The DBM file can be closed with the dbmclose or the untie function.
Formatdbmopen(hash, dbfilename, mode); tie(hash, Module , dbfilename, flags, mode); Example 15.5.
|
Perl's report writing mechanism is very useful for generating formatted data from one of the DBM files. The following examples illustrate how to create, add, delete, and close a DBM file and how to create a Perl-style report.
|
Code View: (The Script)
#!/usr/bin/perl
# Program name: makestates.pl
# This program creates the database using the dbm functions
1 use AnyDBM_File; # Let Perl pick the right dbm for your system
2 dbmopen(%states, "statedb", 0666[a]) || die;
# Create or open the database
3 TRY: {
4 print "Enter the abbreviation for your state. ";
chomp($abbrev=<STDIN>);
$abbrev = uc $abbrev; # Make sure abbreviation is uppercase
5 print "Enter the name of the state. ";
chomp($state=<STDIN>);
lc $state;
6 $states{$abbrev}="\u$state"; # Assign values to the database
7 print "Another entry? ";
$answer = <STDIN>;
8 redo TRY if $answer =~ /Y|y/;
}
9 dbmclose(%states); # Close the database
---------------------------------------------------------------------
(The Command line)
10 $ ls
makestates.pl statedb.dir statedb.pag[b]
------------------------------------------------------------------
(Output)
4 Enter the abbreviation for your state. CA
5 Enter the name of the state. California
7 Another entry? y
Enter the abbreviation for your state. me
Enter the name of the state. Maine
Another entry? y
Enter the abbreviation for your state. NE
Enter the name of the state. Nebraska
Another entry? y
Enter the abbreviation for your state. tx
Enter the name of the state. Texas
Another entry? n
Explanation
|
[a] Permissions are ignored on Win32 systems.
[b] On some versions, only one file with a .db extension is created.
Once the DBM file has been opened, it is associated with a tied hash in the Perl script. All details of the implementation are hidden from the user. Data retrieval is fast and easy. The user simply manipulates the hash as though it were any ordinary Perl hash. Since the hash is tied to the DBM file, when the data is retrieved, it is coming from the DBM file.
To empty the completed DBM file, you can use the undef function; for example, undef %states would clear all entries in the DBM file created in Example 15.8. Deleting a key/value pair is done simply by using the Perl built-in delete function on the appropriate key within the hash that was tied to the DBM file.