SDBM_File not implementing EXISTS 
Author Message
 SDBM_File not implementing EXISTS

I have a hash tied to SDBM_File.  When I call exists against the hash, I
recieve the following error.  SDBM_File doesn't define an EXISTS
method.  

I thought this strange, so I checked out SDBM_File, and found it
inherits from Tie::Hash, which tells me it defines an EXISTS method.

Am I broken?  Do I need to write a new class to implement exists?

Any clues?

Thanks!

Jerome



Mon, 22 Jul 2002 03:00:00 GMT  
 SDBM_File not implementing EXISTS

Quote:
>I have a hash tied to SDBM_File.  When I call exists against the hash, I
>recieve the following error.  SDBM_File doesn't define an EXISTS
>method.  

>I thought this strange, so I checked out SDBM_File, and found it
>inherits from Tie::Hash, which tells me it defines an EXISTS method.

>Am I broken?  Do I need to write a new class to implement exists?

When you look closer, you'll find that EXISTS is defined in Tie::StdHash,
not in Tie::Hash, (and in terms of the standard exists function).

Most DB_* modules don't define an EXISTS method, DB_File (Berkeley
DB) being the only exception I'm aware of.  Even there an undefined
value isn't possible in a tied hash (undef $hash{ x} results in an
empty string being assigned), so that defined and exists are
identical in this case.

So, if you can, just replace exists with defined in your source.
If that is not possible for some reason, you might get away with
something like BEGIN { *SDBM_File::EXISTS = sub { defined $_[0]} },
but I have done only cursory testing.

Anno



Tue, 23 Jul 2002 03:00:00 GMT  
 SDBM_File not implementing EXISTS

Quote:
> I have a hash tied to SDBM_File.  When I call exists against the hash, I
> recieve the following error.  SDBM_File doesn't define an EXISTS method.
> I thought this strange, so I checked out SDBM_File, and found it
> inherits from Tie::Hash, which tells me it defines an EXISTS method.
> Am I broken?  Do I need to write a new class to implement exists?

The underlying SDBM library didn't implement EXISTS.  I patched it to add
this capability when I ran into this, and I believe my patch will be in
the 5.6 release.  If you want to do that yourself, here it is.

--- perl5.005_56/ext/SDBM_File/sdbm/sdbm.h.orig Thu Feb 18 13:02:53 1999

 extern int sdbm_store proto((DBM *, datum, datum, int));
 extern datum sdbm_firstkey proto((DBM *));
 extern datum sdbm_nextkey proto((DBM *));
+extern int sdbm_exists proto((DBM *, datum));

 /*
  * other
--- perl5.005_56/ext/SDBM_File/sdbm/sdbm.c.orig Sun Feb  7 01:54:23 1999

 }

 int
+sdbm_exists(register DBM *db, datum key)
+{
+       if (db == NULL || bad(key))
+               return errno = EINVAL, -1;
+
+       if (getpage(db, exhash(key)))
+               return exipair(db->pagbuf, key);
+
+       return ioerr(db), -1;
+}
+
+int
 sdbm_delete(register DBM *db, datum key)
 {
        if (db == NULL || bad(key))
--- perl5.005_56/ext/SDBM_File/sdbm/pair.h.orig Sat Jan 23 16:56:14 1999

 #define chkpage sdbm__chkpage
 #define delpair sdbm__delpair
 #define duppair sdbm__duppair
+#define exipair sdbm__exipair
 #define fitpair sdbm__fitpair
 #define getnkey sdbm__getnkey

 extern int fitpair proto((char *, int));
 extern void  putpair proto((char *, datum, datum));
 extern datum   getpair proto((char *, datum));
+extern int  exipair proto((char *, datum));
 extern int  delpair proto((char *, datum));
 extern int  chkpage proto((char *));
 extern datum getnkey proto((char *, int));
--- perl5.005_56/ext/SDBM_File/sdbm/pair.c.orig Sat Jan 23 16:56:14 1999

        return val;
 }

+int
+exipair(char *pag, datum key)
+{
+       register short *ino = (short *) pag;
+
+       if (ino[0] == 0)
+               return 0;
+
+       return (seepair(pag, ino[0], key.dptr, key.dsize) != 0);
+}
+
 #ifdef SEEDUPS
 int
 duppair(char *pag, datum key)
--- perl5.005_56/ext/SDBM_File/sdbm/README.too.orig     Sat Jan 23 16:56:13 1999

 Additional portability/configuration changes for libsdbm by Andy Dougherty

+
+
+Mon Mar 22 03:24:47 PST 1999.
+

--- perl5.005_56/ext/SDBM_File/sdbm/sdbm.3.orig Sat Jan 23 16:56:15 1999

 .\" $Id: sdbm.3,v 1.2 90/12/13 13:00:57 oz Exp $
 .TH SDBM 3 "1 March 1990"
 .SH NAME
-sdbm, sdbm_open, sdbm_prep, sdbm_close, sdbm_fetch, sdbm_store, sdbm_delete, sdbm_firstkey, sdbm_nextkey, sdbm_hash, sdbm_rdonly, sdbm_error, sdbm_clearerr, sdbm_dirfno, sdbm_pagfno \- data base subroutines
+sdbm, sdbm_open, sdbm_prep, sdbm_close, sdbm_fetch, sdbm_store, sdbm_delete, sdbm_exists, sdbm_firstkey, sdbm_nextkey, sdbm_hash, sdbm_rdonly, sdbm_error, sdbm_clearerr, sdbm_dirfno, sdbm_pagfno \- data base subroutines
 .SH SYNOPSIS
 .nf

 .sp
 int sdbm_delete(\s-1DBM\s0 *db, datum key)
 .sp
+int sdbm_exists(\s-1DBM\s0 *db, datum key)
+.sp
 datum sdbm_firstkey(\s-1DBM\s0 *db)
 .sp

 .IX sdbm_fetch "" "\fLsdbm_fetch\fR \(em fetch \fLsdbm\fR database data"
 .IX sdbm_store "" "\fLsdbm_store\fR \(em add data to \fLsdbm\fR database"
 .IX sdbm_delete "" "\fLsdbm_delete\fR \(em remove data from \fLsdbm\fR database"
+.IX sdbm_exists "" "\fLsdbm_exists\fR \(em test \fLsdbm\fR key existence"
 .IX sdbm_firstkey "" "\fLsdbm_firstkey\fR \(em access \fLsdbm\fR database"
 .IX sdbm_nextkey "" "\fLsdbm_nextkey\fR \(em access \fLsdbm\fR database"

 routine, and associate data with a key by using the
 .BR sdbm_store (\|)
 routine.
+.BR sdbm_exists (\|)
+will say whether a given key exists in the database.
 .LP
 The values of the
 .I flags
--- perl5.005_56/ext/SDBM_File/SDBM_File.xs.orig        Sat Jan 23 16:56:12 1999

 #define sdbm_FETCH(db,key)                     sdbm_fetch(db,key)
 #define sdbm_STORE(db,key,value,flags)         sdbm_store(db,key,value,flags)
 #define sdbm_DELETE(db,key)                    sdbm_delete(db,key)
+#define sdbm_EXISTS(db,key)                    sdbm_exists(db,key)
 #define sdbm_FIRSTKEY(db)                      sdbm_firstkey(db)
 #define sdbm_NEXTKEY(db,key)                   sdbm_nextkey(db)

 int
 sdbm_DELETE(db, key)
+       SDBM_File       db
+       datum           key
+
+int
+sdbm_EXISTS(db,key)
        SDBM_File       db
        datum           key

--- perl5.005_56/pod/perldelta.pod.orig Sun Feb 28 16:13:46 1999

 A little bit of radial trigonometry (cylindrical and spherical) added,
 for example the great circle distance.

+=item SDBM_File
+
+An EXISTS method has been added to this module (and sdbm_exists() has
+been added to the underlying sdbm library), so one can now call exists
+on an SDBM_File tied hash and get the correct result rather than a
+runtime error.
+
 =item Time::Local

 The timelocal() and timegm() functions used to silently return bogus
--- perl5.005_56/t/lib/sdbm.t.orig      Fri Feb 12 02:14:42 1999

 #If Fcntl is not available, try 0x202 or 0x102 for O_RDWR|O_CREAT
 use Fcntl;

-print "1..18\n";
+print "1..20\n";

 unlink <Op_dbmx.*>;

 print ($h{'foo'} eq '' ? "ok 11\n" : "not ok 11\n");
 print ($h{''} eq 'bar' ? "ok 12\n" : "not ok 12\n");

-untie %h;
-if ($^O eq 'VMS') {
-  unlink 'Op_dbmx.sdbm_dir', $Dfile;
-} else {
-  unlink 'Op_dbmx.dir', $Dfile;
-}
-

 sub ok

     untie(%h);
     unlink "SubDB.pm", <dbhash_tmp.*> ;

+}
+
+ok(19, !exists $h{'goner1'});
+ok(20, exists $h{'foo'});
+
+untie %h;
+if ($^O eq 'VMS') {
+  unlink 'Op_dbmx.sdbm_dir', $Dfile;
+} else {
+  unlink 'Op_dbmx.dir', $Dfile;
 }

--
#!/usr/bin/perl -- Russ Allbery, Just Another Perl Hacker





Tue, 23 Jul 2002 03:00:00 GMT  
 SDBM_File not implementing EXISTS

Quote:
> Most DB_* modules don't define an EXISTS method, DB_File (Berkeley DB)
> being the only exception I'm aware of.  Even there an undefined value
> isn't possible in a tied hash (undef $hash{ x} results in an empty
> string being assigned), so that defined and exists are identical in this
> case.

I think you're confused about the difference between defined and exists.
exists asks whether there is such a key in the database at all; this is
certainly a useful question to ask of a tied hash and any db
implementation really should support that question.  defined and exists
most certainly are not identical for a tied hash; even if they implement
undef as the empty value, $db{key} not existing and $db{key} existing with
a value of '' are two very different things.

--
#!/usr/bin/perl -- Russ Allbery, Just Another Perl Hacker





Tue, 23 Jul 2002 03:00:00 GMT  
 SDBM_File not implementing EXISTS

Quote:

> > Am I broken?  Do I need to write a new class to implement exists?

> The underlying SDBM library didn't implement EXISTS.  I patched it to add
> this capability when I ran into this, and I believe my patch will be in
> the 5.6 release.  If you want to do that yourself, here it is.

[ Patch snipped]

For the record, you rock.

Thanks!

Jerome



Tue, 23 Jul 2002 03:00:00 GMT  
 SDBM_File not implementing EXISTS
)
) I think you're confused about the difference between defined and exists.

I think you have.

) exists asks whether there is such a key in the database at all; this is
) certainly a useful question to ask of a tied hash and any db
) implementation really should support that question.

They do... via C<defined>.

) defined and exists
) most certainly are not identical for a tied hash; even if they implement
) undef as the empty value, $db{key} not existing and $db{key} existing with
) a value of '' are two very different things.

    value   exists   defined
    N/A     0        0
    ''      1        1
    any     1        1

    undef   1        0

since the last case is silently upgraded to the second case,
C<defined> and C<exists> are identical.
--
Tye McQueen    Nothing is obvious unless you are overlooking something
         http://www.metronet.com/~tye/ (scripts, links, nothing fancy)



Tue, 23 Jul 2002 03:00:00 GMT  
 SDBM_File not implementing EXISTS

Quote:

>> I think you're confused about the difference between defined and exists.
> I think you have.

Ah, no, I was thinking backwards instead of forwards.  You're quite
right.  Sorry about that.

Quote:
>     value   exists   defined
>     N/A     0        0
>     ''      1        1
>     any     1        1
>     undef   1        0
> since the last case is silently upgraded to the second case, C<defined>
> and C<exists> are identical.

Yup.

This is not generically true of tied hashes, though, so the post that I
was responding to is still wrong in that particular detail.  It may be
generically true of tied hashes backended by disk files (I don't know),
but the tied hashes returned by, e.g., my Tie::ShadowHash module *could*
usefully distinguish between defined and exists (and do in some
circumstances) if there were a better way of dealing with the backend
problem.  This is one of the reasons why I added support for EXISTS to
SDBM in the first place:

    Not all tied hashes implement EXISTS; in particular, ODBM, NDBM, some
    old versions of GDBM, and versions of SDBM in Perl 5.005_56 or earlier
    don't. Calling exists on a shadow hash that includes one of those tied
    hashes as a data source may therefore result in a runtime error.
    Tie::ShadowHash doesn't use exists except to implement the EXISTS method
    because of this.

    Because it can't use EXISTS due to the above problem, Tie::ShadowHash
    cannot correctly distinguish between a non-existent key and an existing
    key associated with an undefined value. This isn't a large problem,
    since many tied hashes can't store undefined values anyway, but it means
    that if one of your data sources contains a given key associated with an
    undefined value and one of your later data sources contains the same key
    but with a defined value, when the shadow hash is accessed using that
    key, it will return the first defined value it finds. This is an
    exception to the normal rule that all data sources are searched in order
    and the value returned by an access is the first value found.
    (Tie::ShadowHash does correctly handle undefined values stored directly
    in the shadow hash.)

--
#!/usr/bin/perl -- Russ Allbery, Just Another Perl Hacker





Tue, 23 Jul 2002 03:00:00 GMT  
 SDBM_File not implementing EXISTS
)
)     Not all tied hashes implement EXISTS; in particular, ODBM, NDBM, some
)     old versions of GDBM, and versions of SDBM in Perl 5.005_56 or earlier
)     don't. Calling exists on a shadow hash that includes one of those tied
)     hashes as a data source may therefore result in a runtime error.
)     Tie::ShadowHash doesn't use exists except to implement the EXISTS method
)     because of this.

Perhaps Tie::Hash should implement EXISTS as a synonym for
C<defined> since this is a reasonable default.  Having a script
die for using C<exists> seems like a worse solution than allowing
people to write tied hash modules that incorrectly both support
storing of C<undef> and also don't override the defaults EXISTS.
--
Tye McQueen    Nothing is obvious unless you are overlooking something
         http://www.metronet.com/~tye/ (scripts, links, nothing fancy)



Fri, 26 Jul 2002 03:00:00 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. SDBM_File not implementing EXISTS

2. Tie::Hash EXISTS not implemented?

3. SDBM_File - %HASH not returning all records ?

4. Redhat 8.0: IO::Handle::setvbuf not implemented on this architecture

5. ???? Method not implemented POST

6. Perl and method not implemented

7. Bummer, select not implemented

8. "group routines not implemented"-error while testing perl

9. Error 501 Not Implemented

10. IO::Handle::setvbuf not implemented on this architecture.

11. ActivePerl/NT: crypt() not implemented ???

12. Problem using LWP::UserAgent (server returns 501 not implemented error)

 

 
Powered by phpBB® Forum Software