3 DB_File.xs -- Perl 5 interface to Berkeley DB
5 written by Paul Marquess <Paul.Marquess@btinternet.com>
6 last modified 1st March 2002
9 All comments/suggestions/problems are welcome
11 Copyright (c) 1995-2002 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 &
81 1.71 - Support for Berkeley DB version 3.
82 Support for Berkeley DB 2/3's backward compatability mode.
84 1.72 - No change to DB_File.xs
85 1.73 - No change to DB_File.xs
86 1.74 - A call to open needed parenthesised to stop it clashing
88 Added Perl core patches 7703 & 7801.
89 1.75 - Fixed Perl core patch 7703.
90 Added suppport to allow DB_File to be built with
91 Berkeley DB 3.2 -- btree_compare, btree_prefix and hash_cb
93 1.76 - No change to DB_File.xs
94 1.77 - Tidied up a few types used in calling newSVpvn.
95 1.78 - Core patch 10335, 10372, 10534, 10549, 11051 included.
96 1.79 - NEXTKEY ignores the input key.
98 1.800 - Moved backward compatability code into ppport.h.
99 Use the new constants code.
100 1.801 - No change to DB_File.xs
101 1.802 - No change to DB_File.xs
102 1.803 - FETCH, STORE & DELETE don't map the flags parameter
103 into the equivalent Berkeley DB function anymore.
107 #define PERL_NO_GET_CONTEXT
116 /* Mention DB_VERSION_MAJOR_CFG, DB_VERSION_MINOR_CFG, and
117 DB_VERSION_PATCH_CFG here so that Configure pulls them all in. */
119 /* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
120 * shortly #included by the <db.h>) __attribute__ to the possibly
121 * already defined __attribute__, for example by GNUC or by Perl. */
123 /* #if DB_VERSION_MAJOR_CFG < 2 */
124 #ifndef DB_VERSION_MAJOR
125 # undef __attribute__
134 /* Wall starts with 5.7.x */
136 #if PERL_REVISION > 5 || (PERL_REVISION == 5 && PERL_VERSION >= 7)
138 /* Since we dropped the gccish definition of __attribute__ we will want
139 * to redefine dNOOP, however (so that dTHX continues to work). Yes,
140 * all this means that we can't do attribute checking on the DB_File,
142 # ifndef DB_VERSION_MAJOR
145 # define dNOOP extern int Perl___notused
147 /* Ditto for dXSARGS. */
151 I32 ax = mark - PL_stack_base + 1; \
152 I32 items = sp - mark
156 /* avoid -Wall; DB_File xsubs never make use of `ix' setup for ALIASes */
158 # define dXSI32 dNOOP
160 #endif /* Perl >= 5.7 */
167 # define Trace(x) printf x
173 #define DBT_clear(x) Zero(&x, 1, DBT) ;
175 #ifdef DB_VERSION_MAJOR
177 #if DB_VERSION_MAJOR == 2
178 # define BERKELEY_DB_1_OR_2
181 #if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)
182 # define AT_LEAST_DB_3_2
185 /* map version 2 features & constants onto their version 1 equivalent */
190 #define DB_Prefix_t size_t
195 #define DB_Hash_t u_int32_t
197 /* DBTYPE stays the same */
198 /* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
199 #if DB_VERSION_MAJOR == 2
200 typedef DB_INFO INFO ;
201 #else /* DB_VERSION_MAJOR > 2 */
202 # define DB_FIXEDLEN (0x8000)
203 #endif /* DB_VERSION_MAJOR == 2 */
205 /* version 2 has db_recno_t in place of recno_t */
206 typedef db_recno_t recno_t;
209 #define R_CURSOR DB_SET_RANGE
210 #define R_FIRST DB_FIRST
211 #define R_IAFTER DB_AFTER
212 #define R_IBEFORE DB_BEFORE
213 #define R_LAST DB_LAST
214 #define R_NEXT DB_NEXT
215 #define R_NOOVERWRITE DB_NOOVERWRITE
216 #define R_PREV DB_PREV
218 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
219 # define R_SETCURSOR 0x800000
221 # define R_SETCURSOR (-100)
224 #define R_RECNOSYNC 0
225 #define R_FIXEDLEN DB_FIXEDLEN
229 #define db_HA_hash h_hash
230 #define db_HA_ffactor h_ffactor
231 #define db_HA_nelem h_nelem
232 #define db_HA_bsize db_pagesize
233 #define db_HA_cachesize db_cachesize
234 #define db_HA_lorder db_lorder
236 #define db_BT_compare bt_compare
237 #define db_BT_prefix bt_prefix
238 #define db_BT_flags flags
239 #define db_BT_psize db_pagesize
240 #define db_BT_cachesize db_cachesize
241 #define db_BT_lorder db_lorder
242 #define db_BT_maxkeypage
243 #define db_BT_minkeypage
246 #define db_RE_reclen re_len
247 #define db_RE_flags flags
248 #define db_RE_bval re_pad
249 #define db_RE_bfname re_source
250 #define db_RE_psize db_pagesize
251 #define db_RE_cachesize db_cachesize
252 #define db_RE_lorder db_lorder
256 #define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
259 #define DBT_flags(x) x.flags = 0
260 #define DB_flags(x, v) x |= v
262 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
263 # define flagSet(flags, bitmask) ((flags) & (bitmask))
265 # define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (bitmask))
268 #else /* db version 1.x */
270 #define BERKELEY_DB_1
271 #define BERKELEY_DB_1_OR_2
284 # define DB_Prefix_t mDB_Prefix_t
291 # define DB_Hash_t mDB_Hash_t
294 #define db_HA_hash hash.hash
295 #define db_HA_ffactor hash.ffactor
296 #define db_HA_nelem hash.nelem
297 #define db_HA_bsize hash.bsize
298 #define db_HA_cachesize hash.cachesize
299 #define db_HA_lorder hash.lorder
301 #define db_BT_compare btree.compare
302 #define db_BT_prefix btree.prefix
303 #define db_BT_flags btree.flags
304 #define db_BT_psize btree.psize
305 #define db_BT_cachesize btree.cachesize
306 #define db_BT_lorder btree.lorder
307 #define db_BT_maxkeypage btree.maxkeypage
308 #define db_BT_minkeypage btree.minkeypage
310 #define db_RE_reclen recno.reclen
311 #define db_RE_flags recno.flags
312 #define db_RE_bval recno.bval
313 #define db_RE_bfname recno.bfname
314 #define db_RE_psize recno.psize
315 #define db_RE_cachesize recno.cachesize
316 #define db_RE_lorder recno.lorder
320 #define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
322 #define DB_flags(x, v)
323 #define flagSet(flags, bitmask) ((flags) & (bitmask))
325 #endif /* db version 1 */
329 #define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, 0)
330 #define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, 0)
331 #define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, 0)
333 #define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
334 #define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
336 #ifdef DB_VERSION_MAJOR
337 #define db_DESTROY(db) ( db->cursor->c_close(db->cursor),\
338 (db->dbp->close)(db->dbp, 0) )
339 #define db_close(db) ((db->dbp)->close)(db->dbp, 0)
340 #define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \
341 ? ((db->cursor)->c_del)(db->cursor, 0) \
342 : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
344 #else /* ! DB_VERSION_MAJOR */
346 #define db_DESTROY(db) ((db->dbp)->close)(db->dbp)
347 #define db_close(db) ((db->dbp)->close)(db->dbp)
348 #define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
349 #define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
351 #endif /* ! DB_VERSION_MAJOR */
354 #define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
363 #ifdef BERKELEY_DB_1_OR_2
366 #ifdef DB_VERSION_MAJOR
369 SV * filter_fetch_key ;
370 SV * filter_store_key ;
371 SV * filter_fetch_value ;
372 SV * filter_store_value ;
377 typedef DB_File_type * DB_File ;
380 #define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
382 #define OutputValue(arg, name) \
383 { if (RETVAL == 0) { \
384 my_sv_setpvn(arg, name.data, name.size) ; \
385 DBM_ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
389 #define OutputKey(arg, name) \
392 if (db->type != DB_RECNO) { \
393 my_sv_setpvn(arg, name.data, name.size); \
396 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
397 DBM_ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \
401 #define my_SvUV32(sv) ((u_int32_t)SvUV(sv))
404 extern void __getBerkeleyDBInfo(void);
407 /* Internal Global Data */
409 #define MY_CXT_KEY "DB_File::_guts" XS_VERSION
420 #define Value (MY_CXT.x_Value)
421 #define zero (MY_CXT.x_zero)
422 #define CurrentDB (MY_CXT.x_CurrentDB)
423 #define empty (MY_CXT.x_empty)
425 #ifdef DB_VERSION_MAJOR
429 db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
431 db_put(db, key, value, flags)
440 if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) {
444 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
445 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0)
447 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0)
451 memset(&l_key, 0, sizeof(l_key));
452 l_key.data = key.data;
453 l_key.size = key.size;
454 memset(&l_value, 0, sizeof(l_value));
455 l_value.data = value.data;
456 l_value.size = value.size;
458 if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) {
459 (void)temp_cursor->c_close(temp_cursor);
463 status = temp_cursor->c_put(temp_cursor, &key, &value, flags);
464 (void)temp_cursor->c_close(temp_cursor);
470 if (flagSet(flags, R_CURSOR)) {
471 return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT);
474 if (flagSet(flags, R_SETCURSOR)) {
475 if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0)
477 return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE);
481 return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
485 #endif /* DB_VERSION_MAJOR */
489 #ifdef AT_LEAST_DB_3_2
492 btree_compare(DB * db, const DBT *key1, const DBT *key2)
494 btree_compare(db, key1, key2)
498 #endif /* CAN_PROTOTYPE */
500 #else /* Berkeley DB < 3.2 */
503 btree_compare(const DBT *key1, const DBT *key2)
505 btree_compare(key1, key2)
518 void * data1, * data2 ;
522 data1 = (char *) key1->data ;
523 data2 = (char *) key2->data ;
526 /* As newSVpv will assume that the data pointer is a null terminated C
527 string if the size parameter is 0, make sure that data points to an
528 empty string if the length is 0
541 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
542 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
545 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
550 croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
562 #ifdef AT_LEAST_DB_3_2
565 btree_prefix(DB * db, const DBT *key1, const DBT *key2)
567 btree_prefix(db, key1, key2)
573 #else /* Berkeley DB < 3.2 */
576 btree_prefix(const DBT *key1, const DBT *key2)
578 btree_prefix(key1, key2)
590 char * data1, * data2 ;
594 data1 = (char *) key1->data ;
595 data2 = (char *) key2->data ;
598 /* As newSVpv will assume that the data pointer is a null terminated C
599 string if the size parameter is 0, make sure that data points to an
600 empty string if the length is 0
613 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
614 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
617 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
622 croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
635 # define HASH_CB_SIZE_TYPE size_t
637 # define HASH_CB_SIZE_TYPE u_int32_t
641 #ifdef AT_LEAST_DB_3_2
644 hash_cb(DB * db, const void *data, u_int32_t size)
646 hash_cb(db, data, size)
649 HASH_CB_SIZE_TYPE size ;
652 #else /* Berkeley DB < 3.2 */
655 hash_cb(const void *data, HASH_CB_SIZE_TYPE size)
659 HASH_CB_SIZE_TYPE size ;
677 /* DGH - Next two lines added to fix corrupted stack problem */
683 XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
686 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
691 croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
703 #if defined(TRACE) && defined(BERKELEY_DB_1_OR_2)
707 PrintHash(INFO *hash)
713 printf ("HASH Info\n") ;
714 printf (" hash = %s\n",
715 (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
716 printf (" bsize = %d\n", hash->db_HA_bsize) ;
717 printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
718 printf (" nelem = %d\n", hash->db_HA_nelem) ;
719 printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
720 printf (" lorder = %d\n", hash->db_HA_lorder) ;
726 PrintRecno(INFO *recno)
732 printf ("RECNO Info\n") ;
733 printf (" flags = %d\n", recno->db_RE_flags) ;
734 printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
735 printf (" psize = %d\n", recno->db_RE_psize) ;
736 printf (" lorder = %d\n", recno->db_RE_lorder) ;
737 printf (" reclen = %ul\n", (unsigned long)recno->db_RE_reclen) ;
738 printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
739 printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
744 PrintBtree(INFO *btree)
750 printf ("BTREE Info\n") ;
751 printf (" compare = %s\n",
752 (btree->db_BT_compare ? "redefined" : "default")) ;
753 printf (" prefix = %s\n",
754 (btree->db_BT_prefix ? "redefined" : "default")) ;
755 printf (" flags = %d\n", btree->db_BT_flags) ;
756 printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
757 printf (" psize = %d\n", btree->db_BT_psize) ;
758 #ifndef DB_VERSION_MAJOR
759 printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
760 printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
762 printf (" lorder = %d\n", btree->db_BT_lorder) ;
767 #define PrintRecno(recno)
768 #define PrintHash(hash)
769 #define PrintBtree(btree)
776 GetArrayLength(pTHX_ DB_File db)
788 RETVAL = do_SEQ(db, key, value, R_LAST) ;
790 RETVAL = *(I32 *)key.data ;
791 else /* No key means empty file */
794 return ((I32)RETVAL) ;
799 GetRecnoKey(pTHX_ DB_File db, I32 value)
801 GetRecnoKey(db, value)
807 /* Get the length of the array */
808 I32 length = GetArrayLength(aTHX_ db) ;
810 /* check for attempt to write before start of array */
811 if (length + value + 1 <= 0)
812 croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
814 value = length + value + 1 ;
825 ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
827 ParseOpenInfo(isHASH, name, flags, mode, sv)
836 #ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
840 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
841 void * openinfo = NULL ;
842 INFO * info = &RETVAL->info ;
846 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
847 Zero(RETVAL, 1, DB_File_type) ;
849 /* Default to HASH */
850 RETVAL->filtering = 0 ;
851 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
852 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
853 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
854 RETVAL->type = DB_HASH ;
856 /* DGH - Next line added to avoid SEGV on existing hash DB */
859 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
860 RETVAL->in_memory = (name == NULL) ;
865 croak ("type parameter is not a reference") ;
867 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
868 if (svp && SvOK(*svp))
869 action = (HV*) SvRV(*svp) ;
871 croak("internal error") ;
873 if (sv_isa(sv, "DB_File::HASHINFO"))
877 croak("DB_File can only tie an associative array to a DB_HASH database") ;
879 RETVAL->type = DB_HASH ;
880 openinfo = (void*)info ;
882 svp = hv_fetch(action, "hash", 4, FALSE);
884 if (svp && SvOK(*svp))
886 info->db_HA_hash = hash_cb ;
887 RETVAL->hash = newSVsv(*svp) ;
890 info->db_HA_hash = NULL ;
892 svp = hv_fetch(action, "ffactor", 7, FALSE);
893 info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
895 svp = hv_fetch(action, "nelem", 5, FALSE);
896 info->db_HA_nelem = svp ? SvIV(*svp) : 0;
898 svp = hv_fetch(action, "bsize", 5, FALSE);
899 info->db_HA_bsize = svp ? SvIV(*svp) : 0;
901 svp = hv_fetch(action, "cachesize", 9, FALSE);
902 info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
904 svp = hv_fetch(action, "lorder", 6, FALSE);
905 info->db_HA_lorder = svp ? SvIV(*svp) : 0;
909 else if (sv_isa(sv, "DB_File::BTREEINFO"))
912 croak("DB_File can only tie an associative array to a DB_BTREE database");
914 RETVAL->type = DB_BTREE ;
915 openinfo = (void*)info ;
917 svp = hv_fetch(action, "compare", 7, FALSE);
918 if (svp && SvOK(*svp))
920 info->db_BT_compare = btree_compare ;
921 RETVAL->compare = newSVsv(*svp) ;
924 info->db_BT_compare = NULL ;
926 svp = hv_fetch(action, "prefix", 6, FALSE);
927 if (svp && SvOK(*svp))
929 info->db_BT_prefix = btree_prefix ;
930 RETVAL->prefix = newSVsv(*svp) ;
933 info->db_BT_prefix = NULL ;
935 svp = hv_fetch(action, "flags", 5, FALSE);
936 info->db_BT_flags = svp ? SvIV(*svp) : 0;
938 svp = hv_fetch(action, "cachesize", 9, FALSE);
939 info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
941 #ifndef DB_VERSION_MAJOR
942 svp = hv_fetch(action, "minkeypage", 10, FALSE);
943 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
945 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
946 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
949 svp = hv_fetch(action, "psize", 5, FALSE);
950 info->db_BT_psize = svp ? SvIV(*svp) : 0;
952 svp = hv_fetch(action, "lorder", 6, FALSE);
953 info->db_BT_lorder = svp ? SvIV(*svp) : 0;
958 else if (sv_isa(sv, "DB_File::RECNOINFO"))
961 croak("DB_File can only tie an array to a DB_RECNO database");
963 RETVAL->type = DB_RECNO ;
964 openinfo = (void *)info ;
966 info->db_RE_flags = 0 ;
968 svp = hv_fetch(action, "flags", 5, FALSE);
969 info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
971 svp = hv_fetch(action, "reclen", 6, FALSE);
972 info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
974 svp = hv_fetch(action, "cachesize", 9, FALSE);
975 info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
977 svp = hv_fetch(action, "psize", 5, FALSE);
978 info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
980 svp = hv_fetch(action, "lorder", 6, FALSE);
981 info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
983 #ifdef DB_VERSION_MAJOR
984 info->re_source = name ;
987 svp = hv_fetch(action, "bfname", 6, FALSE);
988 if (svp && SvOK(*svp)) {
989 char * ptr = SvPV(*svp,n_a) ;
990 #ifdef DB_VERSION_MAJOR
991 name = (char*) n_a ? ptr : NULL ;
993 info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
997 #ifdef DB_VERSION_MAJOR
1000 info->db_RE_bfname = NULL ;
1003 svp = hv_fetch(action, "bval", 4, FALSE);
1004 #ifdef DB_VERSION_MAJOR
1005 if (svp && SvOK(*svp))
1009 value = (int)*SvPV(*svp, n_a) ;
1011 value = SvIV(*svp) ;
1013 if (info->flags & DB_FIXEDLEN) {
1014 info->re_pad = value ;
1015 info->flags |= DB_PAD ;
1018 info->re_delim = value ;
1019 info->flags |= DB_DELIMITER ;
1024 if (svp && SvOK(*svp))
1027 info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
1029 info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
1030 DB_flags(info->flags, DB_DELIMITER) ;
1035 if (info->db_RE_flags & R_FIXEDLEN)
1036 info->db_RE_bval = (u_char) ' ' ;
1038 info->db_RE_bval = (u_char) '\n' ;
1039 DB_flags(info->flags, DB_DELIMITER) ;
1044 info->flags |= DB_RENUMBER ;
1050 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1054 /* OS2 Specific Code */
1058 #endif /* __EMX__ */
1061 #ifdef DB_VERSION_MAJOR
1067 /* Map 1.x flags to 2.x flags */
1068 if ((flags & O_CREAT) == O_CREAT)
1069 Flags |= DB_CREATE ;
1072 if (flags == O_RDONLY)
1074 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1076 Flags |= DB_RDONLY ;
1079 if ((flags & O_TRUNC) == O_TRUNC)
1080 Flags |= DB_TRUNCATE ;
1083 status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
1085 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
1086 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
1088 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1093 RETVAL->dbp = NULL ;
1098 #if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
1099 RETVAL->dbp = __db185_open(name, flags, mode, RETVAL->type, openinfo) ;
1101 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
1102 #endif /* DB_LIBRARY_COMPATIBILITY_API */
1108 #else /* Berkeley DB Version > 2 */
1112 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
1118 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
1119 Zero(RETVAL, 1, DB_File_type) ;
1121 /* Default to HASH */
1122 RETVAL->filtering = 0 ;
1123 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
1124 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
1125 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
1126 RETVAL->type = DB_HASH ;
1128 /* DGH - Next line added to avoid SEGV on existing hash DB */
1131 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
1132 RETVAL->in_memory = (name == NULL) ;
1134 status = db_create(&RETVAL->dbp, NULL,0) ;
1135 /* printf("db_create returned %d %s\n", status, db_strerror(status)) ; */
1137 RETVAL->dbp = NULL ;
1145 croak ("type parameter is not a reference") ;
1147 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
1148 if (svp && SvOK(*svp))
1149 action = (HV*) SvRV(*svp) ;
1151 croak("internal error") ;
1153 if (sv_isa(sv, "DB_File::HASHINFO"))
1157 croak("DB_File can only tie an associative array to a DB_HASH database") ;
1159 RETVAL->type = DB_HASH ;
1161 svp = hv_fetch(action, "hash", 4, FALSE);
1163 if (svp && SvOK(*svp))
1165 (void)dbp->set_h_hash(dbp, hash_cb) ;
1166 RETVAL->hash = newSVsv(*svp) ;
1169 svp = hv_fetch(action, "ffactor", 7, FALSE);
1171 (void)dbp->set_h_ffactor(dbp, my_SvUV32(*svp)) ;
1173 svp = hv_fetch(action, "nelem", 5, FALSE);
1175 (void)dbp->set_h_nelem(dbp, my_SvUV32(*svp)) ;
1177 svp = hv_fetch(action, "bsize", 5, FALSE);
1179 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp));
1181 svp = hv_fetch(action, "cachesize", 9, FALSE);
1183 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1185 svp = hv_fetch(action, "lorder", 6, FALSE);
1187 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1191 else if (sv_isa(sv, "DB_File::BTREEINFO"))
1194 croak("DB_File can only tie an associative array to a DB_BTREE database");
1196 RETVAL->type = DB_BTREE ;
1198 svp = hv_fetch(action, "compare", 7, FALSE);
1199 if (svp && SvOK(*svp))
1201 (void)dbp->set_bt_compare(dbp, btree_compare) ;
1202 RETVAL->compare = newSVsv(*svp) ;
1205 svp = hv_fetch(action, "prefix", 6, FALSE);
1206 if (svp && SvOK(*svp))
1208 (void)dbp->set_bt_prefix(dbp, btree_prefix) ;
1209 RETVAL->prefix = newSVsv(*svp) ;
1212 svp = hv_fetch(action, "flags", 5, FALSE);
1214 (void)dbp->set_flags(dbp, my_SvUV32(*svp)) ;
1216 svp = hv_fetch(action, "cachesize", 9, FALSE);
1218 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1220 svp = hv_fetch(action, "psize", 5, FALSE);
1222 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
1224 svp = hv_fetch(action, "lorder", 6, FALSE);
1226 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1231 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1236 croak("DB_File can only tie an array to a DB_RECNO database");
1238 RETVAL->type = DB_RECNO ;
1240 svp = hv_fetch(action, "flags", 5, FALSE);
1242 int flags = SvIV(*svp) ;
1243 /* remove FIXDLEN, if present */
1244 if (flags & DB_FIXEDLEN) {
1246 flags &= ~DB_FIXEDLEN ;
1250 svp = hv_fetch(action, "cachesize", 9, FALSE);
1252 status = dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1255 svp = hv_fetch(action, "psize", 5, FALSE);
1257 status = dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
1260 svp = hv_fetch(action, "lorder", 6, FALSE);
1262 status = dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1265 svp = hv_fetch(action, "bval", 4, FALSE);
1266 if (svp && SvOK(*svp))
1270 value = (int)*SvPV(*svp, n_a) ;
1272 value = (int)SvIV(*svp) ;
1275 status = dbp->set_re_pad(dbp, value) ;
1278 status = dbp->set_re_delim(dbp, value) ;
1284 svp = hv_fetch(action, "reclen", 6, FALSE);
1286 u_int32_t len = my_SvUV32(*svp) ;
1287 status = dbp->set_re_len(dbp, len) ;
1292 status = dbp->set_re_source(dbp, name) ;
1296 svp = hv_fetch(action, "bfname", 6, FALSE);
1297 if (svp && SvOK(*svp)) {
1298 char * ptr = SvPV(*svp,n_a) ;
1299 name = (char*) n_a ? ptr : NULL ;
1305 status = dbp->set_flags(dbp, (u_int32_t)DB_RENUMBER) ;
1308 (void)dbp->set_flags(dbp, (u_int32_t)flags) ;
1313 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1317 u_int32_t Flags = 0 ;
1320 /* Map 1.x flags to 3.x flags */
1321 if ((flags & O_CREAT) == O_CREAT)
1322 Flags |= DB_CREATE ;
1325 if (flags == O_RDONLY)
1327 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1329 Flags |= DB_RDONLY ;
1332 if ((flags & O_TRUNC) == O_TRUNC)
1333 Flags |= DB_TRUNCATE ;
1336 status = (RETVAL->dbp->open)(RETVAL->dbp, name, NULL, RETVAL->type,
1338 /* printf("open returned %d %s\n", status, db_strerror(status)) ; */
1341 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1343 /* printf("cursor returned %d %s\n", status, db_strerror(status)) ; */
1346 RETVAL->dbp = NULL ;
1352 #endif /* Berkeley DB Version > 2 */
1354 } /* ParseOpenInfo */
1357 #include "constants.h"
1359 MODULE = DB_File PACKAGE = DB_File PREFIX = db_
1361 INCLUDE: constants.xs
1366 __getBerkeleyDBInfo() ;
1369 empty.data = &zero ;
1370 empty.size = sizeof(recno_t) ;
1376 db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
1383 char * name = (char *) NULL ;
1384 SV * sv = (SV *) NULL ;
1387 if (items >= 3 && SvOK(ST(2)))
1388 name = (char*) SvPV(ST(2), n_a) ;
1393 RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
1394 if (RETVAL->dbp == NULL)
1409 SvREFCNT_dec(db->hash) ;
1411 SvREFCNT_dec(db->compare) ;
1413 SvREFCNT_dec(db->prefix) ;
1414 if (db->filter_fetch_key)
1415 SvREFCNT_dec(db->filter_fetch_key) ;
1416 if (db->filter_store_key)
1417 SvREFCNT_dec(db->filter_store_key) ;
1418 if (db->filter_fetch_value)
1419 SvREFCNT_dec(db->filter_fetch_value) ;
1420 if (db->filter_store_value)
1421 SvREFCNT_dec(db->filter_store_value) ;
1423 #ifdef DB_VERSION_MAJOR
1430 db_DELETE(db, key, flags=0)
1452 RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
1458 db_FETCH(db, key, flags=0)
1471 /* RETVAL = ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) ; */
1472 RETVAL = db_get(db, key, value, flags) ;
1473 ST(0) = sv_newmortal();
1474 OutputValue(ST(0), value)
1478 db_STORE(db, key, value, flags=0)
1503 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1504 ST(0) = sv_newmortal();
1505 OutputKey(ST(0), key) ;
1511 DBTKEY key = NO_INIT
1522 RETVAL = do_SEQ(db, key, value, R_NEXT) ;
1523 ST(0) = sv_newmortal();
1524 OutputKey(ST(0), key) ;
1528 # These would be nice for RECNO
1548 #ifdef DB_VERSION_MAJOR
1549 /* get the first value */
1550 RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
1555 for (i = items-1 ; i > 0 ; --i)
1557 value.data = SvPV(ST(i), n_a) ;
1561 key.size = sizeof(int) ;
1562 #ifdef DB_VERSION_MAJOR
1563 RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
1565 RETVAL = (db->dbp->put)(db->dbp, &key, &value, R_IBEFORE) ;
1591 /* First get the final value */
1592 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1593 ST(0) = sv_newmortal();
1597 /* the call to del will trash value, so take a copy now */
1598 OutputValue(ST(0), value) ;
1599 RETVAL = db_del(db, key, R_CURSOR) ;
1601 sv_setsv(ST(0), &PL_sv_undef);
1621 /* get the first value */
1622 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1623 ST(0) = sv_newmortal();
1627 /* the call to del will trash value, so take a copy now */
1628 OutputValue(ST(0), value) ;
1629 RETVAL = db_del(db, key, R_CURSOR) ;
1631 sv_setsv (ST(0), &PL_sv_undef) ;
1654 /* Set the Cursor to the Last element */
1655 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1656 #ifndef DB_VERSION_MAJOR
1661 keyval = *(int*)key.data ;
1664 for (i = 1 ; i < items ; ++i)
1666 value.data = SvPV(ST(i), n_a) ;
1669 key.data = &keyval ;
1670 key.size = sizeof(int) ;
1671 RETVAL = (Db->put)(Db, TXN &key, &value, 0) ;
1685 ALIAS: FETCHSIZE = 1
1688 RETVAL = GetArrayLength(aTHX_ db) ;
1694 # Now provide an interface to the rest of the DB functionality
1698 db_del(db, key, flags=0)
1706 RETVAL = db_del(db, key, flags) ;
1707 #ifdef DB_VERSION_MAJOR
1710 else if (RETVAL == DB_NOTFOUND)
1718 db_get(db, key, value, flags=0)
1728 RETVAL = db_get(db, key, value, flags) ;
1729 #ifdef DB_VERSION_MAJOR
1732 else if (RETVAL == DB_NOTFOUND)
1740 db_put(db, key, value, flags=0)
1749 RETVAL = db_put(db, key, value, flags) ;
1750 #ifdef DB_VERSION_MAJOR
1753 else if (RETVAL == DB_KEYEXIST)
1758 key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
1767 #ifdef DB_VERSION_MAJOR
1771 status = (db->in_memory
1773 : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
1778 RETVAL = (db->in_memory
1780 : ((db->dbp)->fd)(db->dbp) ) ;
1786 db_sync(db, flags=0)
1793 RETVAL = db_sync(db, flags) ;
1794 #ifdef DB_VERSION_MAJOR
1803 db_seq(db, key, value, flags)
1813 RETVAL = db_seq(db, key, value, flags);
1814 #ifdef DB_VERSION_MAJOR
1817 else if (RETVAL == DB_NOTFOUND)
1826 filter_fetch_key(db, code)
1829 SV * RETVAL = &PL_sv_undef ;
1831 DBM_setFilter(db->filter_fetch_key, code) ;
1834 filter_store_key(db, code)
1837 SV * RETVAL = &PL_sv_undef ;
1839 DBM_setFilter(db->filter_store_key, code) ;
1842 filter_fetch_value(db, code)
1845 SV * RETVAL = &PL_sv_undef ;
1847 DBM_setFilter(db->filter_fetch_value, code) ;
1850 filter_store_value(db, code)
1853 SV * RETVAL = &PL_sv_undef ;
1855 DBM_setFilter(db->filter_store_value, code) ;