xref: /openbsd-src/gnu/usr.bin/perl/cpan/DB_File/DB_File.pm (revision 3d61058aa5c692477b6d18acfbbdb653a9930ff9)
1b39c5158Smillert# DB_File.pm -- Perl 5 interface to Berkeley DB
2b39c5158Smillert#
36fb12b70Safresh1# Written by Paul Marquess (pmqs@cpan.org)
4b39c5158Smillert#
5*3d61058aSafresh1#     Copyright (c) 1995-2023 Paul Marquess. All rights reserved.
6b39c5158Smillert#     This program is free software; you can redistribute it and/or
7b39c5158Smillert#     modify it under the same terms as Perl itself.
8b39c5158Smillert
9b39c5158Smillert
10b39c5158Smillertpackage DB_File::HASHINFO ;
11b39c5158Smillert
12b8851fccSafresh1require 5.008003;
13b39c5158Smillert
14b39c5158Smillertuse warnings;
15b39c5158Smillertuse strict;
16b39c5158Smillertuse Carp;
17b39c5158Smillertrequire Tie::Hash;
18b39c5158Smillert@DB_File::HASHINFO::ISA = qw(Tie::Hash);
19b39c5158Smillert
20b39c5158Smillertsub new
21b39c5158Smillert{
22b39c5158Smillert    my $pkg = shift ;
23b39c5158Smillert    my %x ;
24b39c5158Smillert    tie %x, $pkg ;
25b39c5158Smillert    bless \%x, $pkg ;
26b39c5158Smillert}
27b39c5158Smillert
28b39c5158Smillert
29b39c5158Smillertsub TIEHASH
30b39c5158Smillert{
31b39c5158Smillert    my $pkg = shift ;
32b39c5158Smillert
33b39c5158Smillert    bless { VALID => {
34b39c5158Smillert                        bsize     => 1,
35b39c5158Smillert                        ffactor   => 1,
36b39c5158Smillert                        nelem     => 1,
37b39c5158Smillert                        cachesize => 1,
38b39c5158Smillert                        hash      => 2,
39b39c5158Smillert                        lorder    => 1,
40b39c5158Smillert                     },
41b39c5158Smillert            GOT   => {}
42b39c5158Smillert          }, $pkg ;
43b39c5158Smillert}
44b39c5158Smillert
45b39c5158Smillert
46b39c5158Smillertsub FETCH
47b39c5158Smillert{
48b39c5158Smillert    my $self  = shift ;
49b39c5158Smillert    my $key   = shift ;
50b39c5158Smillert
51b39c5158Smillert    return $self->{GOT}{$key} if exists $self->{VALID}{$key}  ;
52b39c5158Smillert
53b39c5158Smillert    my $pkg = ref $self ;
54b39c5158Smillert    croak "${pkg}::FETCH - Unknown element '$key'" ;
55b39c5158Smillert}
56b39c5158Smillert
57b39c5158Smillert
58b39c5158Smillertsub STORE
59b39c5158Smillert{
60b39c5158Smillert    my $self  = shift ;
61b39c5158Smillert    my $key   = shift ;
62b39c5158Smillert    my $value = shift ;
63b39c5158Smillert
64b39c5158Smillert    my $type = $self->{VALID}{$key};
65b39c5158Smillert
66b39c5158Smillert    if ( $type )
67b39c5158Smillert    {
68b39c5158Smillert        croak "Key '$key' not associated with a code reference"
69b39c5158Smillert            if $type == 2 && !ref $value && ref $value ne 'CODE';
70b39c5158Smillert        $self->{GOT}{$key} = $value ;
71b39c5158Smillert        return ;
72b39c5158Smillert    }
73b39c5158Smillert
74b39c5158Smillert    my $pkg = ref $self ;
75b39c5158Smillert    croak "${pkg}::STORE - Unknown element '$key'" ;
76b39c5158Smillert}
77b39c5158Smillert
78b39c5158Smillertsub DELETE
79b39c5158Smillert{
80b39c5158Smillert    my $self = shift ;
81b39c5158Smillert    my $key  = shift ;
82b39c5158Smillert
83b39c5158Smillert    if ( exists $self->{VALID}{$key} )
84b39c5158Smillert    {
85b39c5158Smillert        delete $self->{GOT}{$key} ;
86b39c5158Smillert        return ;
87b39c5158Smillert    }
88b39c5158Smillert
89b39c5158Smillert    my $pkg = ref $self ;
90b39c5158Smillert    croak "DB_File::HASHINFO::DELETE - Unknown element '$key'" ;
91b39c5158Smillert}
92b39c5158Smillert
93b39c5158Smillertsub EXISTS
94b39c5158Smillert{
95b39c5158Smillert    my $self = shift ;
96b39c5158Smillert    my $key  = shift ;
97b39c5158Smillert
98b39c5158Smillert    exists $self->{VALID}{$key} ;
99b39c5158Smillert}
100b39c5158Smillert
101b39c5158Smillertsub NotHere
102b39c5158Smillert{
103b39c5158Smillert    my $self = shift ;
104b39c5158Smillert    my $method = shift ;
105b39c5158Smillert
106b39c5158Smillert    croak ref($self) . " does not define the method ${method}" ;
107b39c5158Smillert}
108b39c5158Smillert
109b39c5158Smillertsub FIRSTKEY { my $self = shift ; $self->NotHere("FIRSTKEY") }
110b39c5158Smillertsub NEXTKEY  { my $self = shift ; $self->NotHere("NEXTKEY") }
111b39c5158Smillertsub CLEAR    { my $self = shift ; $self->NotHere("CLEAR") }
112b39c5158Smillert
113b39c5158Smillertpackage DB_File::RECNOINFO ;
114b39c5158Smillert
115b39c5158Smillertuse warnings;
116b39c5158Smillertuse strict ;
117b39c5158Smillert
118b39c5158Smillert@DB_File::RECNOINFO::ISA = qw(DB_File::HASHINFO) ;
119b39c5158Smillert
120b39c5158Smillertsub TIEHASH
121b39c5158Smillert{
122b39c5158Smillert    my $pkg = shift ;
123b39c5158Smillert
124b39c5158Smillert    bless { VALID => { map {$_, 1}
125b39c5158Smillert                       qw( bval cachesize psize flags lorder reclen bfname )
126b39c5158Smillert                     },
127b39c5158Smillert            GOT   => {},
128b39c5158Smillert          }, $pkg ;
129b39c5158Smillert}
130b39c5158Smillert
131b39c5158Smillertpackage DB_File::BTREEINFO ;
132b39c5158Smillert
133b39c5158Smillertuse warnings;
134b39c5158Smillertuse strict ;
135b39c5158Smillert
136b39c5158Smillert@DB_File::BTREEINFO::ISA = qw(DB_File::HASHINFO) ;
137b39c5158Smillert
138b39c5158Smillertsub TIEHASH
139b39c5158Smillert{
140b39c5158Smillert    my $pkg = shift ;
141b39c5158Smillert
142b39c5158Smillert    bless { VALID => {
143b39c5158Smillert                        flags      => 1,
144b39c5158Smillert                        cachesize  => 1,
145b39c5158Smillert                        maxkeypage => 1,
146b39c5158Smillert                        minkeypage => 1,
147b39c5158Smillert                        psize      => 1,
148b39c5158Smillert                        compare    => 2,
149b39c5158Smillert                        prefix     => 2,
150b39c5158Smillert                        lorder     => 1,
151b39c5158Smillert                     },
152b39c5158Smillert            GOT   => {},
153b39c5158Smillert          }, $pkg ;
154b39c5158Smillert}
155b39c5158Smillert
156b39c5158Smillert
157b39c5158Smillertpackage DB_File ;
158b39c5158Smillert
159b39c5158Smillertuse warnings;
160b39c5158Smillertuse strict;
161b39c5158Smillertour ($VERSION, @ISA, @EXPORT, $AUTOLOAD, $DB_BTREE, $DB_HASH, $DB_RECNO);
162898184e3Ssthenour ($db_version, $use_XSLoader, $splice_end_array_no_length, $splice_end_array, $Error);
163b39c5158Smillertuse Carp;
164b39c5158Smillert
165b46d8ef2Safresh1# Module not thread safe, so don't clone
166b46d8ef2Safresh1sub CLONE_SKIP { 1 }
167b39c5158Smillert
168*3d61058aSafresh1$VERSION = "1.859" ;
169b39c5158Smillert$VERSION = eval $VERSION; # needed for dev releases
170b39c5158Smillert
171b39c5158Smillert{
17291f110e0Safresh1    local $SIG{__WARN__} = sub {$splice_end_array_no_length = join(" ",@_);};
173b39c5158Smillert    my @a =(1); splice(@a, 3);
174898184e3Ssthen    $splice_end_array_no_length =
175898184e3Ssthen        ($splice_end_array_no_length =~ /^splice\(\) offset past end of array at /);
176898184e3Ssthen}
177898184e3Ssthen{
17891f110e0Safresh1    local $SIG{__WARN__} = sub {$splice_end_array = join(" ", @_);};
179898184e3Ssthen    my @a =(1); splice(@a, 3, 1);
180b39c5158Smillert    $splice_end_array =
181b39c5158Smillert        ($splice_end_array =~ /^splice\(\) offset past end of array at /);
182b39c5158Smillert}
183b39c5158Smillert
184b39c5158Smillert#typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
185eac174f2Safresh1$DB_BTREE = DB_File::BTREEINFO->new();
186eac174f2Safresh1$DB_HASH  = DB_File::HASHINFO->new();
187eac174f2Safresh1$DB_RECNO = DB_File::RECNOINFO->new();
188b39c5158Smillert
189b39c5158Smillertrequire Tie::Hash;
190b39c5158Smillertrequire Exporter;
191b39c5158SmillertBEGIN {
192b39c5158Smillert    $use_XSLoader = 1 ;
193b39c5158Smillert    { local $SIG{__DIE__} ; eval { require XSLoader } ; }
194b39c5158Smillert
195b39c5158Smillert    if ($@) {
196b39c5158Smillert        $use_XSLoader = 0 ;
197b39c5158Smillert        require DynaLoader;
198b39c5158Smillert        @ISA = qw(DynaLoader);
199b39c5158Smillert    }
200b39c5158Smillert}
201b39c5158Smillert
202b39c5158Smillertpush @ISA, qw(Tie::Hash Exporter);
203b39c5158Smillert@EXPORT = qw(
204b39c5158Smillert        $DB_BTREE $DB_HASH $DB_RECNO
205b39c5158Smillert
206b39c5158Smillert        BTREEMAGIC
207b39c5158Smillert        BTREEVERSION
208b39c5158Smillert        DB_LOCK
209b39c5158Smillert        DB_SHMEM
210b39c5158Smillert        DB_TXN
211b39c5158Smillert        HASHMAGIC
212b39c5158Smillert        HASHVERSION
213b39c5158Smillert        MAX_PAGE_NUMBER
214b39c5158Smillert        MAX_PAGE_OFFSET
215b39c5158Smillert        MAX_REC_NUMBER
216b39c5158Smillert        RET_ERROR
217b39c5158Smillert        RET_SPECIAL
218b39c5158Smillert        RET_SUCCESS
219b39c5158Smillert        R_CURSOR
220b39c5158Smillert        R_DUP
221b39c5158Smillert        R_FIRST
222b39c5158Smillert        R_FIXEDLEN
223b39c5158Smillert        R_IAFTER
224b39c5158Smillert        R_IBEFORE
225b39c5158Smillert        R_LAST
226b39c5158Smillert        R_NEXT
227b39c5158Smillert        R_NOKEY
228b39c5158Smillert        R_NOOVERWRITE
229b39c5158Smillert        R_PREV
230b39c5158Smillert        R_RECNOSYNC
231b39c5158Smillert        R_SETCURSOR
232b39c5158Smillert        R_SNAPSHOT
233b39c5158Smillert        __R_UNUSED
234b39c5158Smillert
235b39c5158Smillert);
236b39c5158Smillert
237b39c5158Smillertsub AUTOLOAD {
238b39c5158Smillert    my($constname);
239b39c5158Smillert    ($constname = $AUTOLOAD) =~ s/.*:://;
240b39c5158Smillert    my ($error, $val) = constant($constname);
241b39c5158Smillert    Carp::croak $error if $error;
242b39c5158Smillert    no strict 'refs';
243b39c5158Smillert    *{$AUTOLOAD} = sub { $val };
244b39c5158Smillert    goto &{$AUTOLOAD};
245b39c5158Smillert}
246b39c5158Smillert
247b39c5158Smillert
248b39c5158Smillerteval {
249b39c5158Smillert    # Make all Fcntl O_XXX constants available for importing
250b39c5158Smillert    require Fcntl;
251b39c5158Smillert    my @O = grep /^O_/, @Fcntl::EXPORT;
252b39c5158Smillert    Fcntl->import(@O);  # first we import what we want to export
253b39c5158Smillert    push(@EXPORT, @O);
254b39c5158Smillert};
255b39c5158Smillert
256b39c5158Smillertif ($use_XSLoader)
257b39c5158Smillert  { XSLoader::load("DB_File", $VERSION)}
258b39c5158Smillertelse
259eac174f2Safresh1  { DB_File->bootstrap( $VERSION ) }
260b39c5158Smillert
261b39c5158Smillertsub tie_hash_or_array
262b39c5158Smillert{
263b39c5158Smillert    my (@arg) = @_ ;
264b39c5158Smillert    my $tieHASH = ( (caller(1))[3] =~ /TIEHASH/ ) ;
265b39c5158Smillert
266b39c5158Smillert    use File::Spec;
267b39c5158Smillert    $arg[1] = File::Spec->rel2abs($arg[1])
268b39c5158Smillert        if defined $arg[1] ;
269b39c5158Smillert
270b39c5158Smillert    $arg[4] = tied %{ $arg[4] }
271b39c5158Smillert        if @arg >= 5 && ref $arg[4] && $arg[4] =~ /=HASH/ && tied %{ $arg[4] } ;
272b39c5158Smillert
273b39c5158Smillert    $arg[2] = O_CREAT()|O_RDWR() if @arg >=3 && ! defined $arg[2];
274b39c5158Smillert    $arg[3] = 0666               if @arg >=4 && ! defined $arg[3];
275b39c5158Smillert
276b39c5158Smillert    # make recno in Berkeley DB version 2 (or better) work like
277b39c5158Smillert    # recno in version 1.
278b39c5158Smillert    if ($db_version >= 4 and ! $tieHASH) {
279b39c5158Smillert        $arg[2] |= O_CREAT();
280b39c5158Smillert    }
281b39c5158Smillert
282b39c5158Smillert    if ($db_version > 1 and defined $arg[4] and $arg[4] =~ /RECNO/ and
283b39c5158Smillert        $arg[1] and ! -e $arg[1]) {
284b39c5158Smillert        open(FH, ">$arg[1]") or return undef ;
285b39c5158Smillert        close FH ;
286b39c5158Smillert        chmod $arg[3] ? $arg[3] : 0666 , $arg[1] ;
287b39c5158Smillert    }
288b39c5158Smillert
289b39c5158Smillert    DoTie_($tieHASH, @arg) ;
290b39c5158Smillert}
291b39c5158Smillert
292b39c5158Smillertsub TIEHASH
293b39c5158Smillert{
294b39c5158Smillert    tie_hash_or_array(@_) ;
295b39c5158Smillert}
296b39c5158Smillert
297b39c5158Smillertsub TIEARRAY
298b39c5158Smillert{
299b39c5158Smillert    tie_hash_or_array(@_) ;
300b39c5158Smillert}
301b39c5158Smillert
302b39c5158Smillertsub CLEAR
303b39c5158Smillert{
304b39c5158Smillert    my $self = shift;
305b39c5158Smillert    my $key = 0 ;
306b39c5158Smillert    my $value = "" ;
307b39c5158Smillert    my $status = $self->seq($key, $value, R_FIRST());
308b39c5158Smillert    my @keys;
309b39c5158Smillert
310b39c5158Smillert    while ($status == 0) {
311b39c5158Smillert        push @keys, $key;
312b39c5158Smillert        $status = $self->seq($key, $value, R_NEXT());
313b39c5158Smillert    }
314b39c5158Smillert    foreach $key (reverse @keys) {
315b39c5158Smillert        my $s = $self->del($key);
316b39c5158Smillert    }
317b39c5158Smillert}
318b39c5158Smillert
319b39c5158Smillertsub EXTEND { }
320b39c5158Smillert
321b39c5158Smillertsub STORESIZE
322b39c5158Smillert{
323b39c5158Smillert    my $self = shift;
324b39c5158Smillert    my $length = shift ;
325b39c5158Smillert    my $current_length = $self->length() ;
326b39c5158Smillert
327b39c5158Smillert    if ($length < $current_length) {
328b39c5158Smillert        my $key ;
329b39c5158Smillert        for ($key = $current_length - 1 ; $key >= $length ; -- $key)
330b39c5158Smillert          { $self->del($key) }
331b39c5158Smillert    }
332b39c5158Smillert    elsif ($length > $current_length) {
333b39c5158Smillert        $self->put($length-1, "") ;
334b39c5158Smillert    }
335b39c5158Smillert}
336b39c5158Smillert
337b39c5158Smillert
338b39c5158Smillertsub SPLICE
339b39c5158Smillert{
340b39c5158Smillert    my $self = shift;
341b39c5158Smillert    my $offset = shift;
342b39c5158Smillert    if (not defined $offset) {
343b39c5158Smillert        warnings::warnif('uninitialized', 'Use of uninitialized value in splice');
344b39c5158Smillert        $offset = 0;
345b39c5158Smillert    }
346b39c5158Smillert
347898184e3Ssthen    my $has_length = @_;
348b39c5158Smillert    my $length = @_ ? shift : 0;
349b39c5158Smillert    # Carping about definedness comes _after_ the OFFSET sanity check.
350b39c5158Smillert    # This is so we get the same error messages as Perl's splice().
351b39c5158Smillert    #
352b39c5158Smillert
353b39c5158Smillert    my @list = @_;
354b39c5158Smillert
355b39c5158Smillert    my $size = $self->FETCHSIZE();
356b39c5158Smillert
357b39c5158Smillert    # 'If OFFSET is negative then it start that far from the end of
358b39c5158Smillert    # the array.'
359b39c5158Smillert    #
360b39c5158Smillert    if ($offset < 0) {
361b39c5158Smillert        my $new_offset = $size + $offset;
362b39c5158Smillert        if ($new_offset < 0) {
363b39c5158Smillert            die "Modification of non-creatable array value attempted, "
364b39c5158Smillert              . "subscript $offset";
365b39c5158Smillert        }
366b39c5158Smillert        $offset = $new_offset;
367b39c5158Smillert    }
368b39c5158Smillert
369b39c5158Smillert    if (not defined $length) {
370b39c5158Smillert        warnings::warnif('uninitialized', 'Use of uninitialized value in splice');
371b39c5158Smillert        $length = 0;
372b39c5158Smillert    }
373b39c5158Smillert
374b39c5158Smillert    if ($offset > $size) {
375b39c5158Smillert        $offset = $size;
376b39c5158Smillert        warnings::warnif('misc', 'splice() offset past end of array')
377898184e3Ssthen            if $has_length ? $splice_end_array : $splice_end_array_no_length;
378b39c5158Smillert    }
379b39c5158Smillert
380b39c5158Smillert    # 'If LENGTH is omitted, removes everything from OFFSET onward.'
381b39c5158Smillert    if (not defined $length) {
382b39c5158Smillert        $length = $size - $offset;
383b39c5158Smillert    }
384b39c5158Smillert
385b39c5158Smillert    # 'If LENGTH is negative, leave that many elements off the end of
386b39c5158Smillert    # the array.'
387b39c5158Smillert    #
388b39c5158Smillert    if ($length < 0) {
389b39c5158Smillert        $length = $size - $offset + $length;
390b39c5158Smillert
391b39c5158Smillert        if ($length < 0) {
392b39c5158Smillert            # The user must have specified a length bigger than the
393b39c5158Smillert            # length of the array passed in.  But perl's splice()
394b39c5158Smillert            # doesn't catch this, it just behaves as for length=0.
395b39c5158Smillert            #
396b39c5158Smillert            $length = 0;
397b39c5158Smillert        }
398b39c5158Smillert    }
399b39c5158Smillert
400b39c5158Smillert    if ($length > $size - $offset) {
401b39c5158Smillert        $length = $size - $offset;
402b39c5158Smillert    }
403b39c5158Smillert
404b39c5158Smillert    # $num_elems holds the current number of elements in the database.
405b39c5158Smillert    my $num_elems = $size;
406b39c5158Smillert
407b39c5158Smillert    # 'Removes the elements designated by OFFSET and LENGTH from an
408b39c5158Smillert    # array,'...
409b39c5158Smillert    #
410b39c5158Smillert    my @removed = ();
411b39c5158Smillert    foreach (0 .. $length - 1) {
412b39c5158Smillert        my $old;
413b39c5158Smillert        my $status = $self->get($offset, $old);
414b39c5158Smillert        if ($status != 0) {
415b39c5158Smillert            my $msg = "error from Berkeley DB on get($offset, \$old)";
416b39c5158Smillert            if ($status == 1) {
417b39c5158Smillert                $msg .= ' (no such element?)';
418b39c5158Smillert            }
419b39c5158Smillert            else {
420b39c5158Smillert                $msg .= ": error status $status";
421b39c5158Smillert                if (defined $! and $! ne '') {
422b39c5158Smillert                    $msg .= ", message $!";
423b39c5158Smillert                }
424b39c5158Smillert            }
425b39c5158Smillert            die $msg;
426b39c5158Smillert        }
427b39c5158Smillert        push @removed, $old;
428b39c5158Smillert
429b39c5158Smillert        $status = $self->del($offset);
430b39c5158Smillert        if ($status != 0) {
431b39c5158Smillert            my $msg = "error from Berkeley DB on del($offset)";
432b39c5158Smillert            if ($status == 1) {
433b39c5158Smillert                $msg .= ' (no such element?)';
434b39c5158Smillert            }
435b39c5158Smillert            else {
436b39c5158Smillert                $msg .= ": error status $status";
437b39c5158Smillert                if (defined $! and $! ne '') {
438b39c5158Smillert                    $msg .= ", message $!";
439b39c5158Smillert                }
440b39c5158Smillert            }
441b39c5158Smillert            die $msg;
442b39c5158Smillert        }
443b39c5158Smillert
444b39c5158Smillert        -- $num_elems;
445b39c5158Smillert    }
446b39c5158Smillert
447b39c5158Smillert    # ...'and replaces them with the elements of LIST, if any.'
448b39c5158Smillert    my $pos = $offset;
449b39c5158Smillert    while (defined (my $elem = shift @list)) {
450b39c5158Smillert        my $old_pos = $pos;
451b39c5158Smillert        my $status;
452b39c5158Smillert        if ($pos >= $num_elems) {
453b39c5158Smillert            $status = $self->put($pos, $elem);
454b39c5158Smillert        }
455b39c5158Smillert        else {
456b39c5158Smillert            $status = $self->put($pos, $elem, $self->R_IBEFORE);
457b39c5158Smillert        }
458b39c5158Smillert
459b39c5158Smillert        if ($status != 0) {
460b39c5158Smillert            my $msg = "error from Berkeley DB on put($pos, $elem, ...)";
461b39c5158Smillert            if ($status == 1) {
462b39c5158Smillert                $msg .= ' (no such element?)';
463b39c5158Smillert            }
464b39c5158Smillert            else {
465b39c5158Smillert                $msg .= ", error status $status";
466b39c5158Smillert                if (defined $! and $! ne '') {
467b39c5158Smillert                    $msg .= ", message $!";
468b39c5158Smillert                }
469b39c5158Smillert            }
470b39c5158Smillert            die $msg;
471b39c5158Smillert        }
472b39c5158Smillert
473b39c5158Smillert        die "pos unexpectedly changed from $old_pos to $pos with R_IBEFORE"
474b39c5158Smillert          if $old_pos != $pos;
475b39c5158Smillert
476b39c5158Smillert        ++ $pos;
477b39c5158Smillert        ++ $num_elems;
478b39c5158Smillert    }
479b39c5158Smillert
480b39c5158Smillert    if (wantarray) {
481b39c5158Smillert        # 'In list context, returns the elements removed from the
482b39c5158Smillert        # array.'
483b39c5158Smillert        #
484b39c5158Smillert        return @removed;
485b39c5158Smillert    }
486b39c5158Smillert    elsif (defined wantarray and not wantarray) {
487b39c5158Smillert        # 'In scalar context, returns the last element removed, or
488b39c5158Smillert        # undef if no elements are removed.'
489b39c5158Smillert        #
490b39c5158Smillert        if (@removed) {
491b39c5158Smillert            my $last = pop @removed;
492b39c5158Smillert            return "$last";
493b39c5158Smillert        }
494b39c5158Smillert        else {
495b39c5158Smillert            return undef;
496b39c5158Smillert        }
497b39c5158Smillert    }
498b39c5158Smillert    elsif (not defined wantarray) {
499b39c5158Smillert        # Void context
500b39c5158Smillert    }
501b39c5158Smillert    else { die }
502b39c5158Smillert}
503b39c5158Smillertsub ::DB_File::splice { &SPLICE }
504b39c5158Smillert
505b39c5158Smillertsub find_dup
506b39c5158Smillert{
507b39c5158Smillert    croak "Usage: \$db->find_dup(key,value)\n"
508b39c5158Smillert        unless @_ == 3 ;
509b39c5158Smillert
510b39c5158Smillert    my $db        = shift ;
511b39c5158Smillert    my ($origkey, $value_wanted) = @_ ;
512b39c5158Smillert    my ($key, $value) = ($origkey, 0);
513b39c5158Smillert    my ($status) = 0 ;
514b39c5158Smillert
515b39c5158Smillert    for ($status = $db->seq($key, $value, R_CURSOR() ) ;
516b39c5158Smillert         $status == 0 ;
517b39c5158Smillert         $status = $db->seq($key, $value, R_NEXT() ) ) {
518b39c5158Smillert
519b39c5158Smillert        return 0 if $key eq $origkey and $value eq $value_wanted ;
520b39c5158Smillert    }
521b39c5158Smillert
522b39c5158Smillert    return $status ;
523b39c5158Smillert}
524b39c5158Smillert
525b39c5158Smillertsub del_dup
526b39c5158Smillert{
527b39c5158Smillert    croak "Usage: \$db->del_dup(key,value)\n"
528b39c5158Smillert        unless @_ == 3 ;
529b39c5158Smillert
530b39c5158Smillert    my $db        = shift ;
531b39c5158Smillert    my ($key, $value) = @_ ;
532b39c5158Smillert    my ($status) = $db->find_dup($key, $value) ;
533b39c5158Smillert    return $status if $status != 0 ;
534b39c5158Smillert
535b39c5158Smillert    $status = $db->del($key, R_CURSOR() ) ;
536b39c5158Smillert    return $status ;
537b39c5158Smillert}
538b39c5158Smillert
539b39c5158Smillertsub get_dup
540b39c5158Smillert{
541b39c5158Smillert    croak "Usage: \$db->get_dup(key [,flag])\n"
542b39c5158Smillert        unless @_ == 2 or @_ == 3 ;
543b39c5158Smillert
544b39c5158Smillert    my $db        = shift ;
545b39c5158Smillert    my $key       = shift ;
546b39c5158Smillert    my $flag      = shift ;
547b39c5158Smillert    my $value     = 0 ;
548b39c5158Smillert    my $origkey   = $key ;
549b39c5158Smillert    my $wantarray = wantarray ;
550b39c5158Smillert    my %values    = () ;
551b39c5158Smillert    my @values    = () ;
552b39c5158Smillert    my $counter   = 0 ;
553b39c5158Smillert    my $status    = 0 ;
554b39c5158Smillert
555b39c5158Smillert    # iterate through the database until either EOF ($status == 0)
556b39c5158Smillert    # or a different key is encountered ($key ne $origkey).
557b39c5158Smillert    for ($status = $db->seq($key, $value, R_CURSOR()) ;
558b39c5158Smillert         $status == 0 and $key eq $origkey ;
559b39c5158Smillert         $status = $db->seq($key, $value, R_NEXT()) ) {
560b39c5158Smillert
561b39c5158Smillert        # save the value or count number of matches
562b39c5158Smillert        if ($wantarray) {
563b39c5158Smillert            if ($flag)
564b39c5158Smillert                { ++ $values{$value} }
565b39c5158Smillert            else
566b39c5158Smillert                { push (@values, $value) }
567b39c5158Smillert        }
568b39c5158Smillert        else
569b39c5158Smillert            { ++ $counter }
570b39c5158Smillert
571b39c5158Smillert    }
572b39c5158Smillert
573b39c5158Smillert    return ($wantarray ? ($flag ? %values : @values) : $counter) ;
574b39c5158Smillert}
575b39c5158Smillert
576b39c5158Smillert
577898184e3Ssthensub STORABLE_freeze
578898184e3Ssthen{
579898184e3Ssthen    my $type = ref shift;
580898184e3Ssthen    croak "Cannot freeze $type object\n";
581898184e3Ssthen}
582898184e3Ssthen
583898184e3Ssthensub STORABLE_thaw
584898184e3Ssthen{
585898184e3Ssthen    my $type = ref shift;
586898184e3Ssthen    croak "Cannot thaw $type object\n";
587898184e3Ssthen}
588898184e3Ssthen
589898184e3Ssthen
590898184e3Ssthen
591b39c5158Smillert1;
592b39c5158Smillert__END__
593b39c5158Smillert
594b39c5158Smillert=head1 NAME
595b39c5158Smillert
596b39c5158SmillertDB_File - Perl5 access to Berkeley DB version 1.x
597b39c5158Smillert
598b39c5158Smillert=head1 SYNOPSIS
599b39c5158Smillert
600b39c5158Smillert use DB_File;
601b39c5158Smillert
602b39c5158Smillert [$X =] tie %hash,  'DB_File', [$filename, $flags, $mode, $DB_HASH] ;
603b39c5158Smillert [$X =] tie %hash,  'DB_File', $filename, $flags, $mode, $DB_BTREE ;
604b39c5158Smillert [$X =] tie @array, 'DB_File', $filename, $flags, $mode, $DB_RECNO ;
605b39c5158Smillert
606b39c5158Smillert $status = $X->del($key [, $flags]) ;
607b39c5158Smillert $status = $X->put($key, $value [, $flags]) ;
608b39c5158Smillert $status = $X->get($key, $value [, $flags]) ;
609b39c5158Smillert $status = $X->seq($key, $value, $flags) ;
610b39c5158Smillert $status = $X->sync([$flags]) ;
611b39c5158Smillert $status = $X->fd ;
612b39c5158Smillert
613b39c5158Smillert # BTREE only
614b39c5158Smillert $count = $X->get_dup($key) ;
615b39c5158Smillert @list  = $X->get_dup($key) ;
616b39c5158Smillert %list  = $X->get_dup($key, 1) ;
617b39c5158Smillert $status = $X->find_dup($key, $value) ;
618b39c5158Smillert $status = $X->del_dup($key, $value) ;
619b39c5158Smillert
620b39c5158Smillert # RECNO only
621b39c5158Smillert $a = $X->length;
622b39c5158Smillert $a = $X->pop ;
623b39c5158Smillert $X->push(list);
624b39c5158Smillert $a = $X->shift;
625b39c5158Smillert $X->unshift(list);
626b39c5158Smillert @r = $X->splice(offset, length, elements);
627b39c5158Smillert
628b39c5158Smillert # DBM Filters
629b39c5158Smillert $old_filter = $db->filter_store_key  ( sub { ... } ) ;
630b39c5158Smillert $old_filter = $db->filter_store_value( sub { ... } ) ;
631b39c5158Smillert $old_filter = $db->filter_fetch_key  ( sub { ... } ) ;
632b39c5158Smillert $old_filter = $db->filter_fetch_value( sub { ... } ) ;
633b39c5158Smillert
634b39c5158Smillert untie %hash ;
635b39c5158Smillert untie @array ;
636b39c5158Smillert
637b39c5158Smillert=head1 DESCRIPTION
638b39c5158Smillert
639b39c5158SmillertB<DB_File> is a module which allows Perl programs to make use of the
640b39c5158Smillertfacilities provided by Berkeley DB version 1.x (if you have a newer
641b39c5158Smillertversion of DB, see L<Using DB_File with Berkeley DB version 2 or greater>).
642b39c5158SmillertIt is assumed that you have a copy of the Berkeley DB manual pages at
643b39c5158Smillerthand when reading this documentation. The interface defined here
644b39c5158Smillertmirrors the Berkeley DB interface closely.
645b39c5158Smillert
646b39c5158SmillertBerkeley DB is a C library which provides a consistent interface to a
647b39c5158Smillertnumber of database formats.  B<DB_File> provides an interface to all
648b39c5158Smillertthree of the database types currently supported by Berkeley DB.
649b39c5158Smillert
650b39c5158SmillertThe file types are:
651b39c5158Smillert
652b39c5158Smillert=over 5
653b39c5158Smillert
654b39c5158Smillert=item B<DB_HASH>
655b39c5158Smillert
656b39c5158SmillertThis database type allows arbitrary key/value pairs to be stored in data
657b39c5158Smillertfiles. This is equivalent to the functionality provided by other
658b39c5158Smillerthashing packages like DBM, NDBM, ODBM, GDBM, and SDBM. Remember though,
659b39c5158Smillertthe files created using DB_HASH are not compatible with any of the
660b39c5158Smillertother packages mentioned.
661b39c5158Smillert
662b39c5158SmillertA default hashing algorithm, which will be adequate for most
663b39c5158Smillertapplications, is built into Berkeley DB. If you do need to use your own
664b39c5158Smillerthashing algorithm it is possible to write your own in Perl and have
665b39c5158SmillertB<DB_File> use it instead.
666b39c5158Smillert
667b39c5158Smillert=item B<DB_BTREE>
668b39c5158Smillert
669b39c5158SmillertThe btree format allows arbitrary key/value pairs to be stored in a
670b39c5158Smillertsorted, balanced binary tree.
671b39c5158Smillert
672b39c5158SmillertAs with the DB_HASH format, it is possible to provide a user defined
673b39c5158SmillertPerl routine to perform the comparison of keys. By default, though, the
674b39c5158Smillertkeys are stored in lexical order.
675b39c5158Smillert
676b39c5158Smillert=item B<DB_RECNO>
677b39c5158Smillert
678b39c5158SmillertDB_RECNO allows both fixed-length and variable-length flat text files
679b39c5158Smillertto be manipulated using the same key/value pair interface as in DB_HASH
680b39c5158Smillertand DB_BTREE.  In this case the key will consist of a record (line)
681b39c5158Smillertnumber.
682b39c5158Smillert
683b39c5158Smillert=back
684b39c5158Smillert
685b39c5158Smillert=head2 Using DB_File with Berkeley DB version 2 or greater
686b39c5158Smillert
687b39c5158SmillertAlthough B<DB_File> is intended to be used with Berkeley DB version 1,
688b39c5158Smillertit can also be used with version 2, 3 or 4. In this case the interface is
689b39c5158Smillertlimited to the functionality provided by Berkeley DB 1.x. Anywhere the
690b39c5158Smillertversion 2 or greater interface differs, B<DB_File> arranges for it to work
691b39c5158Smillertlike version 1. This feature allows B<DB_File> scripts that were built
692b39c5158Smillertwith version 1 to be migrated to version 2 or greater without any changes.
693b39c5158Smillert
694b39c5158SmillertIf you want to make use of the new features available in Berkeley DB
69556d68f1eSafresh12.x or greater, use the Perl module L<BerkeleyDB|https://metacpan.org/pod/BerkeleyDB> instead.
696b39c5158Smillert
697b39c5158SmillertB<Note:> The database file format has changed multiple times in Berkeley
698b39c5158SmillertDB version 2, 3 and 4. If you cannot recreate your databases, you
699b39c5158Smillertmust dump any existing databases with either the C<db_dump> or the
700b39c5158SmillertC<db_dump185> utility that comes with Berkeley DB.
701b39c5158SmillertOnce you have rebuilt DB_File to use Berkeley DB version 2 or greater,
702b39c5158Smillertyour databases can be recreated using C<db_load>. Refer to the Berkeley DB
703b39c5158Smillertdocumentation for further details.
704b39c5158Smillert
705b39c5158SmillertPlease read L<"COPYRIGHT"> before using version 2.x or greater of Berkeley
706b39c5158SmillertDB with DB_File.
707b39c5158Smillert
708b39c5158Smillert=head2 Interface to Berkeley DB
709b39c5158Smillert
710b39c5158SmillertB<DB_File> allows access to Berkeley DB files using the tie() mechanism
711b39c5158Smillertin Perl 5 (for full details, see L<perlfunc/tie()>). This facility
712b39c5158Smillertallows B<DB_File> to access Berkeley DB files using either an
713b39c5158Smillertassociative array (for DB_HASH & DB_BTREE file types) or an ordinary
714b39c5158Smillertarray (for the DB_RECNO file type).
715b39c5158Smillert
716b39c5158SmillertIn addition to the tie() interface, it is also possible to access most
717b39c5158Smillertof the functions provided in the Berkeley DB API directly.
718b39c5158SmillertSee L<THE API INTERFACE>.
719b39c5158Smillert
720b39c5158Smillert=head2 Opening a Berkeley DB Database File
721b39c5158Smillert
722b39c5158SmillertBerkeley DB uses the function dbopen() to open or create a database.
723b39c5158SmillertHere is the C prototype for dbopen():
724b39c5158Smillert
725b39c5158Smillert      DB*
726b39c5158Smillert      dbopen (const char * file, int flags, int mode,
727b39c5158Smillert              DBTYPE type, const void * openinfo)
728b39c5158Smillert
729b39c5158SmillertThe parameter C<type> is an enumeration which specifies which of the 3
730b39c5158Smillertinterface methods (DB_HASH, DB_BTREE or DB_RECNO) is to be used.
731b39c5158SmillertDepending on which of these is actually chosen, the final parameter,
732b39c5158SmillertI<openinfo> points to a data structure which allows tailoring of the
733b39c5158Smillertspecific interface method.
734b39c5158Smillert
735b39c5158SmillertThis interface is handled slightly differently in B<DB_File>. Here is
736b39c5158Smillertan equivalent call using B<DB_File>:
737b39c5158Smillert
738b39c5158Smillert        tie %array, 'DB_File', $filename, $flags, $mode, $DB_HASH ;
739b39c5158Smillert
740b39c5158SmillertThe C<filename>, C<flags> and C<mode> parameters are the direct
741b39c5158Smillertequivalent of their dbopen() counterparts. The final parameter $DB_HASH
742b39c5158Smillertperforms the function of both the C<type> and C<openinfo> parameters in
743b39c5158Smillertdbopen().
744b39c5158Smillert
745b39c5158SmillertIn the example above $DB_HASH is actually a pre-defined reference to a
746b39c5158Smillerthash object. B<DB_File> has three of these pre-defined references.
747b39c5158SmillertApart from $DB_HASH, there is also $DB_BTREE and $DB_RECNO.
748b39c5158Smillert
749b39c5158SmillertThe keys allowed in each of these pre-defined references is limited to
750b39c5158Smillertthe names used in the equivalent C structure. So, for example, the
751b39c5158Smillert$DB_HASH reference will only allow keys called C<bsize>, C<cachesize>,
752b39c5158SmillertC<ffactor>, C<hash>, C<lorder> and C<nelem>.
753b39c5158Smillert
754b39c5158SmillertTo change one of these elements, just assign to it like this:
755b39c5158Smillert
756b39c5158Smillert        $DB_HASH->{'cachesize'} = 10000 ;
757b39c5158Smillert
758b39c5158SmillertThe three predefined variables $DB_HASH, $DB_BTREE and $DB_RECNO are
759b39c5158Smillertusually adequate for most applications.  If you do need to create extra
760b39c5158Smillertinstances of these objects, constructors are available for each file
761b39c5158Smillerttype.
762b39c5158Smillert
763b39c5158SmillertHere are examples of the constructors and the valid options available
764b39c5158Smillertfor DB_HASH, DB_BTREE and DB_RECNO respectively.
765b39c5158Smillert
766eac174f2Safresh1     $a = DB_File::HASHINFO->new();
767b39c5158Smillert     $a->{'bsize'} ;
768b39c5158Smillert     $a->{'cachesize'} ;
769b39c5158Smillert     $a->{'ffactor'};
770b39c5158Smillert     $a->{'hash'} ;
771b39c5158Smillert     $a->{'lorder'} ;
772b39c5158Smillert     $a->{'nelem'} ;
773b39c5158Smillert
774eac174f2Safresh1     $b = DB_File::BTREEINFO->new();
775b39c5158Smillert     $b->{'flags'} ;
776b39c5158Smillert     $b->{'cachesize'} ;
777b39c5158Smillert     $b->{'maxkeypage'} ;
778b39c5158Smillert     $b->{'minkeypage'} ;
779b39c5158Smillert     $b->{'psize'} ;
780b39c5158Smillert     $b->{'compare'} ;
781b39c5158Smillert     $b->{'prefix'} ;
782b39c5158Smillert     $b->{'lorder'} ;
783b39c5158Smillert
784eac174f2Safresh1     $c = DB_File::RECNOINFO->new();
785b39c5158Smillert     $c->{'bval'} ;
786b39c5158Smillert     $c->{'cachesize'} ;
787b39c5158Smillert     $c->{'psize'} ;
788b39c5158Smillert     $c->{'flags'} ;
789b39c5158Smillert     $c->{'lorder'} ;
790b39c5158Smillert     $c->{'reclen'} ;
791b39c5158Smillert     $c->{'bfname'} ;
792b39c5158Smillert
793b39c5158SmillertThe values stored in the hashes above are mostly the direct equivalent
794b39c5158Smillertof their C counterpart. Like their C counterparts, all are set to a
795b39c5158Smillertdefault values - that means you don't have to set I<all> of the
796b39c5158Smillertvalues when you only want to change one. Here is an example:
797b39c5158Smillert
798eac174f2Safresh1     $a = DB_File::HASHINFO->new();
799b39c5158Smillert     $a->{'cachesize'} =  12345 ;
800b39c5158Smillert     tie %y, 'DB_File', "filename", $flags, 0777, $a ;
801b39c5158Smillert
802b39c5158SmillertA few of the options need extra discussion here. When used, the C
803b39c5158Smillertequivalent of the keys C<hash>, C<compare> and C<prefix> store pointers
804b39c5158Smillertto C functions. In B<DB_File> these keys are used to store references
805b39c5158Smillertto Perl subs. Below are templates for each of the subs:
806b39c5158Smillert
807b39c5158Smillert    sub hash
808b39c5158Smillert    {
809b39c5158Smillert        my ($data) = @_ ;
810b39c5158Smillert        ...
811b39c5158Smillert        # return the hash value for $data
812b39c5158Smillert        return $hash ;
813b39c5158Smillert    }
814b39c5158Smillert
815b39c5158Smillert    sub compare
816b39c5158Smillert    {
817b39c5158Smillert        my ($key, $key2) = @_ ;
818b39c5158Smillert        ...
819b39c5158Smillert        # return  0 if $key1 eq $key2
820b39c5158Smillert        #        -1 if $key1 lt $key2
821b39c5158Smillert        #         1 if $key1 gt $key2
822b39c5158Smillert        return (-1 , 0 or 1) ;
823b39c5158Smillert    }
824b39c5158Smillert
825b39c5158Smillert    sub prefix
826b39c5158Smillert    {
827b39c5158Smillert        my ($key, $key2) = @_ ;
828b39c5158Smillert        ...
829b39c5158Smillert        # return number of bytes of $key2 which are
830b39c5158Smillert        # necessary to determine that it is greater than $key1
831b39c5158Smillert        return $bytes ;
832b39c5158Smillert    }
833b39c5158Smillert
834b39c5158SmillertSee L<Changing the BTREE sort order> for an example of using the
835b39c5158SmillertC<compare> template.
836b39c5158Smillert
837b39c5158SmillertIf you are using the DB_RECNO interface and you intend making use of
838b39c5158SmillertC<bval>, you should check out L<The 'bval' Option>.
839b39c5158Smillert
840b39c5158Smillert=head2 Default Parameters
841b39c5158Smillert
842b39c5158SmillertIt is possible to omit some or all of the final 4 parameters in the
843b39c5158Smillertcall to C<tie> and let them take default values. As DB_HASH is the most
844b39c5158Smillertcommon file format used, the call:
845b39c5158Smillert
846b39c5158Smillert    tie %A, "DB_File", "filename" ;
847b39c5158Smillert
848b39c5158Smillertis equivalent to:
849b39c5158Smillert
850b39c5158Smillert    tie %A, "DB_File", "filename", O_CREAT|O_RDWR, 0666, $DB_HASH ;
851b39c5158Smillert
852b39c5158SmillertIt is also possible to omit the filename parameter as well, so the
853b39c5158Smillertcall:
854b39c5158Smillert
855b39c5158Smillert    tie %A, "DB_File" ;
856b39c5158Smillert
857b39c5158Smillertis equivalent to:
858b39c5158Smillert
859b39c5158Smillert    tie %A, "DB_File", undef, O_CREAT|O_RDWR, 0666, $DB_HASH ;
860b39c5158Smillert
861b39c5158SmillertSee L<In Memory Databases> for a discussion on the use of C<undef>
862b39c5158Smillertin place of a filename.
863b39c5158Smillert
864b39c5158Smillert=head2 In Memory Databases
865b39c5158Smillert
866b39c5158SmillertBerkeley DB allows the creation of in-memory databases by using NULL
867b39c5158Smillert(that is, a C<(char *)0> in C) in place of the filename.  B<DB_File>
868b39c5158Smillertuses C<undef> instead of NULL to provide this functionality.
869b39c5158Smillert
870b39c5158Smillert=head1 DB_HASH
871b39c5158Smillert
872b39c5158SmillertThe DB_HASH file format is probably the most commonly used of the three
873b39c5158Smillertfile formats that B<DB_File> supports. It is also very straightforward
874b39c5158Smillertto use.
875b39c5158Smillert
876b39c5158Smillert=head2 A Simple Example
877b39c5158Smillert
878b39c5158SmillertThis example shows how to create a database, add key/value pairs to the
879b39c5158Smillertdatabase, delete keys/value pairs and finally how to enumerate the
880b39c5158Smillertcontents of the database.
881b39c5158Smillert
882b39c5158Smillert    use warnings ;
883b39c5158Smillert    use strict ;
884b39c5158Smillert    use DB_File ;
885b39c5158Smillert    our (%h, $k, $v) ;
886b39c5158Smillert
887b39c5158Smillert    unlink "fruit" ;
888b39c5158Smillert    tie %h, "DB_File", "fruit", O_RDWR|O_CREAT, 0666, $DB_HASH
889b39c5158Smillert        or die "Cannot open file 'fruit': $!\n";
890b39c5158Smillert
891b39c5158Smillert    # Add a few key/value pairs to the file
892b39c5158Smillert    $h{"apple"} = "red" ;
893b39c5158Smillert    $h{"orange"} = "orange" ;
894b39c5158Smillert    $h{"banana"} = "yellow" ;
895b39c5158Smillert    $h{"tomato"} = "red" ;
896b39c5158Smillert
897b39c5158Smillert    # Check for existence of a key
898b39c5158Smillert    print "Banana Exists\n\n" if $h{"banana"} ;
899b39c5158Smillert
900b39c5158Smillert    # Delete a key/value pair.
901b39c5158Smillert    delete $h{"apple"} ;
902b39c5158Smillert
903b39c5158Smillert    # print the contents of the file
904b39c5158Smillert    while (($k, $v) = each %h)
905b39c5158Smillert      { print "$k -> $v\n" }
906b39c5158Smillert
907b39c5158Smillert    untie %h ;
908b39c5158Smillert
909b39c5158Smillerthere is the output:
910b39c5158Smillert
911b39c5158Smillert    Banana Exists
912b39c5158Smillert
913b39c5158Smillert    orange -> orange
914b39c5158Smillert    tomato -> red
915b39c5158Smillert    banana -> yellow
916b39c5158Smillert
917b39c5158SmillertNote that the like ordinary associative arrays, the order of the keys
918b39c5158Smillertretrieved is in an apparently random order.
919b39c5158Smillert
920b39c5158Smillert=head1 DB_BTREE
921b39c5158Smillert
922b39c5158SmillertThe DB_BTREE format is useful when you want to store data in a given
923b39c5158Smillertorder. By default the keys will be stored in lexical order, but as you
924b39c5158Smillertwill see from the example shown in the next section, it is very easy to
925b39c5158Smillertdefine your own sorting function.
926b39c5158Smillert
927b39c5158Smillert=head2 Changing the BTREE sort order
928b39c5158Smillert
929b39c5158SmillertThis script shows how to override the default sorting algorithm that
930b39c5158SmillertBTREE uses. Instead of using the normal lexical ordering, a case
931b39c5158Smillertinsensitive compare function will be used.
932b39c5158Smillert
933b39c5158Smillert    use warnings ;
934b39c5158Smillert    use strict ;
935b39c5158Smillert    use DB_File ;
936b39c5158Smillert
937b39c5158Smillert    my %h ;
938b39c5158Smillert
939b39c5158Smillert    sub Compare
940b39c5158Smillert    {
941b39c5158Smillert        my ($key1, $key2) = @_ ;
942b39c5158Smillert        "\L$key1" cmp "\L$key2" ;
943b39c5158Smillert    }
944b39c5158Smillert
945b39c5158Smillert    # specify the Perl sub that will do the comparison
946b39c5158Smillert    $DB_BTREE->{'compare'} = \&Compare ;
947b39c5158Smillert
948b39c5158Smillert    unlink "tree" ;
949b39c5158Smillert    tie %h, "DB_File", "tree", O_RDWR|O_CREAT, 0666, $DB_BTREE
950b39c5158Smillert        or die "Cannot open file 'tree': $!\n" ;
951b39c5158Smillert
952b39c5158Smillert    # Add a key/value pair to the file
953b39c5158Smillert    $h{'Wall'} = 'Larry' ;
954b39c5158Smillert    $h{'Smith'} = 'John' ;
955b39c5158Smillert    $h{'mouse'} = 'mickey' ;
956b39c5158Smillert    $h{'duck'}  = 'donald' ;
957b39c5158Smillert
958b39c5158Smillert    # Delete
959b39c5158Smillert    delete $h{"duck"} ;
960b39c5158Smillert
961b39c5158Smillert    # Cycle through the keys printing them in order.
962b39c5158Smillert    # Note it is not necessary to sort the keys as
963b39c5158Smillert    # the btree will have kept them in order automatically.
964b39c5158Smillert    foreach (keys %h)
965b39c5158Smillert      { print "$_\n" }
966b39c5158Smillert
967b39c5158Smillert    untie %h ;
968b39c5158Smillert
969b39c5158SmillertHere is the output from the code above.
970b39c5158Smillert
971b39c5158Smillert    mouse
972b39c5158Smillert    Smith
973b39c5158Smillert    Wall
974b39c5158Smillert
975b39c5158SmillertThere are a few point to bear in mind if you want to change the
976b39c5158Smillertordering in a BTREE database:
977b39c5158Smillert
978b39c5158Smillert=over 5
979b39c5158Smillert
980b39c5158Smillert=item 1.
981b39c5158Smillert
982b39c5158SmillertThe new compare function must be specified when you create the database.
983b39c5158Smillert
984b39c5158Smillert=item 2.
985b39c5158Smillert
986b39c5158SmillertYou cannot change the ordering once the database has been created. Thus
987b39c5158Smillertyou must use the same compare function every time you access the
988b39c5158Smillertdatabase.
989b39c5158Smillert
990b39c5158Smillert=item 3
991b39c5158Smillert
992b39c5158SmillertDuplicate keys are entirely defined by the comparison function.
993b39c5158SmillertIn the case-insensitive example above, the keys: 'KEY' and 'key'
994b39c5158Smillertwould be considered duplicates, and assigning to the second one
995b39c5158Smillertwould overwrite the first. If duplicates are allowed for (with the
996b39c5158SmillertR_DUP flag discussed below), only a single copy of duplicate keys
997b39c5158Smillertis stored in the database --- so (again with example above) assigning
998b39c5158Smillertthree values to the keys: 'KEY', 'Key', and 'key' would leave just
999b39c5158Smillertthe first key: 'KEY' in the database with three values. For some
1000b39c5158Smillertsituations this results in information loss, so care should be taken
1001b39c5158Smillertto provide fully qualified comparison functions when necessary.
1002b39c5158SmillertFor example, the above comparison routine could be modified to
1003b39c5158Smillertadditionally compare case-sensitively if two keys are equal in the
1004b39c5158Smillertcase insensitive comparison:
1005b39c5158Smillert
1006b39c5158Smillert    sub compare {
1007b39c5158Smillert        my($key1, $key2) = @_;
1008b39c5158Smillert        lc $key1 cmp lc $key2 ||
1009b39c5158Smillert        $key1 cmp $key2;
1010b39c5158Smillert    }
1011b39c5158Smillert
1012b39c5158SmillertAnd now you will only have duplicates when the keys themselves
1013b39c5158Smillertare truly the same. (note: in versions of the db library prior to
1014b39c5158Smillertabout November 1996, such duplicate keys were retained so it was
1015b39c5158Smillertpossible to recover the original keys in sets of keys that
1016b39c5158Smillertcompared as equal).
1017b39c5158Smillert
1018b39c5158Smillert
1019b39c5158Smillert=back
1020b39c5158Smillert
1021b39c5158Smillert=head2 Handling Duplicate Keys
1022b39c5158Smillert
1023b39c5158SmillertThe BTREE file type optionally allows a single key to be associated
1024b39c5158Smillertwith an arbitrary number of values. This option is enabled by setting
1025b39c5158Smillertthe flags element of C<$DB_BTREE> to R_DUP when creating the database.
1026b39c5158Smillert
1027b39c5158SmillertThere are some difficulties in using the tied hash interface if you
1028b39c5158Smillertwant to manipulate a BTREE database with duplicate keys. Consider this
1029b39c5158Smillertcode:
1030b39c5158Smillert
1031b39c5158Smillert    use warnings ;
1032b39c5158Smillert    use strict ;
1033b39c5158Smillert    use DB_File ;
1034b39c5158Smillert
1035b39c5158Smillert    my ($filename, %h) ;
1036b39c5158Smillert
1037b39c5158Smillert    $filename = "tree" ;
1038b39c5158Smillert    unlink $filename ;
1039b39c5158Smillert
1040b39c5158Smillert    # Enable duplicate records
1041b39c5158Smillert    $DB_BTREE->{'flags'} = R_DUP ;
1042b39c5158Smillert
1043b39c5158Smillert    tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE
1044b39c5158Smillert        or die "Cannot open $filename: $!\n";
1045b39c5158Smillert
1046b39c5158Smillert    # Add some key/value pairs to the file
1047b39c5158Smillert    $h{'Wall'} = 'Larry' ;
1048b39c5158Smillert    $h{'Wall'} = 'Brick' ; # Note the duplicate key
1049b39c5158Smillert    $h{'Wall'} = 'Brick' ; # Note the duplicate key and value
1050b39c5158Smillert    $h{'Smith'} = 'John' ;
1051b39c5158Smillert    $h{'mouse'} = 'mickey' ;
1052b39c5158Smillert
1053b39c5158Smillert    # iterate through the associative array
1054b39c5158Smillert    # and print each key/value pair.
1055b39c5158Smillert    foreach (sort keys %h)
1056b39c5158Smillert      { print "$_  -> $h{$_}\n" }
1057b39c5158Smillert
1058b39c5158Smillert    untie %h ;
1059b39c5158Smillert
1060b39c5158SmillertHere is the output:
1061b39c5158Smillert
1062b39c5158Smillert    Smith   -> John
1063b39c5158Smillert    Wall    -> Larry
1064b39c5158Smillert    Wall    -> Larry
1065b39c5158Smillert    Wall    -> Larry
1066b39c5158Smillert    mouse   -> mickey
1067b39c5158Smillert
1068b39c5158SmillertAs you can see 3 records have been successfully created with key C<Wall>
1069b39c5158Smillert- the only thing is, when they are retrieved from the database they
1070b39c5158SmillertI<seem> to have the same value, namely C<Larry>. The problem is caused
1071b39c5158Smillertby the way that the associative array interface works. Basically, when
1072b39c5158Smillertthe associative array interface is used to fetch the value associated
1073b39c5158Smillertwith a given key, it will only ever retrieve the first value.
1074b39c5158Smillert
1075b39c5158SmillertAlthough it may not be immediately obvious from the code above, the
1076b39c5158Smillertassociative array interface can be used to write values with duplicate
1077b39c5158Smillertkeys, but it cannot be used to read them back from the database.
1078b39c5158Smillert
1079b39c5158SmillertThe way to get around this problem is to use the Berkeley DB API method
1080b39c5158Smillertcalled C<seq>.  This method allows sequential access to key/value
1081b39c5158Smillertpairs. See L<THE API INTERFACE> for details of both the C<seq> method
1082b39c5158Smillertand the API in general.
1083b39c5158Smillert
1084b39c5158SmillertHere is the script above rewritten using the C<seq> API method.
1085b39c5158Smillert
1086b39c5158Smillert    use warnings ;
1087b39c5158Smillert    use strict ;
1088b39c5158Smillert    use DB_File ;
1089b39c5158Smillert
1090b39c5158Smillert    my ($filename, $x, %h, $status, $key, $value) ;
1091b39c5158Smillert
1092b39c5158Smillert    $filename = "tree" ;
1093b39c5158Smillert    unlink $filename ;
1094b39c5158Smillert
1095b39c5158Smillert    # Enable duplicate records
1096b39c5158Smillert    $DB_BTREE->{'flags'} = R_DUP ;
1097b39c5158Smillert
1098b39c5158Smillert    $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE
1099b39c5158Smillert        or die "Cannot open $filename: $!\n";
1100b39c5158Smillert
1101b39c5158Smillert    # Add some key/value pairs to the file
1102b39c5158Smillert    $h{'Wall'} = 'Larry' ;
1103b39c5158Smillert    $h{'Wall'} = 'Brick' ; # Note the duplicate key
1104b39c5158Smillert    $h{'Wall'} = 'Brick' ; # Note the duplicate key and value
1105b39c5158Smillert    $h{'Smith'} = 'John' ;
1106b39c5158Smillert    $h{'mouse'} = 'mickey' ;
1107b39c5158Smillert
1108b39c5158Smillert    # iterate through the btree using seq
1109b39c5158Smillert    # and print each key/value pair.
1110b39c5158Smillert    $key = $value = 0 ;
1111b39c5158Smillert    for ($status = $x->seq($key, $value, R_FIRST) ;
1112b39c5158Smillert         $status == 0 ;
1113b39c5158Smillert         $status = $x->seq($key, $value, R_NEXT) )
1114b39c5158Smillert      {  print "$key -> $value\n" }
1115b39c5158Smillert
1116b39c5158Smillert    undef $x ;
1117b39c5158Smillert    untie %h ;
1118b39c5158Smillert
1119b39c5158Smillertthat prints:
1120b39c5158Smillert
1121b39c5158Smillert    Smith   -> John
1122b39c5158Smillert    Wall    -> Brick
1123b39c5158Smillert    Wall    -> Brick
1124b39c5158Smillert    Wall    -> Larry
1125b39c5158Smillert    mouse   -> mickey
1126b39c5158Smillert
1127b39c5158SmillertThis time we have got all the key/value pairs, including the multiple
1128b39c5158Smillertvalues associated with the key C<Wall>.
1129b39c5158Smillert
1130b39c5158SmillertTo make life easier when dealing with duplicate keys, B<DB_File> comes with
1131b39c5158Smillerta few utility methods.
1132b39c5158Smillert
1133b39c5158Smillert=head2 The get_dup() Method
1134b39c5158Smillert
1135b39c5158SmillertThe C<get_dup> method assists in
1136b39c5158Smillertreading duplicate values from BTREE databases. The method can take the
1137b39c5158Smillertfollowing forms:
1138b39c5158Smillert
1139b39c5158Smillert    $count = $x->get_dup($key) ;
1140b39c5158Smillert    @list  = $x->get_dup($key) ;
1141b39c5158Smillert    %list  = $x->get_dup($key, 1) ;
1142b39c5158Smillert
1143b39c5158SmillertIn a scalar context the method returns the number of values associated
1144b39c5158Smillertwith the key, C<$key>.
1145b39c5158Smillert
1146b39c5158SmillertIn list context, it returns all the values which match C<$key>. Note
1147b39c5158Smillertthat the values will be returned in an apparently random order.
1148b39c5158Smillert
1149b39c5158SmillertIn list context, if the second parameter is present and evaluates
1150b39c5158SmillertTRUE, the method returns an associative array. The keys of the
1151b39c5158Smillertassociative array correspond to the values that matched in the BTREE
1152b39c5158Smillertand the values of the array are a count of the number of times that
1153b39c5158Smillertparticular value occurred in the BTREE.
1154b39c5158Smillert
1155b39c5158SmillertSo assuming the database created above, we can use C<get_dup> like
1156b39c5158Smillertthis:
1157b39c5158Smillert
1158b39c5158Smillert    use warnings ;
1159b39c5158Smillert    use strict ;
1160b39c5158Smillert    use DB_File ;
1161b39c5158Smillert
1162b39c5158Smillert    my ($filename, $x, %h) ;
1163b39c5158Smillert
1164b39c5158Smillert    $filename = "tree" ;
1165b39c5158Smillert
1166b39c5158Smillert    # Enable duplicate records
1167b39c5158Smillert    $DB_BTREE->{'flags'} = R_DUP ;
1168b39c5158Smillert
1169b39c5158Smillert    $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE
1170b39c5158Smillert        or die "Cannot open $filename: $!\n";
1171b39c5158Smillert
1172b39c5158Smillert    my $cnt  = $x->get_dup("Wall") ;
1173b39c5158Smillert    print "Wall occurred $cnt times\n" ;
1174b39c5158Smillert
1175b39c5158Smillert    my %hash = $x->get_dup("Wall", 1) ;
1176b39c5158Smillert    print "Larry is there\n" if $hash{'Larry'} ;
1177b39c5158Smillert    print "There are $hash{'Brick'} Brick Walls\n" ;
1178b39c5158Smillert
1179b39c5158Smillert    my @list = sort $x->get_dup("Wall") ;
1180b39c5158Smillert    print "Wall =>      [@list]\n" ;
1181b39c5158Smillert
1182b39c5158Smillert    @list = $x->get_dup("Smith") ;
1183b39c5158Smillert    print "Smith =>     [@list]\n" ;
1184b39c5158Smillert
1185b39c5158Smillert    @list = $x->get_dup("Dog") ;
1186b39c5158Smillert    print "Dog =>       [@list]\n" ;
1187b39c5158Smillert
1188b39c5158Smillert
1189b39c5158Smillertand it will print:
1190b39c5158Smillert
1191b39c5158Smillert    Wall occurred 3 times
1192b39c5158Smillert    Larry is there
1193b39c5158Smillert    There are 2 Brick Walls
1194b39c5158Smillert    Wall =>     [Brick Brick Larry]
1195b39c5158Smillert    Smith =>    [John]
1196b39c5158Smillert    Dog =>      []
1197b39c5158Smillert
1198b39c5158Smillert=head2 The find_dup() Method
1199b39c5158Smillert
1200b39c5158Smillert    $status = $X->find_dup($key, $value) ;
1201b39c5158Smillert
1202b39c5158SmillertThis method checks for the existence of a specific key/value pair. If the
1203b39c5158Smillertpair exists, the cursor is left pointing to the pair and the method
1204b39c5158Smillertreturns 0. Otherwise the method returns a non-zero value.
1205b39c5158Smillert
1206b39c5158SmillertAssuming the database from the previous example:
1207b39c5158Smillert
1208b39c5158Smillert    use warnings ;
1209b39c5158Smillert    use strict ;
1210b39c5158Smillert    use DB_File ;
1211b39c5158Smillert
1212b39c5158Smillert    my ($filename, $x, %h, $found) ;
1213b39c5158Smillert
1214b39c5158Smillert    $filename = "tree" ;
1215b39c5158Smillert
1216b39c5158Smillert    # Enable duplicate records
1217b39c5158Smillert    $DB_BTREE->{'flags'} = R_DUP ;
1218b39c5158Smillert
1219b39c5158Smillert    $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE
1220b39c5158Smillert        or die "Cannot open $filename: $!\n";
1221b39c5158Smillert
1222b39c5158Smillert    $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ;
1223b39c5158Smillert    print "Larry Wall is $found there\n" ;
1224b39c5158Smillert
1225b39c5158Smillert    $found = ( $x->find_dup("Wall", "Harry") == 0 ? "" : "not") ;
1226b39c5158Smillert    print "Harry Wall is $found there\n" ;
1227b39c5158Smillert
1228b39c5158Smillert    undef $x ;
1229b39c5158Smillert    untie %h ;
1230b39c5158Smillert
1231b39c5158Smillertprints this
1232b39c5158Smillert
1233b39c5158Smillert    Larry Wall is  there
1234b39c5158Smillert    Harry Wall is not there
1235b39c5158Smillert
1236b39c5158Smillert
1237b39c5158Smillert=head2 The del_dup() Method
1238b39c5158Smillert
1239b39c5158Smillert    $status = $X->del_dup($key, $value) ;
1240b39c5158Smillert
1241b39c5158SmillertThis method deletes a specific key/value pair. It returns
1242b39c5158Smillert0 if they exist and have been deleted successfully.
1243b39c5158SmillertOtherwise the method returns a non-zero value.
1244b39c5158Smillert
1245b39c5158SmillertAgain assuming the existence of the C<tree> database
1246b39c5158Smillert
1247b39c5158Smillert    use warnings ;
1248b39c5158Smillert    use strict ;
1249b39c5158Smillert    use DB_File ;
1250b39c5158Smillert
1251b39c5158Smillert    my ($filename, $x, %h, $found) ;
1252b39c5158Smillert
1253b39c5158Smillert    $filename = "tree" ;
1254b39c5158Smillert
1255b39c5158Smillert    # Enable duplicate records
1256b39c5158Smillert    $DB_BTREE->{'flags'} = R_DUP ;
1257b39c5158Smillert
1258b39c5158Smillert    $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE
1259b39c5158Smillert        or die "Cannot open $filename: $!\n";
1260b39c5158Smillert
1261b39c5158Smillert    $x->del_dup("Wall", "Larry") ;
1262b39c5158Smillert
1263b39c5158Smillert    $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ;
1264b39c5158Smillert    print "Larry Wall is $found there\n" ;
1265b39c5158Smillert
1266b39c5158Smillert    undef $x ;
1267b39c5158Smillert    untie %h ;
1268b39c5158Smillert
1269b39c5158Smillertprints this
1270b39c5158Smillert
1271b39c5158Smillert    Larry Wall is not there
1272b39c5158Smillert
1273b39c5158Smillert=head2 Matching Partial Keys
1274b39c5158Smillert
1275b39c5158SmillertThe BTREE interface has a feature which allows partial keys to be
1276b39c5158Smillertmatched. This functionality is I<only> available when the C<seq> method
1277b39c5158Smillertis used along with the R_CURSOR flag.
1278b39c5158Smillert
1279b39c5158Smillert    $x->seq($key, $value, R_CURSOR) ;
1280b39c5158Smillert
1281b39c5158SmillertHere is the relevant quote from the dbopen man page where it defines
1282b39c5158Smillertthe use of the R_CURSOR flag with seq:
1283b39c5158Smillert
1284b39c5158Smillert    Note, for the DB_BTREE access method, the returned key is not
1285b39c5158Smillert    necessarily an exact match for the specified key. The returned key
1286b39c5158Smillert    is the smallest key greater than or equal to the specified key,
1287b39c5158Smillert    permitting partial key matches and range searches.
1288b39c5158Smillert
1289b39c5158SmillertIn the example script below, the C<match> sub uses this feature to find
1290b39c5158Smillertand print the first matching key/value pair given a partial key.
1291b39c5158Smillert
1292b39c5158Smillert    use warnings ;
1293b39c5158Smillert    use strict ;
1294b39c5158Smillert    use DB_File ;
1295b39c5158Smillert    use Fcntl ;
1296b39c5158Smillert
1297b39c5158Smillert    my ($filename, $x, %h, $st, $key, $value) ;
1298b39c5158Smillert
1299b39c5158Smillert    sub match
1300b39c5158Smillert    {
1301b39c5158Smillert        my $key = shift ;
1302b39c5158Smillert        my $value = 0;
1303b39c5158Smillert        my $orig_key = $key ;
1304b39c5158Smillert        $x->seq($key, $value, R_CURSOR) ;
1305b39c5158Smillert        print "$orig_key\t-> $key\t-> $value\n" ;
1306b39c5158Smillert    }
1307b39c5158Smillert
1308b39c5158Smillert    $filename = "tree" ;
1309b39c5158Smillert    unlink $filename ;
1310b39c5158Smillert
1311b39c5158Smillert    $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE
1312b39c5158Smillert        or die "Cannot open $filename: $!\n";
1313b39c5158Smillert
1314b39c5158Smillert    # Add some key/value pairs to the file
1315b39c5158Smillert    $h{'mouse'} = 'mickey' ;
1316b39c5158Smillert    $h{'Wall'} = 'Larry' ;
1317b39c5158Smillert    $h{'Walls'} = 'Brick' ;
1318b39c5158Smillert    $h{'Smith'} = 'John' ;
1319b39c5158Smillert
1320b39c5158Smillert
1321b39c5158Smillert    $key = $value = 0 ;
1322b39c5158Smillert    print "IN ORDER\n" ;
1323b39c5158Smillert    for ($st = $x->seq($key, $value, R_FIRST) ;
1324b39c5158Smillert         $st == 0 ;
1325b39c5158Smillert         $st = $x->seq($key, $value, R_NEXT) )
1326b39c5158Smillert
1327b39c5158Smillert      {  print "$key    -> $value\n" }
1328b39c5158Smillert
1329b39c5158Smillert    print "\nPARTIAL MATCH\n" ;
1330b39c5158Smillert
1331b39c5158Smillert    match "Wa" ;
1332b39c5158Smillert    match "A" ;
1333b39c5158Smillert    match "a" ;
1334b39c5158Smillert
1335b39c5158Smillert    undef $x ;
1336b39c5158Smillert    untie %h ;
1337b39c5158Smillert
1338b39c5158SmillertHere is the output:
1339b39c5158Smillert
1340b39c5158Smillert    IN ORDER
1341b39c5158Smillert    Smith -> John
1342b39c5158Smillert    Wall  -> Larry
1343b39c5158Smillert    Walls -> Brick
1344b39c5158Smillert    mouse -> mickey
1345b39c5158Smillert
1346b39c5158Smillert    PARTIAL MATCH
1347b39c5158Smillert    Wa -> Wall  -> Larry
1348b39c5158Smillert    A  -> Smith -> John
1349b39c5158Smillert    a  -> mouse -> mickey
1350b39c5158Smillert
1351b39c5158Smillert=head1 DB_RECNO
1352b39c5158Smillert
1353b39c5158SmillertDB_RECNO provides an interface to flat text files. Both variable and
1354b39c5158Smillertfixed length records are supported.
1355b39c5158Smillert
1356b39c5158SmillertIn order to make RECNO more compatible with Perl, the array offset for
1357b39c5158Smillertall RECNO arrays begins at 0 rather than 1 as in Berkeley DB.
1358b39c5158Smillert
1359b39c5158SmillertAs with normal Perl arrays, a RECNO array can be accessed using
1360b39c5158Smillertnegative indexes. The index -1 refers to the last element of the array,
1361b39c5158Smillert-2 the second last, and so on. Attempting to access an element before
1362b39c5158Smillertthe start of the array will raise a fatal run-time error.
1363b39c5158Smillert
1364b39c5158Smillert=head2 The 'bval' Option
1365b39c5158Smillert
1366b39c5158SmillertThe operation of the bval option warrants some discussion. Here is the
1367b39c5158Smillertdefinition of bval from the Berkeley DB 1.85 recno manual page:
1368b39c5158Smillert
1369b39c5158Smillert    The delimiting byte to be used to mark  the  end  of  a
1370b39c5158Smillert    record for variable-length records, and the pad charac-
1371b39c5158Smillert    ter for fixed-length records.  If no  value  is  speci-
1372b39c5158Smillert    fied,  newlines  (``\n'')  are  used to mark the end of
1373b39c5158Smillert    variable-length records and  fixed-length  records  are
1374b39c5158Smillert    padded with spaces.
1375b39c5158Smillert
1376b39c5158SmillertThe second sentence is wrong. In actual fact bval will only default to
1377b39c5158SmillertC<"\n"> when the openinfo parameter in dbopen is NULL. If a non-NULL
1378b39c5158Smillertopeninfo parameter is used at all, the value that happens to be in bval
1379b39c5158Smillertwill be used. That means you always have to specify bval when making
1380b39c5158Smillertuse of any of the options in the openinfo parameter. This documentation
1381b39c5158Smillerterror will be fixed in the next release of Berkeley DB.
1382b39c5158Smillert
1383b39c5158SmillertThat clarifies the situation with regards Berkeley DB itself. What
1384b39c5158Smillertabout B<DB_File>? Well, the behavior defined in the quote above is
1385b39c5158Smillertquite useful, so B<DB_File> conforms to it.
1386b39c5158Smillert
1387b39c5158SmillertThat means that you can specify other options (e.g. cachesize) and
1388b39c5158Smillertstill have bval default to C<"\n"> for variable length records, and
1389b39c5158Smillertspace for fixed length records.
1390b39c5158Smillert
1391b39c5158SmillertAlso note that the bval option only allows you to specify a single byte
1392b39c5158Smillertas a delimiter.
1393b39c5158Smillert
1394b39c5158Smillert=head2 A Simple Example
1395b39c5158Smillert
1396b39c5158SmillertHere is a simple example that uses RECNO (if you are using a version
1397b39c5158Smillertof Perl earlier than 5.004_57 this example won't work -- see
1398b39c5158SmillertL<Extra RECNO Methods> for a workaround).
1399b39c5158Smillert
1400b39c5158Smillert    use warnings ;
1401b39c5158Smillert    use strict ;
1402b39c5158Smillert    use DB_File ;
1403b39c5158Smillert
1404b39c5158Smillert    my $filename = "text" ;
1405b39c5158Smillert    unlink $filename ;
1406b39c5158Smillert
1407b39c5158Smillert    my @h ;
1408b39c5158Smillert    tie @h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_RECNO
1409b39c5158Smillert        or die "Cannot open file 'text': $!\n" ;
1410b39c5158Smillert
1411b39c5158Smillert    # Add a few key/value pairs to the file
1412b39c5158Smillert    $h[0] = "orange" ;
1413b39c5158Smillert    $h[1] = "blue" ;
1414b39c5158Smillert    $h[2] = "yellow" ;
1415b39c5158Smillert
1416b39c5158Smillert    push @h, "green", "black" ;
1417b39c5158Smillert
1418b39c5158Smillert    my $elements = scalar @h ;
1419b39c5158Smillert    print "The array contains $elements entries\n" ;
1420b39c5158Smillert
1421b39c5158Smillert    my $last = pop @h ;
1422b39c5158Smillert    print "popped $last\n" ;
1423b39c5158Smillert
1424b39c5158Smillert    unshift @h, "white" ;
1425b39c5158Smillert    my $first = shift @h ;
1426b39c5158Smillert    print "shifted $first\n" ;
1427b39c5158Smillert
1428b39c5158Smillert    # Check for existence of a key
1429b39c5158Smillert    print "Element 1 Exists with value $h[1]\n" if $h[1] ;
1430b39c5158Smillert
1431b39c5158Smillert    # use a negative index
1432b39c5158Smillert    print "The last element is $h[-1]\n" ;
1433b39c5158Smillert    print "The 2nd last element is $h[-2]\n" ;
1434b39c5158Smillert
1435b39c5158Smillert    untie @h ;
1436b39c5158Smillert
1437b39c5158SmillertHere is the output from the script:
1438b39c5158Smillert
1439b39c5158Smillert    The array contains 5 entries
1440b39c5158Smillert    popped black
1441b39c5158Smillert    shifted white
1442b39c5158Smillert    Element 1 Exists with value blue
1443b39c5158Smillert    The last element is green
1444b39c5158Smillert    The 2nd last element is yellow
1445b39c5158Smillert
1446b39c5158Smillert=head2 Extra RECNO Methods
1447b39c5158Smillert
1448b39c5158SmillertIf you are using a version of Perl earlier than 5.004_57, the tied
1449b39c5158Smillertarray interface is quite limited. In the example script above
1450b39c5158SmillertC<push>, C<pop>, C<shift>, C<unshift>
1451b39c5158Smillertor determining the array length will not work with a tied array.
1452b39c5158Smillert
1453b39c5158SmillertTo make the interface more useful for older versions of Perl, a number
1454b39c5158Smillertof methods are supplied with B<DB_File> to simulate the missing array
1455b39c5158Smillertoperations. All these methods are accessed via the object returned from
1456b39c5158Smillertthe tie call.
1457b39c5158Smillert
1458b39c5158SmillertHere are the methods:
1459b39c5158Smillert
1460b39c5158Smillert=over 5
1461b39c5158Smillert
1462b39c5158Smillert=item B<$X-E<gt>push(list) ;>
1463b39c5158Smillert
1464b39c5158SmillertPushes the elements of C<list> to the end of the array.
1465b39c5158Smillert
1466b39c5158Smillert=item B<$value = $X-E<gt>pop ;>
1467b39c5158Smillert
1468b39c5158SmillertRemoves and returns the last element of the array.
1469b39c5158Smillert
1470b39c5158Smillert=item B<$X-E<gt>shift>
1471b39c5158Smillert
1472b39c5158SmillertRemoves and returns the first element of the array.
1473b39c5158Smillert
1474b39c5158Smillert=item B<$X-E<gt>unshift(list) ;>
1475b39c5158Smillert
1476b39c5158SmillertPushes the elements of C<list> to the start of the array.
1477b39c5158Smillert
1478b39c5158Smillert=item B<$X-E<gt>length>
1479b39c5158Smillert
1480b39c5158SmillertReturns the number of elements in the array.
1481b39c5158Smillert
1482b39c5158Smillert=item B<$X-E<gt>splice(offset, length, elements);>
1483b39c5158Smillert
1484b39c5158SmillertReturns a splice of the array.
1485b39c5158Smillert
1486b39c5158Smillert=back
1487b39c5158Smillert
1488b39c5158Smillert=head2 Another Example
1489b39c5158Smillert
1490b39c5158SmillertHere is a more complete example that makes use of some of the methods
1491b39c5158Smillertdescribed above. It also makes use of the API interface directly (see
1492b39c5158SmillertL<THE API INTERFACE>).
1493b39c5158Smillert
1494b39c5158Smillert    use warnings ;
1495b39c5158Smillert    use strict ;
1496b39c5158Smillert    my (@h, $H, $file, $i) ;
1497b39c5158Smillert    use DB_File ;
1498b39c5158Smillert    use Fcntl ;
1499b39c5158Smillert
1500b39c5158Smillert    $file = "text" ;
1501b39c5158Smillert
1502b39c5158Smillert    unlink $file ;
1503b39c5158Smillert
1504b39c5158Smillert    $H = tie @h, "DB_File", $file, O_RDWR|O_CREAT, 0666, $DB_RECNO
1505b39c5158Smillert        or die "Cannot open file $file: $!\n" ;
1506b39c5158Smillert
1507b39c5158Smillert    # first create a text file to play with
1508b39c5158Smillert    $h[0] = "zero" ;
1509b39c5158Smillert    $h[1] = "one" ;
1510b39c5158Smillert    $h[2] = "two" ;
1511b39c5158Smillert    $h[3] = "three" ;
1512b39c5158Smillert    $h[4] = "four" ;
1513b39c5158Smillert
1514b39c5158Smillert
1515b39c5158Smillert    # Print the records in order.
1516b39c5158Smillert    #
1517b39c5158Smillert    # The length method is needed here because evaluating a tied
1518b39c5158Smillert    # array in a scalar context does not return the number of
1519b39c5158Smillert    # elements in the array.
1520b39c5158Smillert
1521b39c5158Smillert    print "\nORIGINAL\n" ;
1522b39c5158Smillert    foreach $i (0 .. $H->length - 1) {
1523b39c5158Smillert        print "$i: $h[$i]\n" ;
1524b39c5158Smillert    }
1525b39c5158Smillert
1526b39c5158Smillert    # use the push & pop methods
1527b39c5158Smillert    $a = $H->pop ;
1528b39c5158Smillert    $H->push("last") ;
1529b39c5158Smillert    print "\nThe last record was [$a]\n" ;
1530b39c5158Smillert
1531b39c5158Smillert    # and the shift & unshift methods
1532b39c5158Smillert    $a = $H->shift ;
1533b39c5158Smillert    $H->unshift("first") ;
1534b39c5158Smillert    print "The first record was [$a]\n" ;
1535b39c5158Smillert
1536b39c5158Smillert    # Use the API to add a new record after record 2.
1537b39c5158Smillert    $i = 2 ;
1538b39c5158Smillert    $H->put($i, "Newbie", R_IAFTER) ;
1539b39c5158Smillert
1540b39c5158Smillert    # and a new record before record 1.
1541b39c5158Smillert    $i = 1 ;
1542b39c5158Smillert    $H->put($i, "New One", R_IBEFORE) ;
1543b39c5158Smillert
1544b39c5158Smillert    # delete record 3
1545b39c5158Smillert    $H->del(3) ;
1546b39c5158Smillert
1547b39c5158Smillert    # now print the records in reverse order
1548b39c5158Smillert    print "\nREVERSE\n" ;
1549b39c5158Smillert    for ($i = $H->length - 1 ; $i >= 0 ; -- $i)
1550b39c5158Smillert      { print "$i: $h[$i]\n" }
1551b39c5158Smillert
1552b39c5158Smillert    # same again, but use the API functions instead
1553b39c5158Smillert    print "\nREVERSE again\n" ;
1554b39c5158Smillert    my ($s, $k, $v)  = (0, 0, 0) ;
1555b39c5158Smillert    for ($s = $H->seq($k, $v, R_LAST) ;
1556b39c5158Smillert             $s == 0 ;
1557b39c5158Smillert             $s = $H->seq($k, $v, R_PREV))
1558b39c5158Smillert      { print "$k: $v\n" }
1559b39c5158Smillert
1560b39c5158Smillert    undef $H ;
1561b39c5158Smillert    untie @h ;
1562b39c5158Smillert
1563b39c5158Smillertand this is what it outputs:
1564b39c5158Smillert
1565b39c5158Smillert    ORIGINAL
1566b39c5158Smillert    0: zero
1567b39c5158Smillert    1: one
1568b39c5158Smillert    2: two
1569b39c5158Smillert    3: three
1570b39c5158Smillert    4: four
1571b39c5158Smillert
1572b39c5158Smillert    The last record was [four]
1573b39c5158Smillert    The first record was [zero]
1574b39c5158Smillert
1575b39c5158Smillert    REVERSE
1576b39c5158Smillert    5: last
1577b39c5158Smillert    4: three
1578b39c5158Smillert    3: Newbie
1579b39c5158Smillert    2: one
1580b39c5158Smillert    1: New One
1581b39c5158Smillert    0: first
1582b39c5158Smillert
1583b39c5158Smillert    REVERSE again
1584b39c5158Smillert    5: last
1585b39c5158Smillert    4: three
1586b39c5158Smillert    3: Newbie
1587b39c5158Smillert    2: one
1588b39c5158Smillert    1: New One
1589b39c5158Smillert    0: first
1590b39c5158Smillert
1591b39c5158SmillertNotes:
1592b39c5158Smillert
1593b39c5158Smillert=over 5
1594b39c5158Smillert
1595b39c5158Smillert=item 1.
1596b39c5158Smillert
1597b39c5158SmillertRather than iterating through the array, C<@h> like this:
1598b39c5158Smillert
1599b39c5158Smillert    foreach $i (@h)
1600b39c5158Smillert
1601b39c5158Smillertit is necessary to use either this:
1602b39c5158Smillert
1603b39c5158Smillert    foreach $i (0 .. $H->length - 1)
1604b39c5158Smillert
1605b39c5158Smillertor this:
1606b39c5158Smillert
1607b39c5158Smillert    for ($a = $H->get($k, $v, R_FIRST) ;
1608b39c5158Smillert         $a == 0 ;
1609b39c5158Smillert         $a = $H->get($k, $v, R_NEXT) )
1610b39c5158Smillert
1611b39c5158Smillert=item 2.
1612b39c5158Smillert
1613b39c5158SmillertNotice that both times the C<put> method was used the record index was
1614b39c5158Smillertspecified using a variable, C<$i>, rather than the literal value
1615b39c5158Smillertitself. This is because C<put> will return the record number of the
1616b39c5158Smillertinserted line via that parameter.
1617b39c5158Smillert
1618b39c5158Smillert=back
1619b39c5158Smillert
1620b39c5158Smillert=head1 THE API INTERFACE
1621b39c5158Smillert
1622b39c5158SmillertAs well as accessing Berkeley DB using a tied hash or array, it is also
1623b39c5158Smillertpossible to make direct use of most of the API functions defined in the
1624b39c5158SmillertBerkeley DB documentation.
1625b39c5158Smillert
1626b39c5158SmillertTo do this you need to store a copy of the object returned from the tie.
1627b39c5158Smillert
1628b39c5158Smillert        $db = tie %hash, "DB_File", "filename" ;
1629b39c5158Smillert
1630b39c5158SmillertOnce you have done that, you can access the Berkeley DB API functions
1631b39c5158Smillertas B<DB_File> methods directly like this:
1632b39c5158Smillert
1633b39c5158Smillert        $db->put($key, $value, R_NOOVERWRITE) ;
1634b39c5158Smillert
1635b39c5158SmillertB<Important:> If you have saved a copy of the object returned from
1636b39c5158SmillertC<tie>, the underlying database file will I<not> be closed until both
1637b39c5158Smillertthe tied variable is untied and all copies of the saved object are
1638b39c5158Smillertdestroyed.
1639b39c5158Smillert
1640b39c5158Smillert    use DB_File ;
1641b39c5158Smillert    $db = tie %hash, "DB_File", "filename"
1642b39c5158Smillert        or die "Cannot tie filename: $!" ;
1643b39c5158Smillert    ...
1644b39c5158Smillert    undef $db ;
1645b39c5158Smillert    untie %hash ;
1646b39c5158Smillert
1647b39c5158SmillertSee L<The untie() Gotcha> for more details.
1648b39c5158Smillert
1649b39c5158SmillertAll the functions defined in L<dbopen> are available except for
1650b39c5158Smillertclose() and dbopen() itself. The B<DB_File> method interface to the
1651b39c5158Smillertsupported functions have been implemented to mirror the way Berkeley DB
1652b39c5158Smillertworks whenever possible. In particular note that:
1653b39c5158Smillert
1654b39c5158Smillert=over 5
1655b39c5158Smillert
1656b39c5158Smillert=item *
1657b39c5158Smillert
1658b39c5158SmillertThe methods return a status value. All return 0 on success.
1659b39c5158SmillertAll return -1 to signify an error and set C<$!> to the exact
1660b39c5158Smillerterror code. The return code 1 generally (but not always) means that the
1661b39c5158Smillertkey specified did not exist in the database.
1662b39c5158Smillert
1663b39c5158SmillertOther return codes are defined. See below and in the Berkeley DB
1664b39c5158Smillertdocumentation for details. The Berkeley DB documentation should be used
1665b39c5158Smillertas the definitive source.
1666b39c5158Smillert
1667b39c5158Smillert=item *
1668b39c5158Smillert
1669b39c5158SmillertWhenever a Berkeley DB function returns data via one of its parameters,
1670b39c5158Smillertthe equivalent B<DB_File> method does exactly the same.
1671b39c5158Smillert
1672b39c5158Smillert=item *
1673b39c5158Smillert
1674b39c5158SmillertIf you are careful, it is possible to mix API calls with the tied
1675b39c5158Smillerthash/array interface in the same piece of code. Although only a few of
1676b39c5158Smillertthe methods used to implement the tied interface currently make use of
1677b39c5158Smillertthe cursor, you should always assume that the cursor has been changed
1678b39c5158Smillertany time the tied hash/array interface is used. As an example, this
1679b39c5158Smillertcode will probably not do what you expect:
1680b39c5158Smillert
1681b39c5158Smillert    $X = tie %x, 'DB_File', $filename, O_RDWR|O_CREAT, 0777, $DB_BTREE
1682b39c5158Smillert        or die "Cannot tie $filename: $!" ;
1683b39c5158Smillert
1684b39c5158Smillert    # Get the first key/value pair and set  the cursor
1685b39c5158Smillert    $X->seq($key, $value, R_FIRST) ;
1686b39c5158Smillert
1687b39c5158Smillert    # this line will modify the cursor
1688b39c5158Smillert    $count = scalar keys %x ;
1689b39c5158Smillert
1690b39c5158Smillert    # Get the second key/value pair.
1691b39c5158Smillert    # oops, it didn't, it got the last key/value pair!
1692b39c5158Smillert    $X->seq($key, $value, R_NEXT) ;
1693b39c5158Smillert
1694b39c5158SmillertThe code above can be rearranged to get around the problem, like this:
1695b39c5158Smillert
1696b39c5158Smillert    $X = tie %x, 'DB_File', $filename, O_RDWR|O_CREAT, 0777, $DB_BTREE
1697b39c5158Smillert        or die "Cannot tie $filename: $!" ;
1698b39c5158Smillert
1699b39c5158Smillert    # this line will modify the cursor
1700b39c5158Smillert    $count = scalar keys %x ;
1701b39c5158Smillert
1702b39c5158Smillert    # Get the first key/value pair and set  the cursor
1703b39c5158Smillert    $X->seq($key, $value, R_FIRST) ;
1704b39c5158Smillert
1705b39c5158Smillert    # Get the second key/value pair.
1706b39c5158Smillert    # worked this time.
1707b39c5158Smillert    $X->seq($key, $value, R_NEXT) ;
1708b39c5158Smillert
1709b39c5158Smillert=back
1710b39c5158Smillert
1711b39c5158SmillertAll the constants defined in L<dbopen> for use in the flags parameters
1712b39c5158Smillertin the methods defined below are also available. Refer to the Berkeley
1713b39c5158SmillertDB documentation for the precise meaning of the flags values.
1714b39c5158Smillert
1715b39c5158SmillertBelow is a list of the methods available.
1716b39c5158Smillert
1717b39c5158Smillert=over 5
1718b39c5158Smillert
1719b39c5158Smillert=item B<$status = $X-E<gt>get($key, $value [, $flags]) ;>
1720b39c5158Smillert
1721b39c5158SmillertGiven a key (C<$key>) this method reads the value associated with it
1722b39c5158Smillertfrom the database. The value read from the database is returned in the
1723b39c5158SmillertC<$value> parameter.
1724b39c5158Smillert
1725b39c5158SmillertIf the key does not exist the method returns 1.
1726b39c5158Smillert
1727b39c5158SmillertNo flags are currently defined for this method.
1728b39c5158Smillert
1729b39c5158Smillert=item B<$status = $X-E<gt>put($key, $value [, $flags]) ;>
1730b39c5158Smillert
1731b39c5158SmillertStores the key/value pair in the database.
1732b39c5158Smillert
1733b39c5158SmillertIf you use either the R_IAFTER or R_IBEFORE flags, the C<$key> parameter
1734b39c5158Smillertwill have the record number of the inserted key/value pair set.
1735b39c5158Smillert
1736b39c5158SmillertValid flags are R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE and
1737b39c5158SmillertR_SETCURSOR.
1738b39c5158Smillert
1739b39c5158Smillert=item B<$status = $X-E<gt>del($key [, $flags]) ;>
1740b39c5158Smillert
1741b39c5158SmillertRemoves all key/value pairs with key C<$key> from the database.
1742b39c5158Smillert
1743b39c5158SmillertA return code of 1 means that the requested key was not in the
1744b39c5158Smillertdatabase.
1745b39c5158Smillert
1746b39c5158SmillertR_CURSOR is the only valid flag at present.
1747b39c5158Smillert
1748b39c5158Smillert=item B<$status = $X-E<gt>fd ;>
1749b39c5158Smillert
1750b39c5158SmillertReturns the file descriptor for the underlying database.
1751b39c5158Smillert
1752b39c5158SmillertSee L<Locking: The Trouble with fd> for an explanation for why you should
1753b39c5158Smillertnot use C<fd> to lock your database.
1754b39c5158Smillert
1755b39c5158Smillert=item B<$status = $X-E<gt>seq($key, $value, $flags) ;>
1756b39c5158Smillert
1757b39c5158SmillertThis interface allows sequential retrieval from the database. See
1758b39c5158SmillertL<dbopen> for full details.
1759b39c5158Smillert
1760b39c5158SmillertBoth the C<$key> and C<$value> parameters will be set to the key/value
1761b39c5158Smillertpair read from the database.
1762b39c5158Smillert
1763b39c5158SmillertThe flags parameter is mandatory. The valid flag values are R_CURSOR,
1764b39c5158SmillertR_FIRST, R_LAST, R_NEXT and R_PREV.
1765b39c5158Smillert
1766b39c5158Smillert=item B<$status = $X-E<gt>sync([$flags]) ;>
1767b39c5158Smillert
1768b39c5158SmillertFlushes any cached buffers to disk.
1769b39c5158Smillert
1770b39c5158SmillertR_RECNOSYNC is the only valid flag at present.
1771b39c5158Smillert
1772b39c5158Smillert=back
1773b39c5158Smillert
1774b39c5158Smillert=head1 DBM FILTERS
1775b39c5158Smillert
17769f11ffb7Safresh1A DBM Filter is a piece of code that is be used when you I<always> want to
17779f11ffb7Safresh1make the same transformation to all keys and/or values in a DBM database.
17789f11ffb7Safresh1An example is when you need to encode your data in UTF-8 before writing to
17799f11ffb7Safresh1the database and then decode the UTF-8 when reading from the database file.
17809f11ffb7Safresh1
17819f11ffb7Safresh1There are two ways to use a DBM Filter.
17829f11ffb7Safresh1
17839f11ffb7Safresh1=over 5
17849f11ffb7Safresh1
17859f11ffb7Safresh1=item 1.
17869f11ffb7Safresh1
17879f11ffb7Safresh1Using the low-level API defined below.
17889f11ffb7Safresh1
17899f11ffb7Safresh1=item 2.
17909f11ffb7Safresh1
17919f11ffb7Safresh1Using the L<DBM_Filter> module.
17929f11ffb7Safresh1This module hides the complexity of the API defined below and comes
17939f11ffb7Safresh1with a number of "canned" filters that cover some of the common use-cases.
17949f11ffb7Safresh1
17959f11ffb7Safresh1=back
17969f11ffb7Safresh1
17979f11ffb7Safresh1Use of the L<DBM_Filter> module is recommended.
17989f11ffb7Safresh1
17999f11ffb7Safresh1=head2 DBM Filter Low-level API
1800b39c5158Smillert
1801b39c5158SmillertThere are four methods associated with DBM Filters. All work identically,
1802b39c5158Smillertand each is used to install (or uninstall) a single DBM Filter. Each
1803b39c5158Smillertexpects a single parameter, namely a reference to a sub. The only
1804b39c5158Smillertdifference between them is the place that the filter is installed.
1805b39c5158Smillert
1806b39c5158SmillertTo summarise:
1807b39c5158Smillert
1808b39c5158Smillert=over 5
1809b39c5158Smillert
1810b39c5158Smillert=item B<filter_store_key>
1811b39c5158Smillert
1812b39c5158SmillertIf a filter has been installed with this method, it will be invoked
1813b39c5158Smillertevery time you write a key to a DBM database.
1814b39c5158Smillert
1815b39c5158Smillert=item B<filter_store_value>
1816b39c5158Smillert
1817b39c5158SmillertIf a filter has been installed with this method, it will be invoked
1818b39c5158Smillertevery time you write a value to a DBM database.
1819b39c5158Smillert
1820b39c5158Smillert
1821b39c5158Smillert=item B<filter_fetch_key>
1822b39c5158Smillert
1823b39c5158SmillertIf a filter has been installed with this method, it will be invoked
1824b39c5158Smillertevery time you read a key from a DBM database.
1825b39c5158Smillert
1826b39c5158Smillert=item B<filter_fetch_value>
1827b39c5158Smillert
1828b39c5158SmillertIf a filter has been installed with this method, it will be invoked
1829b39c5158Smillertevery time you read a value from a DBM database.
1830b39c5158Smillert
1831b39c5158Smillert=back
1832b39c5158Smillert
1833b39c5158SmillertYou can use any combination of the methods, from none, to all four.
1834b39c5158Smillert
1835b39c5158SmillertAll filter methods return the existing filter, if present, or C<undef>
1836b39c5158Smillertin not.
1837b39c5158Smillert
1838b39c5158SmillertTo delete a filter pass C<undef> to it.
1839b39c5158Smillert
1840b39c5158Smillert=head2 The Filter
1841b39c5158Smillert
1842b39c5158SmillertWhen each filter is called by Perl, a local copy of C<$_> will contain
1843b39c5158Smillertthe key or value to be filtered. Filtering is achieved by modifying
1844b39c5158Smillertthe contents of C<$_>. The return code from the filter is ignored.
1845b39c5158Smillert
1846b39c5158Smillert=head2 An Example -- the NULL termination problem.
1847b39c5158Smillert
1848b39c5158SmillertConsider the following scenario. You have a DBM database
1849b39c5158Smillertthat you need to share with a third-party C application. The C application
1850b39c5158Smillertassumes that I<all> keys and values are NULL terminated. Unfortunately
1851b39c5158Smillertwhen Perl writes to DBM databases it doesn't use NULL termination, so
1852b39c5158Smillertyour Perl application will have to manage NULL termination itself. When
1853b39c5158Smillertyou write to the database you will have to use something like this:
1854b39c5158Smillert
1855b39c5158Smillert    $hash{"$key\0"} = "$value\0" ;
1856b39c5158Smillert
1857b39c5158SmillertSimilarly the NULL needs to be taken into account when you are considering
1858b39c5158Smillertthe length of existing keys/values.
1859b39c5158Smillert
1860b39c5158SmillertIt would be much better if you could ignore the NULL terminations issue
1861b39c5158Smillertin the main application code and have a mechanism that automatically
1862b39c5158Smillertadded the terminating NULL to all keys and values whenever you write to
1863b39c5158Smillertthe database and have them removed when you read from the database. As I'm
1864b39c5158Smillertsure you have already guessed, this is a problem that DBM Filters can
1865b39c5158Smillertfix very easily.
1866b39c5158Smillert
1867b39c5158Smillert    use warnings ;
1868b39c5158Smillert    use strict ;
1869b39c5158Smillert    use DB_File ;
1870b39c5158Smillert
1871b39c5158Smillert    my %hash ;
1872b39c5158Smillert    my $filename = "filt" ;
1873b39c5158Smillert    unlink $filename ;
1874b39c5158Smillert
1875b39c5158Smillert    my $db = tie %hash, 'DB_File', $filename, O_CREAT|O_RDWR, 0666, $DB_HASH
1876b39c5158Smillert      or die "Cannot open $filename: $!\n" ;
1877b39c5158Smillert
1878b39c5158Smillert    # Install DBM Filters
1879b39c5158Smillert    $db->filter_fetch_key  ( sub { s/\0$//    } ) ;
1880b39c5158Smillert    $db->filter_store_key  ( sub { $_ .= "\0" } ) ;
1881b39c5158Smillert    $db->filter_fetch_value( sub { s/\0$//    } ) ;
1882b39c5158Smillert    $db->filter_store_value( sub { $_ .= "\0" } ) ;
1883b39c5158Smillert
1884b39c5158Smillert    $hash{"abc"} = "def" ;
1885b39c5158Smillert    my $a = $hash{"ABC"} ;
1886b39c5158Smillert    # ...
1887b39c5158Smillert    undef $db ;
1888b39c5158Smillert    untie %hash ;
1889b39c5158Smillert
1890b39c5158SmillertHopefully the contents of each of the filters should be
1891b39c5158Smillertself-explanatory. Both "fetch" filters remove the terminating NULL,
1892b39c5158Smillertand both "store" filters add a terminating NULL.
1893b39c5158Smillert
1894b39c5158Smillert
1895b39c5158Smillert=head2 Another Example -- Key is a C int.
1896b39c5158Smillert
1897b39c5158SmillertHere is another real-life example. By default, whenever Perl writes to
1898b39c5158Smillerta DBM database it always writes the key and value as strings. So when
1899b39c5158Smillertyou use this:
1900b39c5158Smillert
1901b39c5158Smillert    $hash{12345} = "something" ;
1902b39c5158Smillert
1903b39c5158Smillertthe key 12345 will get stored in the DBM database as the 5 byte string
1904b39c5158Smillert"12345". If you actually want the key to be stored in the DBM database
1905b39c5158Smillertas a C int, you will have to use C<pack> when writing, and C<unpack>
1906b39c5158Smillertwhen reading.
1907b39c5158Smillert
1908b39c5158SmillertHere is a DBM Filter that does it:
1909b39c5158Smillert
1910b39c5158Smillert    use warnings ;
1911b39c5158Smillert    use strict ;
1912b39c5158Smillert    use DB_File ;
1913b39c5158Smillert    my %hash ;
1914b39c5158Smillert    my $filename = "filt" ;
1915b39c5158Smillert    unlink $filename ;
1916b39c5158Smillert
1917b39c5158Smillert
1918b39c5158Smillert    my $db = tie %hash, 'DB_File', $filename, O_CREAT|O_RDWR, 0666, $DB_HASH
1919b39c5158Smillert      or die "Cannot open $filename: $!\n" ;
1920b39c5158Smillert
1921b39c5158Smillert    $db->filter_fetch_key  ( sub { $_ = unpack("i", $_) } ) ;
1922b39c5158Smillert    $db->filter_store_key  ( sub { $_ = pack ("i", $_) } ) ;
1923b39c5158Smillert    $hash{123} = "def" ;
1924b39c5158Smillert    # ...
1925b39c5158Smillert    undef $db ;
1926b39c5158Smillert    untie %hash ;
1927b39c5158Smillert
1928b39c5158SmillertThis time only two filters have been used -- we only need to manipulate
1929b39c5158Smillertthe contents of the key, so it wasn't necessary to install any value
1930b39c5158Smillertfilters.
1931b39c5158Smillert
1932b39c5158Smillert=head1 HINTS AND TIPS
1933b39c5158Smillert
1934b39c5158Smillert
1935b39c5158Smillert=head2 Locking: The Trouble with fd
1936b39c5158Smillert
1937b39c5158SmillertUntil version 1.72 of this module, the recommended technique for locking
1938b39c5158SmillertB<DB_File> databases was to flock the filehandle returned from the "fd"
1939b39c5158Smillertfunction. Unfortunately this technique has been shown to be fundamentally
1940b39c5158Smillertflawed (Kudos to David Harris for tracking this down). Use it at your own
1941b39c5158Smillertperil!
1942b39c5158Smillert
1943b39c5158SmillertThe locking technique went like this.
1944b39c5158Smillert
1945b39c5158Smillert    $db = tie(%db, 'DB_File', 'foo.db', O_CREAT|O_RDWR, 0644)
1946b39c5158Smillert        || die "dbcreat foo.db $!";
1947b39c5158Smillert    $fd = $db->fd;
1948b39c5158Smillert    open(DB_FH, "+<&=$fd") || die "dup $!";
1949b39c5158Smillert    flock (DB_FH, LOCK_EX) || die "flock: $!";
1950b39c5158Smillert    ...
1951b39c5158Smillert    $db{"Tom"} = "Jerry" ;
1952b39c5158Smillert    ...
1953b39c5158Smillert    flock(DB_FH, LOCK_UN);
1954b39c5158Smillert    undef $db;
1955b39c5158Smillert    untie %db;
1956b39c5158Smillert    close(DB_FH);
1957b39c5158Smillert
1958b39c5158SmillertIn simple terms, this is what happens:
1959b39c5158Smillert
1960b39c5158Smillert=over 5
1961b39c5158Smillert
1962b39c5158Smillert=item 1.
1963b39c5158Smillert
1964b39c5158SmillertUse "tie" to open the database.
1965b39c5158Smillert
1966b39c5158Smillert=item 2.
1967b39c5158Smillert
1968b39c5158SmillertLock the database with fd & flock.
1969b39c5158Smillert
1970b39c5158Smillert=item 3.
1971b39c5158Smillert
1972b39c5158SmillertRead & Write to the database.
1973b39c5158Smillert
1974b39c5158Smillert=item 4.
1975b39c5158Smillert
1976b39c5158SmillertUnlock and close the database.
1977b39c5158Smillert
1978b39c5158Smillert=back
1979b39c5158Smillert
1980b39c5158SmillertHere is the crux of the problem. A side-effect of opening the B<DB_File>
1981b39c5158Smillertdatabase in step 2 is that an initial block from the database will get
1982b39c5158Smillertread from disk and cached in memory.
1983b39c5158Smillert
1984b39c5158SmillertTo see why this is a problem, consider what can happen when two processes,
1985b39c5158Smillertsay "A" and "B", both want to update the same B<DB_File> database
1986b39c5158Smillertusing the locking steps outlined above. Assume process "A" has already
1987b39c5158Smillertopened the database and has a write lock, but it hasn't actually updated
1988b39c5158Smillertthe database yet (it has finished step 2, but not started step 3 yet). Now
1989b39c5158Smillertprocess "B" tries to open the same database - step 1 will succeed,
1990b39c5158Smillertbut it will block on step 2 until process "A" releases the lock. The
1991b39c5158Smillertimportant thing to notice here is that at this point in time both
1992b39c5158Smillertprocesses will have cached identical initial blocks from the database.
1993b39c5158Smillert
1994b39c5158SmillertNow process "A" updates the database and happens to change some of the
1995b39c5158Smillertdata held in the initial buffer. Process "A" terminates, flushing
1996b39c5158Smillertall cached data to disk and releasing the database lock. At this point
1997b39c5158Smillertthe database on disk will correctly reflect the changes made by process
1998b39c5158Smillert"A".
1999b39c5158Smillert
2000b39c5158SmillertWith the lock released, process "B" can now continue. It also updates the
2001b39c5158Smillertdatabase and unfortunately it too modifies the data that was in its
2002b39c5158Smillertinitial buffer. Once that data gets flushed to disk it will overwrite
2003b39c5158Smillertsome/all of the changes process "A" made to the database.
2004b39c5158Smillert
2005b39c5158SmillertThe result of this scenario is at best a database that doesn't contain
2006b39c5158Smillertwhat you expect. At worst the database will corrupt.
2007b39c5158Smillert
2008b39c5158SmillertThe above won't happen every time competing process update the same
2009b39c5158SmillertB<DB_File> database, but it does illustrate why the technique should
2010b39c5158Smillertnot be used.
2011b39c5158Smillert
2012b39c5158Smillert=head2 Safe ways to lock a database
2013b39c5158Smillert
2014b39c5158SmillertStarting with version 2.x, Berkeley DB  has internal support for locking.
201556d68f1eSafresh1The companion module to this one, L<BerkeleyDB|https://metacpan.org/pod/BerkeleyDB>, provides an interface
2016b39c5158Smillertto this locking functionality. If you are serious about locking
201756d68f1eSafresh1Berkeley DB databases, I strongly recommend using L<BerkeleyDB|https://metacpan.org/pod/BerkeleyDB>.
2018b39c5158Smillert
201956d68f1eSafresh1If using L<BerkeleyDB|https://metacpan.org/pod/BerkeleyDB> isn't an option, there are a number of modules
2020b39c5158Smillertavailable on CPAN that can be used to implement locking. Each one
2021b39c5158Smillertimplements locking differently and has different goals in mind. It is
2022b39c5158Smillerttherefore worth knowing the difference, so that you can pick the right
2023b39c5158Smillertone for your application. Here are the three locking wrappers:
2024b39c5158Smillert
2025b39c5158Smillert=over 5
2026b39c5158Smillert
2027b39c5158Smillert=item B<Tie::DB_Lock>
2028b39c5158Smillert
2029b39c5158SmillertA B<DB_File> wrapper which creates copies of the database file for
2030b39c5158Smillertread access, so that you have a kind of a multiversioning concurrent read
2031b39c5158Smillertsystem. However, updates are still serial. Use for databases where reads
2032b39c5158Smillertmay be lengthy and consistency problems may occur.
2033b39c5158Smillert
2034b39c5158Smillert=item B<Tie::DB_LockFile>
2035b39c5158Smillert
2036b39c5158SmillertA B<DB_File> wrapper that has the ability to lock and unlock the database
2037b39c5158Smillertwhile it is being used. Avoids the tie-before-flock problem by simply
2038b39c5158Smillertre-tie-ing the database when you get or drop a lock.  Because of the
2039b39c5158Smillertflexibility in dropping and re-acquiring the lock in the middle of a
2040b39c5158Smillertsession, this can be massaged into a system that will work with long
2041b39c5158Smillertupdates and/or reads if the application follows the hints in the POD
2042b39c5158Smillertdocumentation.
2043b39c5158Smillert
2044b39c5158Smillert=item B<DB_File::Lock>
2045b39c5158Smillert
2046b39c5158SmillertAn extremely lightweight B<DB_File> wrapper that simply flocks a lockfile
2047b39c5158Smillertbefore tie-ing the database and drops the lock after the untie. Allows
2048b39c5158Smillertone to use the same lockfile for multiple databases to avoid deadlock
2049b39c5158Smillertproblems, if desired. Use for databases where updates are reads are
2050b39c5158Smillertquick and simple flock locking semantics are enough.
2051b39c5158Smillert
2052b39c5158Smillert=back
2053b39c5158Smillert
2054b39c5158Smillert=head2 Sharing Databases With C Applications
2055b39c5158Smillert
2056b39c5158SmillertThere is no technical reason why a Berkeley DB database cannot be
2057b39c5158Smillertshared by both a Perl and a C application.
2058b39c5158Smillert
2059b39c5158SmillertThe vast majority of problems that are reported in this area boil down
2060b39c5158Smillertto the fact that C strings are NULL terminated, whilst Perl strings are
2061b39c5158Smillertnot. See L<DBM FILTERS> for a generic way to work around this problem.
2062b39c5158Smillert
2063b39c5158SmillertHere is a real example. Netscape 2.0 keeps a record of the locations you
2064b39c5158Smillertvisit along with the time you last visited them in a DB_HASH database.
2065b39c5158SmillertThis is usually stored in the file F<~/.netscape/history.db>. The key
2066b39c5158Smillertfield in the database is the location string and the value field is the
2067b39c5158Smillerttime the location was last visited stored as a 4 byte binary value.
2068b39c5158Smillert
2069b39c5158SmillertIf you haven't already guessed, the location string is stored with a
2070b39c5158Smillertterminating NULL. This means you need to be careful when accessing the
2071b39c5158Smillertdatabase.
2072b39c5158Smillert
2073b39c5158SmillertHere is a snippet of code that is loosely based on Tom Christiansen's
2074b39c5158SmillertI<ggh> script (available from your nearest CPAN archive in
2075b39c5158SmillertF<authors/id/TOMC/scripts/nshist.gz>).
2076b39c5158Smillert
2077b39c5158Smillert    use warnings ;
2078b39c5158Smillert    use strict ;
2079b39c5158Smillert    use DB_File ;
2080b39c5158Smillert    use Fcntl ;
2081b39c5158Smillert
2082b39c5158Smillert    my ($dotdir, $HISTORY, %hist_db, $href, $binary_time, $date) ;
2083b39c5158Smillert    $dotdir = $ENV{HOME} || $ENV{LOGNAME};
2084b39c5158Smillert
2085b39c5158Smillert    $HISTORY = "$dotdir/.netscape/history.db";
2086b39c5158Smillert
2087b39c5158Smillert    tie %hist_db, 'DB_File', $HISTORY
2088b39c5158Smillert        or die "Cannot open $HISTORY: $!\n" ;;
2089b39c5158Smillert
2090b39c5158Smillert    # Dump the complete database
2091b39c5158Smillert    while ( ($href, $binary_time) = each %hist_db ) {
2092b39c5158Smillert
2093b39c5158Smillert        # remove the terminating NULL
2094b39c5158Smillert        $href =~ s/\x00$// ;
2095b39c5158Smillert
2096b39c5158Smillert        # convert the binary time into a user friendly string
2097b39c5158Smillert        $date = localtime unpack("V", $binary_time);
2098b39c5158Smillert        print "$date $href\n" ;
2099b39c5158Smillert    }
2100b39c5158Smillert
2101b39c5158Smillert    # check for the existence of a specific key
2102b39c5158Smillert    # remember to add the NULL
2103b39c5158Smillert    if ( $binary_time = $hist_db{"http://mox.perl.com/\x00"} ) {
2104b39c5158Smillert        $date = localtime unpack("V", $binary_time) ;
2105b39c5158Smillert        print "Last visited mox.perl.com on $date\n" ;
2106b39c5158Smillert    }
2107b39c5158Smillert    else {
2108b39c5158Smillert        print "Never visited mox.perl.com\n"
2109b39c5158Smillert    }
2110b39c5158Smillert
2111b39c5158Smillert    untie %hist_db ;
2112b39c5158Smillert
2113b39c5158Smillert=head2 The untie() Gotcha
2114b39c5158Smillert
2115b39c5158SmillertIf you make use of the Berkeley DB API, it is I<very> strongly
2116b39c5158Smillertrecommended that you read L<perltie/The untie Gotcha>.
2117b39c5158Smillert
2118b39c5158SmillertEven if you don't currently make use of the API interface, it is still
2119b39c5158Smillertworth reading it.
2120b39c5158Smillert
2121b39c5158SmillertHere is an example which illustrates the problem from a B<DB_File>
2122b39c5158Smillertperspective:
2123b39c5158Smillert
2124b39c5158Smillert    use DB_File ;
2125b39c5158Smillert    use Fcntl ;
2126b39c5158Smillert
2127b39c5158Smillert    my %x ;
2128b39c5158Smillert    my $X ;
2129b39c5158Smillert
2130b39c5158Smillert    $X = tie %x, 'DB_File', 'tst.fil' , O_RDWR|O_TRUNC
2131b39c5158Smillert        or die "Cannot tie first time: $!" ;
2132b39c5158Smillert
2133b39c5158Smillert    $x{123} = 456 ;
2134b39c5158Smillert
2135b39c5158Smillert    untie %x ;
2136b39c5158Smillert
2137b39c5158Smillert    tie %x, 'DB_File', 'tst.fil' , O_RDWR|O_CREAT
2138b39c5158Smillert        or die "Cannot tie second time: $!" ;
2139b39c5158Smillert
2140b39c5158Smillert    untie %x ;
2141b39c5158Smillert
2142b39c5158SmillertWhen run, the script will produce this error message:
2143b39c5158Smillert
2144b39c5158Smillert    Cannot tie second time: Invalid argument at bad.file line 14.
2145b39c5158Smillert
2146b39c5158SmillertAlthough the error message above refers to the second tie() statement
2147b39c5158Smillertin the script, the source of the problem is really with the untie()
2148b39c5158Smillertstatement that precedes it.
2149b39c5158Smillert
2150b39c5158SmillertHaving read L<perltie> you will probably have already guessed that the
2151b39c5158Smillerterror is caused by the extra copy of the tied object stored in C<$X>.
2152b39c5158SmillertIf you haven't, then the problem boils down to the fact that the
2153b39c5158SmillertB<DB_File> destructor, DESTROY, will not be called until I<all>
2154b39c5158Smillertreferences to the tied object are destroyed. Both the tied variable,
2155b39c5158SmillertC<%x>, and C<$X> above hold a reference to the object. The call to
2156b39c5158Smillertuntie() will destroy the first, but C<$X> still holds a valid
2157b39c5158Smillertreference, so the destructor will not get called and the database file
2158b39c5158SmillertF<tst.fil> will remain open. The fact that Berkeley DB then reports the
2159b39c5158Smillertattempt to open a database that is already open via the catch-all
2160b39c5158Smillert"Invalid argument" doesn't help.
2161b39c5158Smillert
2162b39c5158SmillertIf you run the script with the C<-w> flag the error message becomes:
2163b39c5158Smillert
2164b39c5158Smillert    untie attempted while 1 inner references still exist at bad.file line 12.
2165b39c5158Smillert    Cannot tie second time: Invalid argument at bad.file line 14.
2166b39c5158Smillert
2167b39c5158Smillertwhich pinpoints the real problem. Finally the script can now be
2168b39c5158Smillertmodified to fix the original problem by destroying the API object
2169b39c5158Smillertbefore the untie:
2170b39c5158Smillert
2171b39c5158Smillert    ...
2172b39c5158Smillert    $x{123} = 456 ;
2173b39c5158Smillert
2174b39c5158Smillert    undef $X ;
2175b39c5158Smillert    untie %x ;
2176b39c5158Smillert
2177b39c5158Smillert    $X = tie %x, 'DB_File', 'tst.fil' , O_RDWR|O_CREAT
2178b39c5158Smillert    ...
2179b39c5158Smillert
2180b39c5158Smillert
2181b39c5158Smillert=head1 COMMON QUESTIONS
2182b39c5158Smillert
2183b39c5158Smillert=head2 Why is there Perl source in my database?
2184b39c5158Smillert
2185b39c5158SmillertIf you look at the contents of a database file created by DB_File,
2186b39c5158Smillertthere can sometimes be part of a Perl script included in it.
2187b39c5158Smillert
2188b39c5158SmillertThis happens because Berkeley DB uses dynamic memory to allocate
2189b39c5158Smillertbuffers which will subsequently be written to the database file. Being
2190b39c5158Smillertdynamic, the memory could have been used for anything before DB
2191b39c5158Smillertmalloced it. As Berkeley DB doesn't clear the memory once it has been
2192b39c5158Smillertallocated, the unused portions will contain random junk. In the case
2193b39c5158Smillertwhere a Perl script gets written to the database, the random junk will
2194b39c5158Smillertcorrespond to an area of dynamic memory that happened to be used during
2195b39c5158Smillertthe compilation of the script.
2196b39c5158Smillert
2197b39c5158SmillertUnless you don't like the possibility of there being part of your Perl
2198b39c5158Smillertscripts embedded in a database file, this is nothing to worry about.
2199b39c5158Smillert
2200b39c5158Smillert=head2 How do I store complex data structures with DB_File?
2201b39c5158Smillert
2202b39c5158SmillertAlthough B<DB_File> cannot do this directly, there is a module which
2203b39c5158Smillertcan layer transparently over B<DB_File> to accomplish this feat.
2204b39c5158Smillert
2205b39c5158SmillertCheck out the MLDBM module, available on CPAN in the directory
2206b39c5158SmillertF<modules/by-module/MLDBM>.
2207b39c5158Smillert
22089f11ffb7Safresh1=head2 What does "wide character in subroutine entry" mean?
22099f11ffb7Safresh1
22109f11ffb7Safresh1You will usually get this message if you are working with UTF-8 data and
22119f11ffb7Safresh1want to read/write it from/to a Berkeley DB database file.
22129f11ffb7Safresh1
22139f11ffb7Safresh1The easist way to deal with this issue is to use the pre-defined "utf8"
22149f11ffb7Safresh1B<DBM_Filter> (see L<DBM_Filter>) that was designed to deal with this
22159f11ffb7Safresh1situation.
22169f11ffb7Safresh1
22179f11ffb7Safresh1The example below shows what you need if I<both> the key and value are
22189f11ffb7Safresh1expected to be in UTF-8.
22199f11ffb7Safresh1
22209f11ffb7Safresh1    use DB_File;
22219f11ffb7Safresh1    use DBM_Filter;
22229f11ffb7Safresh1
22239f11ffb7Safresh1    my $db = tie %h, 'DB_File', '/tmp/try.db', O_CREAT|O_RDWR, 0666, $DB_BTREE;
22249f11ffb7Safresh1    $db->Filter_Key_Push('utf8');
22259f11ffb7Safresh1    $db->Filter_Value_Push('utf8');
22269f11ffb7Safresh1
22279f11ffb7Safresh1    my $key = "\N{LATIN SMALL LETTER A WITH ACUTE}";
22289f11ffb7Safresh1    my $value = "\N{LATIN SMALL LETTER E WITH ACUTE}";
22299f11ffb7Safresh1    $h{ $key } = $value;
22309f11ffb7Safresh1
2231b39c5158Smillert=head2 What does "Invalid Argument" mean?
2232b39c5158Smillert
2233b39c5158SmillertYou will get this error message when one of the parameters in the
2234b39c5158SmillertC<tie> call is wrong. Unfortunately there are quite a few parameters to
2235b39c5158Smillertget wrong, so it can be difficult to figure out which one it is.
2236b39c5158Smillert
2237b39c5158SmillertHere are a couple of possibilities:
2238b39c5158Smillert
2239b39c5158Smillert=over 5
2240b39c5158Smillert
2241b39c5158Smillert=item 1.
2242b39c5158Smillert
2243b39c5158SmillertAttempting to reopen a database without closing it.
2244b39c5158Smillert
2245b39c5158Smillert=item 2.
2246b39c5158Smillert
2247b39c5158SmillertUsing the O_WRONLY flag.
2248b39c5158Smillert
2249b39c5158Smillert=back
2250b39c5158Smillert
2251b39c5158Smillert=head2 What does "Bareword 'DB_File' not allowed" mean?
2252b39c5158Smillert
2253b39c5158SmillertYou will encounter this particular error message when you have the
2254b39c5158SmillertC<strict 'subs'> pragma (or the full strict pragma) in your script.
2255b39c5158SmillertConsider this script:
2256b39c5158Smillert
2257b39c5158Smillert    use warnings ;
2258b39c5158Smillert    use strict ;
2259b39c5158Smillert    use DB_File ;
2260b39c5158Smillert    my %x ;
2261b39c5158Smillert    tie %x, DB_File, "filename" ;
2262b39c5158Smillert
2263b39c5158SmillertRunning it produces the error in question:
2264b39c5158Smillert
2265b39c5158Smillert    Bareword "DB_File" not allowed while "strict subs" in use
2266b39c5158Smillert
2267b39c5158SmillertTo get around the error, place the word C<DB_File> in either single or
2268b39c5158Smillertdouble quotes, like this:
2269b39c5158Smillert
2270b39c5158Smillert    tie %x, "DB_File", "filename" ;
2271b39c5158Smillert
2272b39c5158SmillertAlthough it might seem like a real pain, it is really worth the effort
2273b39c5158Smillertof having a C<use strict> in all your scripts.
2274b39c5158Smillert
2275b39c5158Smillert=head1 REFERENCES
2276b39c5158Smillert
2277b39c5158SmillertArticles that are either about B<DB_File> or make use of it.
2278b39c5158Smillert
2279b39c5158Smillert=over 5
2280b39c5158Smillert
2281b39c5158Smillert=item 1.
2282b39c5158Smillert
2283b39c5158SmillertI<Full-Text Searching in Perl>, Tim Kientzle (tkientzle@ddj.com),
2284b39c5158SmillertDr. Dobb's Journal, Issue 295, January 1999, pp 34-41
2285b39c5158Smillert
2286b39c5158Smillert=back
2287b39c5158Smillert
2288b39c5158Smillert=head1 HISTORY
2289b39c5158Smillert
2290b39c5158SmillertMoved to the Changes file.
2291b39c5158Smillert
2292b39c5158Smillert=head1 BUGS
2293b39c5158Smillert
2294b39c5158SmillertSome older versions of Berkeley DB had problems with fixed length
2295b39c5158Smillertrecords using the RECNO file format. This problem has been fixed since
2296b39c5158Smillertversion 1.85 of Berkeley DB.
2297b39c5158Smillert
2298b39c5158SmillertI am sure there are bugs in the code. If you do find any, or can
2299b39c5158Smillertsuggest any enhancements, I would welcome your comments.
2300b39c5158Smillert
230156d68f1eSafresh1=head1 SUPPORT
230256d68f1eSafresh1
230356d68f1eSafresh1General feedback/questions/bug reports should be sent to
230456d68f1eSafresh1L<https://github.com/pmqs/DB_File/issues> (preferred) or
230556d68f1eSafresh1L<https://rt.cpan.org/Public/Dist/Display.html?Name=DB_File>.
230656d68f1eSafresh1
2307b39c5158Smillert=head1 AVAILABILITY
2308b39c5158Smillert
2309b39c5158SmillertB<DB_File> comes with the standard Perl source distribution. Look in
2310b39c5158Smillertthe directory F<ext/DB_File>. Given the amount of time between releases
2311b39c5158Smillertof Perl the version that ships with Perl is quite likely to be out of
2312b39c5158Smillertdate, so the most recent version can always be found on CPAN (see
2313b39c5158SmillertL<perlmodlib/CPAN> for details), in the directory
2314b39c5158SmillertF<modules/by-module/DB_File>.
2315b39c5158Smillert
231656d68f1eSafresh1B<DB_File> is designed to work with any version of Berkeley DB, but is limited to the functionality provided by
231756d68f1eSafresh1version 1. If you want to make use of the new features available in Berkeley DB
231856d68f1eSafresh12.x, or greater, use the Perl module L<BerkeleyDB|https://metacpan.org/pod/BerkeleyDB> instead.
2319b39c5158Smillert
232056d68f1eSafresh1The official web site for Berkeley DB is L<http://www.oracle.com/technology/products/berkeley-db/db/index.html>.
2321b39c5158SmillertAll versions of Berkeley DB are available there.
2322b39c5158Smillert
2323b39c5158SmillertAlternatively, Berkeley DB version 1 is available at your nearest CPAN
2324b39c5158Smillertarchive in F<src/misc/db.1.85.tar.gz>.
2325b39c5158Smillert
2326b39c5158Smillert=head1 COPYRIGHT
2327b39c5158Smillert
2328*3d61058aSafresh1Copyright (c) 1995-2023 Paul Marquess. All rights reserved. This program
2329b39c5158Smillertis free software; you can redistribute it and/or modify it under the
2330b39c5158Smillertsame terms as Perl itself.
2331b39c5158Smillert
2332b39c5158SmillertAlthough B<DB_File> is covered by the Perl license, the library it
2333b39c5158Smillertmakes use of, namely Berkeley DB, is not. Berkeley DB has its own
2334e0680481Safresh1copyright and its own license.
2335e0680481Safresh1See L<AGPL|https://www.oracle.com/downloads/licenses/berkeleydb-oslicense.html> for more details.
2336e0680481Safresh1Please take the time to read the Berkeley DB license and decide how it impacts your use of this Perl module.
2337b39c5158Smillert
2338b39c5158Smillert=head1 SEE ALSO
2339b39c5158Smillert
2340b39c5158SmillertL<perl>, L<dbopen(3)>, L<hash(3)>, L<recno(3)>, L<btree(3)>,
23419f11ffb7Safresh1L<perldbmfilter>, L<DBM_Filter>
2342b39c5158Smillert
2343b39c5158Smillert=head1 AUTHOR
2344b39c5158Smillert
2345b39c5158SmillertThe DB_File interface was written by Paul Marquess
2346b39c5158SmillertE<lt>pmqs@cpan.orgE<gt>.
2347b39c5158Smillert
2348b39c5158Smillert=cut
2349