3 DB_File.xs -- Perl 5 interface to Berkeley DB
5 written by Paul Marquess <Paul.Marquess@btinternet.com>
6 last modified 4th August 1999
9 All comments/suggestions/problems are welcome
11 Copyright (c) 1995-9 Paul Marquess. All rights reserved.
12 This program is free software; you can redistribute it and/or
13 modify it under the same terms as Perl itself.
17 0.2 - No longer bombs out if dbopen returns an error.
18 0.3 - Added some support for multiple btree compares
19 1.0 - Complete support for multiple callbacks added.
20 Fixed a problem with pushing a value onto an empty list.
21 1.01 - Fixed a SunOS core dump problem.
22 The return value from TIEHASH wasn't set to NULL when
23 dbopen returned an error.
24 1.02 - Use ALIAS to define TIEARRAY.
25 Removed some redundant commented code.
26 Merged OS2 code into the main distribution.
27 Allow negative subscripts with RECNO interface.
28 Changed the default flags to O_CREAT|O_RDWR
30 1.04 - fixed a couple of bugs in hash_cb. Patches supplied by
31 Dave Hammen, hammen@gothamcity.jsc.nasa.gov
32 1.05 - Added logic to allow prefix & hash types to be specified via
34 1.06 - Minor namespace cleanup: Localized PrintBtree.
35 1.07 - Fixed bug with RECNO, where bval wasn't defaulting to "\n".
36 1.08 - No change to DB_File.xs
37 1.09 - Default mode for dbopen changed to 0666
38 1.10 - Fixed fd method so that it still returns -1 for
39 in-memory files when db 1.86 is used.
40 1.11 - No change to DB_File.xs
41 1.12 - No change to DB_File.xs
42 1.13 - Tidied up a few casts.
43 1.14 - Made it illegal to tie an associative array to a RECNO
44 database and an ordinary array to a HASH or BTREE database.
45 1.50 - Make work with both DB 1.x or DB 2.x
46 1.51 - Fixed a bug in mapping 1.x O_RDONLY flag to 2.x DB_RDONLY equivalent
47 1.52 - Patch from Gisle Aas <gisle@aas.no> to suppress "use of
48 undefined value" warning with db_get and db_seq.
49 1.53 - Added DB_RENUMBER to flags for recno.
50 1.54 - Fixed bug in the fd method
51 1.55 - Fix for AIX from Jarkko Hietaniemi
52 1.56 - No change to DB_File.xs
53 1.57 - added the #undef op to allow building with Threads support.
54 1.58 - Fixed a problem with the use of sv_setpvn. When the
55 size is specified as 0, it does a strlen on the data.
56 This was ok for DB 1.x, but isn't for DB 2.x.
57 1.59 - No change to DB_File.xs
58 1.60 - Some code tidy up
59 1.61 - added flagSet macro for DB 2.5.x
60 fixed typo in O_RDONLY test.
61 1.62 - No change to DB_File.xs
62 1.63 - Fix to alllow DB 2.6.x to build.
63 1.64 - Tidied up the 1.x to 2.x flags mapping code.
64 Added a patch from Mark Kettenis <kettenis@wins.uva.nl>
65 to fix a flag mapping problem with O_RDONLY on the Hurd
66 1.65 - Fixed a bug in the PUSH logic.
67 Added BOOT check that using 2.3.4 or greater
68 1.66 - Added DBM filter code
69 1.67 - Backed off the use of newSVpvn.
70 Fixed DBM Filter code for Perl 5.004.
71 Fixed a small memory leak in the filter code.
72 1.68 - fixed backward compatability bug with R_IAFTER & R_IBEFORE
73 merged in the 5.005_58 changes
74 1.69 - fixed a bug in push -- DB_APPEND wasn't working properly.
75 Fixed the R_SETCURSOR bug introduced in 1.68
76 Added a new Perl variable $DB_File::db_ver
77 1.70 - Initialise $DB_File::db_ver and $DB_File::db_version with
78 GV_ADD|GV_ADDMULT -- bug spotted by Nick Ing-Simmons.
79 Added a BOOT check to test for equivalent versions of db.h &
89 # include "patchlevel.h"
90 # define PERL_REVISION 5
91 # define PERL_VERSION PATCHLEVEL
92 # define PERL_SUBVERSION SUBVERSION
95 #if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 ))
97 # define PL_sv_undef sv_undef
102 /* DEFSV appears first in 5.004_56 */
104 # define DEFSV GvSV(defgv)
107 /* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
108 * shortly #included by the <db.h>) __attribute__ to the possibly
109 * already defined __attribute__, for example by GNUC or by Perl. */
113 /* If Perl has been compiled with Threads support,the symbol op will
114 be defined here. This clashes with a field name in db.h, so get rid of it.
129 # define newSVpvn(a,b) newSVpv(a,b)
135 #define DBM_FILTERING
139 #ifdef DB_VERSION_MAJOR
141 /* map version 2 features & constants onto their version 1 equivalent */
146 #define DB_Prefix_t size_t
151 #define DB_Hash_t u_int32_t
153 /* DBTYPE stays the same */
154 /* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
155 typedef DB_INFO INFO ;
157 /* version 2 has db_recno_t in place of recno_t */
158 typedef db_recno_t recno_t;
161 #define R_CURSOR DB_SET_RANGE
162 #define R_FIRST DB_FIRST
163 #define R_IAFTER DB_AFTER
164 #define R_IBEFORE DB_BEFORE
165 #define R_LAST DB_LAST
166 #define R_NEXT DB_NEXT
167 #define R_NOOVERWRITE DB_NOOVERWRITE
168 #define R_PREV DB_PREV
169 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
170 #define R_SETCURSOR 0x800000
172 #define R_SETCURSOR (-100)
174 #define R_RECNOSYNC 0
175 #define R_FIXEDLEN DB_FIXEDLEN
178 #define db_HA_hash h_hash
179 #define db_HA_ffactor h_ffactor
180 #define db_HA_nelem h_nelem
181 #define db_HA_bsize db_pagesize
182 #define db_HA_cachesize db_cachesize
183 #define db_HA_lorder db_lorder
185 #define db_BT_compare bt_compare
186 #define db_BT_prefix bt_prefix
187 #define db_BT_flags flags
188 #define db_BT_psize db_pagesize
189 #define db_BT_cachesize db_cachesize
190 #define db_BT_lorder db_lorder
191 #define db_BT_maxkeypage
192 #define db_BT_minkeypage
195 #define db_RE_reclen re_len
196 #define db_RE_flags flags
197 #define db_RE_bval re_pad
198 #define db_RE_bfname re_source
199 #define db_RE_psize db_pagesize
200 #define db_RE_cachesize db_cachesize
201 #define db_RE_lorder db_lorder
205 #define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
208 #define DBT_flags(x) x.flags = 0
209 #define DB_flags(x, v) x |= v
211 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
212 #define flagSet(flags, bitmask) ((flags) & (bitmask))
214 #define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (bitmask))
217 #else /* db version 1.x */
230 #define DB_Prefix_t mDB_Prefix_t
237 #define DB_Hash_t mDB_Hash_t
240 #define db_HA_hash hash.hash
241 #define db_HA_ffactor hash.ffactor
242 #define db_HA_nelem hash.nelem
243 #define db_HA_bsize hash.bsize
244 #define db_HA_cachesize hash.cachesize
245 #define db_HA_lorder hash.lorder
247 #define db_BT_compare btree.compare
248 #define db_BT_prefix btree.prefix
249 #define db_BT_flags btree.flags
250 #define db_BT_psize btree.psize
251 #define db_BT_cachesize btree.cachesize
252 #define db_BT_lorder btree.lorder
253 #define db_BT_maxkeypage btree.maxkeypage
254 #define db_BT_minkeypage btree.minkeypage
256 #define db_RE_reclen recno.reclen
257 #define db_RE_flags recno.flags
258 #define db_RE_bval recno.bval
259 #define db_RE_bfname recno.bfname
260 #define db_RE_psize recno.psize
261 #define db_RE_cachesize recno.cachesize
262 #define db_RE_lorder recno.lorder
266 #define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
268 #define DB_flags(x, v)
269 #define flagSet(flags, bitmask) ((flags) & (bitmask))
271 #endif /* db version 1 */
275 #define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, flags)
276 #define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, flags)
277 #define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
279 #define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
280 #define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
282 #ifdef DB_VERSION_MAJOR
283 #define db_DESTROY(db) ( db->cursor->c_close(db->cursor),\
284 db->dbp->close(db->dbp, 0) )
285 #define db_close(db) ((db->dbp)->close)(db->dbp, 0)
286 #define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \
287 ? ((db->cursor)->c_del)(db->cursor, 0) \
288 : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
292 #define db_DESTROY(db) ((db->dbp)->close)(db->dbp)
293 #define db_close(db) ((db->dbp)->close)(db->dbp)
294 #define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
295 #define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
300 #define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
310 #ifdef DB_VERSION_MAJOR
314 SV * filter_fetch_key ;
315 SV * filter_store_key ;
316 SV * filter_fetch_value ;
317 SV * filter_store_value ;
319 #endif /* DBM_FILTERING */
323 typedef DB_File_type * DB_File ;
328 #define ckFilter(arg,type,name) \
331 /* printf("filtering %s\n", name) ;*/ \
333 croak("recursion detected in %s", name) ; \
334 db->filtering = TRUE ; \
335 save_defsv = newSVsv(DEFSV) ; \
336 sv_setsv(DEFSV, arg) ; \
338 (void) perl_call_sv(db->type, G_DISCARD|G_NOARGS); \
339 sv_setsv(arg, DEFSV) ; \
340 sv_setsv(DEFSV, save_defsv) ; \
341 SvREFCNT_dec(save_defsv) ; \
342 db->filtering = FALSE ; \
343 /*printf("end of filtering %s\n", name) ;*/ \
348 #define ckFilter(arg,type, name)
350 #endif /* DBM_FILTERING */
352 #define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
354 #define OutputValue(arg, name) \
355 { if (RETVAL == 0) { \
356 my_sv_setpvn(arg, name.data, name.size) ; \
357 ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
361 #define OutputKey(arg, name) \
364 if (db->type != DB_RECNO) { \
365 my_sv_setpvn(arg, name.data, name.size); \
368 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
369 ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \
374 /* Internal Global Data */
375 static recno_t Value ;
376 static recno_t zero = 0 ;
377 static DB_File CurrentDB ;
378 static DBTKEY empty ;
380 #ifdef DB_VERSION_MAJOR
384 db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
386 db_put(db, key, value, flags)
395 if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) {
399 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
400 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0)
402 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0)
406 memset(&l_key, 0, sizeof(l_key));
407 l_key.data = key.data;
408 l_key.size = key.size;
409 memset(&l_value, 0, sizeof(l_value));
410 l_value.data = value.data;
411 l_value.size = value.size;
413 if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) {
414 (void)temp_cursor->c_close(temp_cursor);
418 status = temp_cursor->c_put(temp_cursor, &key, &value, flags);
419 (void)temp_cursor->c_close(temp_cursor);
425 if (flagSet(flags, R_CURSOR)) {
426 return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT);
429 if (flagSet(flags, R_SETCURSOR)) {
430 if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0)
432 return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE);
436 return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
440 #endif /* DB_VERSION_MAJOR */
445 SV * version_sv = perl_get_sv("DB_File::db_version", GV_ADD|GV_ADDMULTI) ;
446 SV * ver_sv = perl_get_sv("DB_File::db_ver", GV_ADD|GV_ADDMULTI) ;
447 #ifdef DB_VERSION_MAJOR
448 int Major, Minor, Patch ;
450 (void)db_version(&Major, &Minor, &Patch) ;
452 /* Check that the versions of db.h and libdb.a are the same */
453 if (Major != DB_VERSION_MAJOR || Minor != DB_VERSION_MINOR
454 || Patch != DB_VERSION_PATCH)
455 croak("\nDB_File needs compatible versions of libdb & db.h\n\tyou have db.h version %d.%d.%d and libdb version %d.%d.%d\n",
456 DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
457 Major, Minor, Patch) ;
459 /* check that libdb is recent enough -- we need 2.3.4 or greater */
460 if (Major == 2 && (Minor < 3 || (Minor == 3 && Patch < 4)))
461 croak("DB_File needs Berkeley DB 2.3.4 or greater, you have %d.%d.%d\n",
462 Major, Minor, Patch) ;
465 sv_setpvf(version_sv, "%d.%d", Major, Minor) ;
466 sv_setpvf(ver_sv, "%d.%03d%03d", Major, Minor, Patch) ;
470 sprintf(buffer, "%d.%d", Major, Minor) ;
471 sv_setpv(version_sv, buffer) ;
472 sprintf(buffer, "%d.%03d%03d", Major, Minor, Patch) ;
473 sv_setpv(ver_sv, buffer) ;
478 sv_setiv(version_sv, 1) ;
479 sv_setiv(ver_sv, 1) ;
487 btree_compare(const DBT *key1, const DBT *key2)
489 btree_compare(key1, key2)
498 void * data1, * data2 ;
506 /* As newSVpv will assume that the data pointer is a null terminated C
507 string if the size parameter is 0, make sure that data points to an
508 empty string if the length is 0
521 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
522 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
525 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
530 croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
543 btree_prefix(const DBT *key1, const DBT *key2)
545 btree_prefix(key1, key2)
554 void * data1, * data2 ;
562 /* As newSVpv will assume that the data pointer is a null terminated C
563 string if the size parameter is 0, make sure that data points to an
564 empty string if the length is 0
577 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
578 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
581 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
586 croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
599 hash_cb(const void *data, size_t size)
618 /* DGH - Next two lines added to fix corrupted stack problem */
624 XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
627 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
632 croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
648 PrintHash(INFO *hash)
654 printf ("HASH Info\n") ;
655 printf (" hash = %s\n",
656 (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
657 printf (" bsize = %d\n", hash->db_HA_bsize) ;
658 printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
659 printf (" nelem = %d\n", hash->db_HA_nelem) ;
660 printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
661 printf (" lorder = %d\n", hash->db_HA_lorder) ;
667 PrintRecno(INFO *recno)
673 printf ("RECNO Info\n") ;
674 printf (" flags = %d\n", recno->db_RE_flags) ;
675 printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
676 printf (" psize = %d\n", recno->db_RE_psize) ;
677 printf (" lorder = %d\n", recno->db_RE_lorder) ;
678 printf (" reclen = %ul\n", (unsigned long)recno->db_RE_reclen) ;
679 printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
680 printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
685 PrintBtree(INFO *btree)
691 printf ("BTREE Info\n") ;
692 printf (" compare = %s\n",
693 (btree->db_BT_compare ? "redefined" : "default")) ;
694 printf (" prefix = %s\n",
695 (btree->db_BT_prefix ? "redefined" : "default")) ;
696 printf (" flags = %d\n", btree->db_BT_flags) ;
697 printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
698 printf (" psize = %d\n", btree->db_BT_psize) ;
699 #ifndef DB_VERSION_MAJOR
700 printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
701 printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
703 printf (" lorder = %d\n", btree->db_BT_lorder) ;
708 #define PrintRecno(recno)
709 #define PrintHash(hash)
710 #define PrintBtree(btree)
717 GetArrayLength(pTHX_ DB_File db)
729 RETVAL = do_SEQ(db, key, value, R_LAST) ;
731 RETVAL = *(I32 *)key.data ;
732 else /* No key means empty file */
735 return ((I32)RETVAL) ;
740 GetRecnoKey(pTHX_ DB_File db, I32 value)
742 GetRecnoKey(db, value)
748 /* Get the length of the array */
749 I32 length = GetArrayLength(aTHX_ db) ;
751 /* check for attempt to write before start of array */
752 if (length + value + 1 <= 0)
753 croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
755 value = length + value + 1 ;
765 ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
767 ParseOpenInfo(isHASH, name, flags, mode, sv)
777 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
778 void * openinfo = NULL ;
779 INFO * info = &RETVAL->info ;
782 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
783 Zero(RETVAL, 1, DB_File_type) ;
785 /* Default to HASH */
787 RETVAL->filtering = 0 ;
788 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
789 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
790 #endif /* DBM_FILTERING */
791 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
792 RETVAL->type = DB_HASH ;
794 /* DGH - Next line added to avoid SEGV on existing hash DB */
797 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
798 RETVAL->in_memory = (name == NULL) ;
803 croak ("type parameter is not a reference") ;
805 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
806 if (svp && SvOK(*svp))
807 action = (HV*) SvRV(*svp) ;
809 croak("internal error") ;
811 if (sv_isa(sv, "DB_File::HASHINFO"))
815 croak("DB_File can only tie an associative array to a DB_HASH database") ;
817 RETVAL->type = DB_HASH ;
818 openinfo = (void*)info ;
820 svp = hv_fetch(action, "hash", 4, FALSE);
822 if (svp && SvOK(*svp))
824 info->db_HA_hash = hash_cb ;
825 RETVAL->hash = newSVsv(*svp) ;
828 info->db_HA_hash = NULL ;
830 svp = hv_fetch(action, "ffactor", 7, FALSE);
831 info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
833 svp = hv_fetch(action, "nelem", 5, FALSE);
834 info->db_HA_nelem = svp ? SvIV(*svp) : 0;
836 svp = hv_fetch(action, "bsize", 5, FALSE);
837 info->db_HA_bsize = svp ? SvIV(*svp) : 0;
839 svp = hv_fetch(action, "cachesize", 9, FALSE);
840 info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
842 svp = hv_fetch(action, "lorder", 6, FALSE);
843 info->db_HA_lorder = svp ? SvIV(*svp) : 0;
847 else if (sv_isa(sv, "DB_File::BTREEINFO"))
850 croak("DB_File can only tie an associative array to a DB_BTREE database");
852 RETVAL->type = DB_BTREE ;
853 openinfo = (void*)info ;
855 svp = hv_fetch(action, "compare", 7, FALSE);
856 if (svp && SvOK(*svp))
858 info->db_BT_compare = btree_compare ;
859 RETVAL->compare = newSVsv(*svp) ;
862 info->db_BT_compare = NULL ;
864 svp = hv_fetch(action, "prefix", 6, FALSE);
865 if (svp && SvOK(*svp))
867 info->db_BT_prefix = btree_prefix ;
868 RETVAL->prefix = newSVsv(*svp) ;
871 info->db_BT_prefix = NULL ;
873 svp = hv_fetch(action, "flags", 5, FALSE);
874 info->db_BT_flags = svp ? SvIV(*svp) : 0;
876 svp = hv_fetch(action, "cachesize", 9, FALSE);
877 info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
879 #ifndef DB_VERSION_MAJOR
880 svp = hv_fetch(action, "minkeypage", 10, FALSE);
881 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
883 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
884 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
887 svp = hv_fetch(action, "psize", 5, FALSE);
888 info->db_BT_psize = svp ? SvIV(*svp) : 0;
890 svp = hv_fetch(action, "lorder", 6, FALSE);
891 info->db_BT_lorder = svp ? SvIV(*svp) : 0;
896 else if (sv_isa(sv, "DB_File::RECNOINFO"))
899 croak("DB_File can only tie an array to a DB_RECNO database");
901 RETVAL->type = DB_RECNO ;
902 openinfo = (void *)info ;
904 info->db_RE_flags = 0 ;
906 svp = hv_fetch(action, "flags", 5, FALSE);
907 info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
909 svp = hv_fetch(action, "reclen", 6, FALSE);
910 info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
912 svp = hv_fetch(action, "cachesize", 9, FALSE);
913 info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
915 svp = hv_fetch(action, "psize", 5, FALSE);
916 info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
918 svp = hv_fetch(action, "lorder", 6, FALSE);
919 info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
921 #ifdef DB_VERSION_MAJOR
922 info->re_source = name ;
925 svp = hv_fetch(action, "bfname", 6, FALSE);
926 if (svp && SvOK(*svp)) {
927 char * ptr = SvPV(*svp,n_a) ;
928 #ifdef DB_VERSION_MAJOR
929 name = (char*) n_a ? ptr : NULL ;
931 info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
935 #ifdef DB_VERSION_MAJOR
938 info->db_RE_bfname = NULL ;
941 svp = hv_fetch(action, "bval", 4, FALSE);
942 #ifdef DB_VERSION_MAJOR
943 if (svp && SvOK(*svp))
947 value = (int)*SvPV(*svp, n_a) ;
951 if (info->flags & DB_FIXEDLEN) {
952 info->re_pad = value ;
953 info->flags |= DB_PAD ;
956 info->re_delim = value ;
957 info->flags |= DB_DELIMITER ;
962 if (svp && SvOK(*svp))
965 info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
967 info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
968 DB_flags(info->flags, DB_DELIMITER) ;
973 if (info->db_RE_flags & R_FIXEDLEN)
974 info->db_RE_bval = (u_char) ' ' ;
976 info->db_RE_bval = (u_char) '\n' ;
977 DB_flags(info->flags, DB_DELIMITER) ;
982 info->flags |= DB_RENUMBER ;
988 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
992 /* OS2 Specific Code */
999 #ifdef DB_VERSION_MAJOR
1005 /* Map 1.x flags to 2.x flags */
1006 if ((flags & O_CREAT) == O_CREAT)
1007 Flags |= DB_CREATE ;
1010 if (flags == O_RDONLY)
1012 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1014 Flags |= DB_RDONLY ;
1017 if ((flags & O_TRUNC) == O_TRUNC)
1018 Flags |= DB_TRUNCATE ;
1021 status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
1023 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
1024 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
1026 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1031 RETVAL->dbp = NULL ;
1035 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
1043 #ifdef CAN_PROTOTYPE
1044 constant(char *name, int arg)
1056 if (strEQ(name, "BTREEMAGIC"))
1062 if (strEQ(name, "BTREEVERSION"))
1064 return BTREEVERSION;
1072 if (strEQ(name, "DB_LOCK"))
1078 if (strEQ(name, "DB_SHMEM"))
1084 if (strEQ(name, "DB_TXN"))
1098 if (strEQ(name, "HASHMAGIC"))
1104 if (strEQ(name, "HASHVERSION"))
1120 if (strEQ(name, "MAX_PAGE_NUMBER"))
1121 #ifdef MAX_PAGE_NUMBER
1122 return (U32)MAX_PAGE_NUMBER;
1126 if (strEQ(name, "MAX_PAGE_OFFSET"))
1127 #ifdef MAX_PAGE_OFFSET
1128 return MAX_PAGE_OFFSET;
1132 if (strEQ(name, "MAX_REC_NUMBER"))
1133 #ifdef MAX_REC_NUMBER
1134 return (U32)MAX_REC_NUMBER;
1148 if (strEQ(name, "RET_ERROR"))
1154 if (strEQ(name, "RET_SPECIAL"))
1160 if (strEQ(name, "RET_SUCCESS"))
1166 if (strEQ(name, "R_CURSOR"))
1172 if (strEQ(name, "R_DUP"))
1178 if (strEQ(name, "R_FIRST"))
1184 if (strEQ(name, "R_FIXEDLEN"))
1190 if (strEQ(name, "R_IAFTER"))
1196 if (strEQ(name, "R_IBEFORE"))
1202 if (strEQ(name, "R_LAST"))
1208 if (strEQ(name, "R_NEXT"))
1214 if (strEQ(name, "R_NOKEY"))
1220 if (strEQ(name, "R_NOOVERWRITE"))
1221 #ifdef R_NOOVERWRITE
1222 return R_NOOVERWRITE;
1226 if (strEQ(name, "R_PREV"))
1232 if (strEQ(name, "R_RECNOSYNC"))
1238 if (strEQ(name, "R_SETCURSOR"))
1244 if (strEQ(name, "R_SNAPSHOT"))
1278 MODULE = DB_File PACKAGE = DB_File PREFIX = db_
1282 GetVersionInfo(aTHX) ;
1284 empty.data = &zero ;
1285 empty.size = sizeof(recno_t) ;
1296 db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
1303 char * name = (char *) NULL ;
1304 SV * sv = (SV *) NULL ;
1307 if (items >= 3 && SvOK(ST(2)))
1308 name = (char*) SvPV(ST(2), n_a) ;
1313 RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
1314 if (RETVAL->dbp == NULL)
1327 SvREFCNT_dec(db->hash) ;
1329 SvREFCNT_dec(db->compare) ;
1331 SvREFCNT_dec(db->prefix) ;
1332 #ifdef DBM_FILTERING
1333 if (db->filter_fetch_key)
1334 SvREFCNT_dec(db->filter_fetch_key) ;
1335 if (db->filter_store_key)
1336 SvREFCNT_dec(db->filter_store_key) ;
1337 if (db->filter_fetch_value)
1338 SvREFCNT_dec(db->filter_fetch_value) ;
1339 if (db->filter_store_value)
1340 SvREFCNT_dec(db->filter_store_value) ;
1341 #endif /* DBM_FILTERING */
1343 #ifdef DB_VERSION_MAJOR
1350 db_DELETE(db, key, flags=0)
1368 RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
1374 db_FETCH(db, key, flags=0)
1384 /* RETVAL = ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) ; */
1385 RETVAL = db_get(db, key, value, flags) ;
1386 ST(0) = sv_newmortal();
1387 OutputValue(ST(0), value)
1391 db_STORE(db, key, value, flags=0)
1411 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1412 ST(0) = sv_newmortal();
1413 OutputKey(ST(0), key) ;
1426 RETVAL = do_SEQ(db, key, value, R_NEXT) ;
1427 ST(0) = sv_newmortal();
1428 OutputKey(ST(0), key) ;
1432 # These would be nice for RECNO
1451 #ifdef DB_VERSION_MAJOR
1452 /* get the first value */
1453 RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
1458 for (i = items-1 ; i > 0 ; --i)
1460 value.data = SvPV(ST(i), n_a) ;
1464 key.size = sizeof(int) ;
1465 #ifdef DB_VERSION_MAJOR
1466 RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
1468 RETVAL = (Db->put)(Db, &key, &value, R_IBEFORE) ;
1490 /* First get the final value */
1491 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1492 ST(0) = sv_newmortal();
1496 /* the call to del will trash value, so take a copy now */
1497 OutputValue(ST(0), value) ;
1498 RETVAL = db_del(db, key, R_CURSOR) ;
1500 sv_setsv(ST(0), &PL_sv_undef);
1516 /* get the first value */
1517 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1518 ST(0) = sv_newmortal();
1522 /* the call to del will trash value, so take a copy now */
1523 OutputValue(ST(0), value) ;
1524 RETVAL = db_del(db, key, R_CURSOR) ;
1526 sv_setsv (ST(0), &PL_sv_undef) ;
1546 #ifdef DB_VERSION_MAJOR
1547 RETVAL = do_SEQ(db, key, value, DB_LAST) ;
1550 for (i = 1 ; i < items ; ++i)
1552 value.data = SvPV(ST(i), n_a) ;
1554 RETVAL = (Db->put)(Db, NULL, &key, &value, DB_APPEND) ;
1560 /* Set the Cursor to the Last element */
1561 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1566 for (i = items - 1 ; i > 0 ; --i)
1568 value.data = SvPV(ST(i), n_a) ;
1570 RETVAL = (Db->put)(Db, &key, &value, R_IAFTER) ;
1584 ALIAS: FETCHSIZE = 1
1587 RETVAL = GetArrayLength(aTHX_ db) ;
1593 # Now provide an interface to the rest of the DB functionality
1597 db_del(db, key, flags=0)
1603 RETVAL = db_del(db, key, flags) ;
1604 #ifdef DB_VERSION_MAJOR
1607 else if (RETVAL == DB_NOTFOUND)
1615 db_get(db, key, value, flags=0)
1623 RETVAL = db_get(db, key, value, flags) ;
1624 #ifdef DB_VERSION_MAJOR
1627 else if (RETVAL == DB_NOTFOUND)
1635 db_put(db, key, value, flags=0)
1642 RETVAL = db_put(db, key, value, flags) ;
1643 #ifdef DB_VERSION_MAJOR
1646 else if (RETVAL == DB_KEYEXIST)
1651 key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
1659 #ifdef DB_VERSION_MAJOR
1661 status = (db->in_memory
1663 : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
1667 RETVAL = (db->in_memory
1669 : ((db->dbp)->fd)(db->dbp) ) ;
1675 db_sync(db, flags=0)
1680 RETVAL = db_sync(db, flags) ;
1681 #ifdef DB_VERSION_MAJOR
1690 db_seq(db, key, value, flags)
1698 RETVAL = db_seq(db, key, value, flags);
1699 #ifdef DB_VERSION_MAJOR
1702 else if (RETVAL == DB_NOTFOUND)
1710 #ifdef DBM_FILTERING
1712 #define setFilter(type) \
1715 RETVAL = sv_mortalcopy(db->type) ; \
1717 if (db->type && (code == &PL_sv_undef)) { \
1718 SvREFCNT_dec(db->type) ; \
1723 sv_setsv(db->type, code) ; \
1725 db->type = newSVsv(code) ; \
1731 filter_fetch_key(db, code)
1734 SV * RETVAL = &PL_sv_undef ;
1736 setFilter(filter_fetch_key) ;
1739 filter_store_key(db, code)
1742 SV * RETVAL = &PL_sv_undef ;
1744 setFilter(filter_store_key) ;
1747 filter_fetch_value(db, code)
1750 SV * RETVAL = &PL_sv_undef ;
1752 setFilter(filter_fetch_value) ;
1755 filter_store_value(db, code)
1758 SV * RETVAL = &PL_sv_undef ;
1760 setFilter(filter_store_value) ;
1762 #endif /* DBM_FILTERING */