3 DB_File.xs -- Perl 5 interface to Berkeley DB
5 Written by Paul Marquess <pmqs@cpan.org>
7 All comments/suggestions/problems are welcome
9 Copyright (c) 1995-2020 Paul Marquess. All rights reserved.
10 This program is free software; you can redistribute it and/or
11 modify it under the same terms as Perl itself.
15 0.2 - No longer bombs out if dbopen returns an error.
16 0.3 - Added some support for multiple btree compares
17 1.0 - Complete support for multiple callbacks added.
18 Fixed a problem with pushing a value onto an empty list.
19 1.01 - Fixed a SunOS core dump problem.
20 The return value from TIEHASH wasn't set to NULL when
21 dbopen returned an error.
22 1.02 - Use ALIAS to define TIEARRAY.
23 Removed some redundant commented code.
24 Merged OS2 code into the main distribution.
25 Allow negative subscripts with RECNO interface.
26 Changed the default flags to O_CREAT|O_RDWR
28 1.04 - fixed a couple of bugs in hash_cb. Patches supplied by
29 Dave Hammen, hammen@gothamcity.jsc.nasa.gov
30 1.05 - Added logic to allow prefix & hash types to be specified via
32 1.06 - Minor namespace cleanup: Localized PrintBtree.
33 1.07 - Fixed bug with RECNO, where bval wasn't defaulting to "\n".
34 1.08 - No change to DB_File.xs
35 1.09 - Default mode for dbopen changed to 0666
36 1.10 - Fixed fd method so that it still returns -1 for
37 in-memory files when db 1.86 is used.
38 1.11 - No change to DB_File.xs
39 1.12 - No change to DB_File.xs
40 1.13 - Tidied up a few casts.
41 1.14 - Made it illegal to tie an associative array to a RECNO
42 database and an ordinary array to a HASH or BTREE database.
43 1.50 - Make work with both DB 1.x or DB 2.x
44 1.51 - Fixed a bug in mapping 1.x O_RDONLY flag to 2.x DB_RDONLY equivalent
45 1.52 - Patch from Gisle Aas <gisle@aas.no> to suppress "use of
46 undefined value" warning with db_get and db_seq.
47 1.53 - Added DB_RENUMBER to flags for recno.
48 1.54 - Fixed bug in the fd method
49 1.55 - Fix for AIX from Jarkko Hietaniemi
50 1.56 - No change to DB_File.xs
51 1.57 - added the #undef op to allow building with Threads support.
52 1.58 - Fixed a problem with the use of sv_setpvn. When the
53 size is specified as 0, it does a strlen on the data.
54 This was ok for DB 1.x, but isn't for DB 2.x.
55 1.59 - No change to DB_File.xs
56 1.60 - Some code tidy up
57 1.61 - added flagSet macro for DB 2.5.x
58 fixed typo in O_RDONLY test.
59 1.62 - No change to DB_File.xs
60 1.63 - Fix to alllow DB 2.6.x to build.
61 1.64 - Tidied up the 1.x to 2.x flags mapping code.
62 Added a patch from Mark Kettenis <kettenis@wins.uva.nl>
63 to fix a flag mapping problem with O_RDONLY on the Hurd
64 1.65 - Fixed a bug in the PUSH logic.
65 Added BOOT check that using 2.3.4 or greater
66 1.66 - Added DBM filter code
67 1.67 - Backed off the use of newSVpvn.
68 Fixed DBM Filter code for Perl 5.004.
69 Fixed a small memory leak in the filter code.
70 1.68 - fixed backward compatibility bug with R_IAFTER & R_IBEFORE
71 merged in the 5.005_58 changes
72 1.69 - fixed a bug in push -- DB_APPEND wasn't working properly.
73 Fixed the R_SETCURSOR bug introduced in 1.68
74 Added a new Perl variable $DB_File::db_ver
75 1.70 - Initialise $DB_File::db_ver and $DB_File::db_version with
76 GV_ADD|GV_ADDMULT -- bug spotted by Nick Ing-Simmons.
77 Added a BOOT check to test for equivalent versions of db.h &
79 1.71 - Support for Berkeley DB version 3.
80 Support for Berkeley DB 2/3's backward compatibility mode.
82 1.72 - No change to DB_File.xs
83 1.73 - No change to DB_File.xs
84 1.74 - A call to open needed parenthesised to stop it clashing
86 Added Perl core patches 7703 & 7801.
87 1.75 - Fixed Perl core patch 7703.
88 Added support to allow DB_File to be built with
89 Berkeley DB 3.2 -- btree_compare, btree_prefix and hash_cb
91 1.76 - No change to DB_File.xs
92 1.77 - Tidied up a few types used in calling newSVpvn.
93 1.78 - Core patch 10335, 10372, 10534, 10549, 11051 included.
94 1.79 - NEXTKEY ignores the input key.
96 1.800 - Moved backward compatibility code into ppport.h.
97 Use the new constants code.
98 1.801 - No change to DB_File.xs
99 1.802 - No change to DB_File.xs
100 1.803 - FETCH, STORE & DELETE don't map the flags parameter
101 into the equivalent Berkeley DB function anymore.
103 1.805 - recursion detection added to the callbacks
104 Support for 4.1.X added.
105 Filter code can now cope with read-only $_
106 1.806 - recursion detection beefed up.
108 1.808 - leak fixed in ParseOpenInfo
115 1.814 - C++ casting fixes
119 #define PERL_NO_GET_CONTEXT
128 int DB_File___unused() { return 0; }
130 /* Mention DB_VERSION_MAJOR_CFG, DB_VERSION_MINOR_CFG, and
131 DB_VERSION_PATCH_CFG here so that Configure pulls them all in. */
133 /* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
134 * shortly #included by the <db.h>) __attribute__ to the possibly
135 * already defined __attribute__, for example by GNUC or by Perl. */
137 /* #if DB_VERSION_MAJOR_CFG < 2 */
138 #ifndef DB_VERSION_MAJOR
139 # undef __attribute__
146 /* Uncomment one of the lines below */
147 /* See the section "At least one secondary cursor must be specified to DB->join"
148 in the README file for the circumstances where you need to uncomment one
149 of the two lines below.
152 /* #define time_t __time64_t */
153 /* #define time_t __time32_t */
158 #ifndef PERL_UNUSED_ARG
159 # define PERL_UNUSED_ARG(x) ((void)x)
162 /* Wall starts with 5.7.x */
164 #if PERL_REVISION > 5 || (PERL_REVISION == 5 && PERL_VERSION >= 7)
166 /* Since we dropped the gccish definition of __attribute__ we will want
167 * to redefine dNOOP, however (so that dTHX continues to work). Yes,
168 * all this means that we can't do attribute checking on the DB_File,
170 # ifndef DB_VERSION_MAJOR
174 # define dNOOP (void)0
176 # define dNOOP extern int DB_File___notused()
179 /* Ditto for dXSARGS. */
183 I32 ax = mark - PL_stack_base + 1; \
184 I32 items = sp - mark
188 /* avoid -Wall; DB_File xsubs never make use of `ix' setup for ALIASes */
190 # define dXSI32 dNOOP
192 #endif /* Perl >= 5.7 */
199 # define Trace(x) printf x
205 #define DBT_clear(x) Zero(&x, 1, DBT) ;
207 #ifdef DB_VERSION_MAJOR
209 #if DB_VERSION_MAJOR == 2
210 # define BERKELEY_DB_1_OR_2
213 #if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)
214 # define AT_LEAST_DB_3_2
217 #if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 3)
218 # define AT_LEAST_DB_3_3
221 #if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
222 # define AT_LEAST_DB_4_1
225 #if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
226 # define AT_LEAST_DB_4_3
229 #if DB_VERSION_MAJOR >= 6
230 # define AT_LEAST_DB_6_0
233 #ifdef AT_LEAST_DB_3_3
237 /* map version 2 features & constants onto their version 1 equivalent */
242 #define DB_Prefix_t size_t
247 #define DB_Hash_t u_int32_t
249 /* DBTYPE stays the same */
250 /* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
251 #if DB_VERSION_MAJOR == 2
252 typedef DB_INFO INFO ;
253 #else /* DB_VERSION_MAJOR > 2 */
254 # define DB_FIXEDLEN (0x8000)
255 #endif /* DB_VERSION_MAJOR == 2 */
257 /* version 2 has db_recno_t in place of recno_t */
258 typedef db_recno_t recno_t;
261 #define R_CURSOR DB_SET_RANGE
262 #define R_FIRST DB_FIRST
263 #define R_IAFTER DB_AFTER
264 #define R_IBEFORE DB_BEFORE
265 #define R_LAST DB_LAST
266 #define R_NEXT DB_NEXT
267 #define R_NOOVERWRITE DB_NOOVERWRITE
268 #define R_PREV DB_PREV
270 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
271 # define R_SETCURSOR 0x800000
273 # define R_SETCURSOR (DB_OPFLAGS_MASK)
276 #define R_RECNOSYNC 0
277 #define R_FIXEDLEN DB_FIXEDLEN
281 #define db_HA_hash h_hash
282 #define db_HA_ffactor h_ffactor
283 #define db_HA_nelem h_nelem
284 #define db_HA_bsize db_pagesize
285 #define db_HA_cachesize db_cachesize
286 #define db_HA_lorder db_lorder
288 #define db_BT_compare bt_compare
289 #define db_BT_prefix bt_prefix
290 #define db_BT_flags flags
291 #define db_BT_psize db_pagesize
292 #define db_BT_cachesize db_cachesize
293 #define db_BT_lorder db_lorder
294 #define db_BT_maxkeypage
295 #define db_BT_minkeypage
298 #define db_RE_reclen re_len
299 #define db_RE_flags flags
300 #define db_RE_bval re_pad
301 #define db_RE_bfname re_source
302 #define db_RE_psize db_pagesize
303 #define db_RE_cachesize db_cachesize
304 #define db_RE_lorder db_lorder
308 #define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
311 #define DBT_flags(x) x.flags = 0
312 #define DB_flags(x, v) x |= v
314 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
315 # define flagSet(flags, bitmask) ((flags) & (bitmask))
317 # define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (u_int)(bitmask))
320 #else /* db version 1.x */
322 #define BERKELEY_DB_1
323 #define BERKELEY_DB_1_OR_2
336 # define DB_Prefix_t mDB_Prefix_t
343 # define DB_Hash_t mDB_Hash_t
346 #define db_HA_hash hash.hash
347 #define db_HA_ffactor hash.ffactor
348 #define db_HA_nelem hash.nelem
349 #define db_HA_bsize hash.bsize
350 #define db_HA_cachesize hash.cachesize
351 #define db_HA_lorder hash.lorder
353 #define db_BT_compare btree.compare
354 #define db_BT_prefix btree.prefix
355 #define db_BT_flags btree.flags
356 #define db_BT_psize btree.psize
357 #define db_BT_cachesize btree.cachesize
358 #define db_BT_lorder btree.lorder
359 #define db_BT_maxkeypage btree.maxkeypage
360 #define db_BT_minkeypage btree.minkeypage
362 #define db_RE_reclen recno.reclen
363 #define db_RE_flags recno.flags
364 #define db_RE_bval recno.bval
365 #define db_RE_bfname recno.bfname
366 #define db_RE_psize recno.psize
367 #define db_RE_cachesize recno.cachesize
368 #define db_RE_lorder recno.lorder
372 #define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
374 #define DB_flags(x, v)
375 #define flagSet(flags, bitmask) ((flags) & (bitmask))
377 #endif /* db version 1 */
381 #define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, 0)
382 #define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, 0)
383 #define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, 0)
385 #define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
386 #define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
388 #ifdef DB_VERSION_MAJOR
389 #define db_DESTROY(db) (!db->aborted && ( db->cursor->c_close(db->cursor),\
390 (db->dbp->close)(db->dbp, 0) ))
391 #define db_close(db) ((db->dbp)->close)(db->dbp, 0)
392 #define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \
393 ? ((db->cursor)->c_del)(db->cursor, 0) \
394 : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
396 #else /* ! DB_VERSION_MAJOR */
398 #define db_DESTROY(db) (!db->aborted && ((db->dbp)->close)(db->dbp))
399 #define db_close(db) ((db->dbp)->close)(db->dbp)
400 #define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
401 #define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
403 #endif /* ! DB_VERSION_MAJOR */
406 #define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
419 #ifdef BERKELEY_DB_1_OR_2
422 #ifdef DB_VERSION_MAJOR
425 SV * filter_fetch_key ;
426 SV * filter_store_key ;
427 SV * filter_fetch_value ;
428 SV * filter_store_value ;
433 typedef DB_File_type * DB_File ;
436 #define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (const char *)""), s)
438 #define OutputValue(arg, name) \
439 { if (RETVAL == 0) { \
441 my_sv_setpvn(arg, (const char *)name.data, name.size) ; \
445 DBM_ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
449 #define OutputKey(arg, name) \
453 if (db->type != DB_RECNO) { \
454 my_sv_setpvn(arg, (const char *)name.data, name.size); \
457 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
461 DBM_ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \
465 /* Macro err_close only for use in croak_and_free */
466 #ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
467 # define err_close(r)
469 # define err_close(r) db_close(r)
472 /* Macro croak_and_free only for use in ParseOpenInfo */
473 #define croak_and_free(x) \
476 if (RETVAL->dbp) err_close(RETVAL) ; \
481 #define my_SvUV32(sv) ((u_int32_t)SvUV(sv))
484 extern void __getBerkeleyDBInfo(void);
487 /* Internal Global Data */
489 #define MY_CXT_KEY "DB_File::_guts" XS_VERSION
500 #define Value (MY_CXT.x_Value)
501 #define zero (MY_CXT.x_zero)
502 #define CurrentDB (MY_CXT.x_CurrentDB)
503 #define empty (MY_CXT.x_empty)
505 #define ERR_BUFF "DB_File::Error"
507 #ifdef DB_VERSION_MAJOR
511 db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
513 db_put(db, key, value, flags)
522 if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) {
526 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
527 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0)
529 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0)
533 memset(&l_key, 0, sizeof(l_key));
534 l_key.data = key.data;
535 l_key.size = key.size;
536 memset(&l_value, 0, sizeof(l_value));
537 l_value.data = value.data;
538 l_value.size = value.size;
540 if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) {
541 (void)temp_cursor->c_close(temp_cursor);
545 status = temp_cursor->c_put(temp_cursor, &key, &value, flags);
546 (void)temp_cursor->c_close(temp_cursor);
552 if (flagSet(flags, R_CURSOR)) {
553 return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT);
555 if (flagSet(flags, R_SETCURSOR)) {
556 if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0)
558 return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE);
561 return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
565 #endif /* DB_VERSION_MAJOR */
576 #ifdef AT_LEAST_DB_6_0
578 btree_compare(DB * db, const DBT *key1, const DBT *key2, size_t* locp)
580 btree_compare(db, key1, key2, locp)
585 #endif /* CAN_PROTOTYPE */
587 #else /* Berkeley DB < 6.0 */
588 #ifdef AT_LEAST_DB_3_2
591 btree_compare(DB * db, const DBT *key1, const DBT *key2)
593 btree_compare(db, key1, key2)
597 #endif /* CAN_PROTOTYPE */
599 #else /* Berkeley DB < 3.2 */
602 btree_compare(const DBT *key1, const DBT *key2)
604 btree_compare(key1, key2)
618 void * data1, * data2 ;
622 #ifdef AT_LEAST_DB_3_2
625 #ifdef AT_LEAST_DB_6_0
626 PERL_UNUSED_ARG(locp);
629 if (CurrentDB->in_compare) {
631 croak ("DB_File btree_compare: recursion detected\n") ;
634 data1 = (char *) key1->data ;
635 data2 = (char *) key2->data ;
638 /* As newSVpv will assume that the data pointer is a null terminated C
639 string if the size parameter is 0, make sure that data points to an
640 empty string if the length is 0
651 CurrentDB->in_compare = FALSE;
652 SAVEINT(CurrentDB->in_compare);
653 CurrentDB->in_compare = TRUE;
657 PUSHs(sv_2mortal(newSVpvn((const char*)data1,key1->size)));
658 PUSHs(sv_2mortal(newSVpvn((const char*)data2,key2->size)));
661 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
667 croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
681 #ifdef AT_LEAST_DB_3_2
684 btree_prefix(DB * db, const DBT *key1, const DBT *key2)
686 btree_prefix(db, key1, key2)
692 #else /* Berkeley DB < 3.2 */
695 btree_prefix(const DBT *key1, const DBT *key2)
697 btree_prefix(key1, key2)
709 char * data1, * data2 ;
713 #ifdef AT_LEAST_DB_3_2
717 if (CurrentDB->in_prefix){
719 croak ("DB_File btree_prefix: recursion detected\n") ;
722 data1 = (char *) key1->data ;
723 data2 = (char *) key2->data ;
726 /* As newSVpv will assume that the data pointer is a null terminated C
727 string if the size parameter is 0, make sure that data points to an
728 empty string if the length is 0
739 CurrentDB->in_prefix = FALSE;
740 SAVEINT(CurrentDB->in_prefix);
741 CurrentDB->in_prefix = TRUE;
745 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
746 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
749 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
755 croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
769 # define HASH_CB_SIZE_TYPE size_t
771 # define HASH_CB_SIZE_TYPE u_int32_t
775 #ifdef AT_LEAST_DB_3_2
778 hash_cb(DB * db, const void *data, u_int32_t size)
780 hash_cb(db, data, size)
783 HASH_CB_SIZE_TYPE size ;
786 #else /* Berkeley DB < 3.2 */
789 hash_cb(const void *data, HASH_CB_SIZE_TYPE size)
793 HASH_CB_SIZE_TYPE size ;
806 #ifdef AT_LEAST_DB_3_2
810 if (CurrentDB->in_hash){
812 croak ("DB_File hash callback: recursion detected\n") ;
820 /* DGH - Next two lines added to fix corrupted stack problem */
824 CurrentDB->in_hash = FALSE;
825 SAVEINT(CurrentDB->in_hash);
826 CurrentDB->in_hash = TRUE;
831 XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
834 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
840 croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
855 #ifdef AT_LEAST_DB_4_3
856 db_errcall_cb(const DB_ENV* dbenv, const char * db_errpfx, const char * buffer)
858 db_errcall_cb(const char * db_errpfx, char * buffer)
864 SV * sv = perl_get_sv(ERR_BUFF, FALSE) ;
865 #ifdef AT_LEAST_DB_4_3
866 PERL_UNUSED_ARG(dbenv);
870 sv_setpvf(sv, "%s: %s", db_errpfx, buffer) ;
872 sv_setpv(sv, buffer) ;
877 #if defined(TRACE) && defined(BERKELEY_DB_1_OR_2)
881 PrintHash(INFO *hash)
887 printf ("HASH Info\n") ;
888 printf (" hash = %s\n",
889 (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
890 printf (" bsize = %d\n", hash->db_HA_bsize) ;
891 printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
892 printf (" nelem = %d\n", hash->db_HA_nelem) ;
893 printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
894 printf (" lorder = %d\n", hash->db_HA_lorder) ;
900 PrintRecno(INFO *recno)
906 printf ("RECNO Info\n") ;
907 printf (" flags = %d\n", recno->db_RE_flags) ;
908 printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
909 printf (" psize = %d\n", recno->db_RE_psize) ;
910 printf (" lorder = %d\n", recno->db_RE_lorder) ;
911 printf (" reclen = %lu\n", (unsigned long)recno->db_RE_reclen) ;
912 printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
913 printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
918 PrintBtree(INFO *btree)
924 printf ("BTREE Info\n") ;
925 printf (" compare = %s\n",
926 (btree->db_BT_compare ? "redefined" : "default")) ;
927 printf (" prefix = %s\n",
928 (btree->db_BT_prefix ? "redefined" : "default")) ;
929 printf (" flags = %d\n", btree->db_BT_flags) ;
930 printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
931 printf (" psize = %d\n", btree->db_BT_psize) ;
932 #ifndef DB_VERSION_MAJOR
933 printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
934 printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
936 printf (" lorder = %d\n", btree->db_BT_lorder) ;
941 #define PrintRecno(recno)
942 #define PrintHash(hash)
943 #define PrintBtree(btree)
950 GetArrayLength(pTHX_ DB_File db)
962 RETVAL = do_SEQ(db, key, value, R_LAST) ;
964 RETVAL = *(I32 *)key.data ;
965 else /* No key means empty file */
968 return ((I32)RETVAL) ;
973 GetRecnoKey(pTHX_ DB_File db, I32 value)
975 GetRecnoKey(db, value)
981 /* Get the length of the array */
982 I32 length = GetArrayLength(aTHX_ db) ;
984 /* check for attempt to write before start of array */
985 if (length + value + 1 <= 0) {
987 croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
990 value = length + value + 1 ;
1000 #ifdef CAN_PROTOTYPE
1001 ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
1003 ParseOpenInfo(isHASH, name, flags, mode, sv)
1012 #ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
1016 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
1017 void * openinfo = NULL ;
1018 INFO * info = &RETVAL->info ;
1023 printf("In ParseOpenInfo name=[%s] flags=[%d] mode=[%d] SV NULL=[%d]\n",
1024 name, flags, mode, sv == NULL) ;
1026 Zero(RETVAL, 1, DB_File_type) ;
1028 /* Default to HASH */
1029 RETVAL->filtering = 0 ;
1030 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
1031 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
1032 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
1033 RETVAL->type = DB_HASH ;
1035 /* DGH - Next line added to avoid SEGV on existing hash DB */
1038 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
1039 RETVAL->in_memory = (name == NULL) ;
1044 croak_and_free("type parameter is not a reference") ;
1046 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
1047 if (svp && SvOK(*svp))
1048 action = (HV*) SvRV(*svp) ;
1050 croak_and_free("internal error") ;
1052 if (sv_isa(sv, "DB_File::HASHINFO"))
1056 croak_and_free("DB_File can only tie an associative array to a DB_HASH database") ;
1058 RETVAL->type = DB_HASH ;
1059 openinfo = (void*)info ;
1061 svp = hv_fetch(action, "hash", 4, FALSE);
1063 if (svp && SvOK(*svp))
1065 info->db_HA_hash = hash_cb ;
1066 RETVAL->hash = newSVsv(*svp) ;
1069 info->db_HA_hash = NULL ;
1071 svp = hv_fetch(action, "ffactor", 7, FALSE);
1072 info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
1074 svp = hv_fetch(action, "nelem", 5, FALSE);
1075 info->db_HA_nelem = svp ? SvIV(*svp) : 0;
1077 svp = hv_fetch(action, "bsize", 5, FALSE);
1078 info->db_HA_bsize = svp ? SvIV(*svp) : 0;
1080 svp = hv_fetch(action, "cachesize", 9, FALSE);
1081 info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
1083 svp = hv_fetch(action, "lorder", 6, FALSE);
1084 info->db_HA_lorder = svp ? SvIV(*svp) : 0;
1088 else if (sv_isa(sv, "DB_File::BTREEINFO"))
1091 croak_and_free("DB_File can only tie an associative array to a DB_BTREE database");
1093 RETVAL->type = DB_BTREE ;
1094 openinfo = (void*)info ;
1096 svp = hv_fetch(action, "compare", 7, FALSE);
1097 if (svp && SvOK(*svp))
1099 info->db_BT_compare = btree_compare ;
1100 RETVAL->compare = newSVsv(*svp) ;
1103 info->db_BT_compare = NULL ;
1105 svp = hv_fetch(action, "prefix", 6, FALSE);
1106 if (svp && SvOK(*svp))
1108 info->db_BT_prefix = btree_prefix ;
1109 RETVAL->prefix = newSVsv(*svp) ;
1112 info->db_BT_prefix = NULL ;
1114 svp = hv_fetch(action, "flags", 5, FALSE);
1115 info->db_BT_flags = svp ? SvIV(*svp) : 0;
1117 svp = hv_fetch(action, "cachesize", 9, FALSE);
1118 info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
1120 #ifndef DB_VERSION_MAJOR
1121 svp = hv_fetch(action, "minkeypage", 10, FALSE);
1122 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
1124 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
1125 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
1128 svp = hv_fetch(action, "psize", 5, FALSE);
1129 info->db_BT_psize = svp ? SvIV(*svp) : 0;
1131 svp = hv_fetch(action, "lorder", 6, FALSE);
1132 info->db_BT_lorder = svp ? SvIV(*svp) : 0;
1137 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1140 croak_and_free("DB_File can only tie an array to a DB_RECNO database");
1142 RETVAL->type = DB_RECNO ;
1143 openinfo = (void *)info ;
1145 info->db_RE_flags = 0 ;
1147 svp = hv_fetch(action, "flags", 5, FALSE);
1148 info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
1150 svp = hv_fetch(action, "reclen", 6, FALSE);
1151 info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
1153 svp = hv_fetch(action, "cachesize", 9, FALSE);
1154 info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
1156 svp = hv_fetch(action, "psize", 5, FALSE);
1157 info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
1159 svp = hv_fetch(action, "lorder", 6, FALSE);
1160 info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
1162 #ifdef DB_VERSION_MAJOR
1163 info->re_source = name ;
1166 svp = hv_fetch(action, "bfname", 6, FALSE);
1167 if (svp && SvOK(*svp)) {
1168 char * ptr = SvPV(*svp,n_a) ;
1169 #ifdef DB_VERSION_MAJOR
1170 name = (char*) n_a ? ptr : NULL ;
1172 info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
1176 #ifdef DB_VERSION_MAJOR
1179 info->db_RE_bfname = NULL ;
1182 svp = hv_fetch(action, "bval", 4, FALSE);
1183 #ifdef DB_VERSION_MAJOR
1184 if (svp && SvOK(*svp))
1188 value = (int)*SvPV(*svp, n_a) ;
1190 value = SvIV(*svp) ;
1192 if (info->flags & DB_FIXEDLEN) {
1193 info->re_pad = value ;
1194 info->flags |= DB_PAD ;
1197 info->re_delim = value ;
1198 info->flags |= DB_DELIMITER ;
1203 if (svp && SvOK(*svp))
1206 info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
1208 info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
1209 DB_flags(info->flags, DB_DELIMITER) ;
1214 if (info->db_RE_flags & R_FIXEDLEN)
1215 info->db_RE_bval = (u_char) ' ' ;
1217 info->db_RE_bval = (u_char) '\n' ;
1218 DB_flags(info->flags, DB_DELIMITER) ;
1223 info->flags |= DB_RENUMBER ;
1229 croak_and_free("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1233 /* OS2 Specific Code */
1237 #endif /* __EMX__ */
1240 #ifdef DB_VERSION_MAJOR
1246 /* Map 1.x flags to 2.x flags */
1247 if ((flags & O_CREAT) == O_CREAT)
1248 Flags |= DB_CREATE ;
1251 if (flags == O_RDONLY)
1253 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1255 Flags |= DB_RDONLY ;
1258 if ((flags & O_TRUNC) == O_TRUNC)
1259 Flags |= DB_TRUNCATE ;
1262 status = db_open(name, RETVAL->type, Flags, mode, NULL, (DB_INFO*)openinfo, &RETVAL->dbp) ;
1264 #if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
1265 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
1267 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor, 0) ;
1271 RETVAL->dbp = NULL ;
1275 #if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
1276 RETVAL->dbp = __db185_open(name, flags, mode, RETVAL->type, openinfo) ;
1278 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
1279 #endif /* DB_LIBRARY_COMPATIBILITY_API */
1285 #else /* Berkeley DB Version > 2 */
1289 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
1295 Trace(("In ParseOpenInfo name=[%s] flags=[%d] mode=[%d] SV NULL=[%d]\n",\
1296 name, flags, mode, sv == NULL)) ;
1297 Zero(RETVAL, 1, DB_File_type) ;
1299 /* Default to HASH */
1300 RETVAL->filtering = 0 ;
1301 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
1302 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
1303 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
1304 RETVAL->type = DB_HASH ;
1306 /* DGH - Next line added to avoid SEGV on existing hash DB */
1309 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
1310 RETVAL->in_memory = (name == NULL) ;
1312 status = db_create(&RETVAL->dbp, NULL,0) ;
1313 Trace(("db_create returned %d %s\n", status, db_strerror(status))) ;
1315 RETVAL->dbp = NULL ;
1321 RETVAL->dbp->set_errcall(RETVAL->dbp, db_errcall_cb) ;
1326 croak_and_free("type parameter is not a reference") ;
1328 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
1329 if (svp && SvOK(*svp))
1330 action = (HV*) SvRV(*svp) ;
1332 croak_and_free("internal error") ;
1334 if (sv_isa(sv, "DB_File::HASHINFO"))
1338 croak_and_free("DB_File can only tie an associative array to a DB_HASH database") ;
1340 RETVAL->type = DB_HASH ;
1342 svp = hv_fetch(action, "hash", 4, FALSE);
1344 if (svp && SvOK(*svp))
1346 (void)dbp->set_h_hash(dbp, hash_cb) ;
1347 RETVAL->hash = newSVsv(*svp) ;
1350 svp = hv_fetch(action, "ffactor", 7, FALSE);
1352 (void)dbp->set_h_ffactor(dbp, my_SvUV32(*svp)) ;
1354 svp = hv_fetch(action, "nelem", 5, FALSE);
1356 (void)dbp->set_h_nelem(dbp, my_SvUV32(*svp)) ;
1358 svp = hv_fetch(action, "bsize", 5, FALSE);
1360 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp));
1362 svp = hv_fetch(action, "cachesize", 9, FALSE);
1364 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1366 svp = hv_fetch(action, "lorder", 6, FALSE);
1368 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1372 else if (sv_isa(sv, "DB_File::BTREEINFO"))
1375 croak_and_free("DB_File can only tie an associative array to a DB_BTREE database");
1377 RETVAL->type = DB_BTREE ;
1379 svp = hv_fetch(action, "compare", 7, FALSE);
1380 if (svp && SvOK(*svp))
1382 (void)dbp->set_bt_compare(dbp, btree_compare) ;
1383 RETVAL->compare = newSVsv(*svp) ;
1386 svp = hv_fetch(action, "prefix", 6, FALSE);
1387 if (svp && SvOK(*svp))
1389 (void)dbp->set_bt_prefix(dbp, btree_prefix) ;
1390 RETVAL->prefix = newSVsv(*svp) ;
1393 svp = hv_fetch(action, "flags", 5, FALSE);
1395 (void)dbp->set_flags(dbp, my_SvUV32(*svp)) ;
1397 svp = hv_fetch(action, "cachesize", 9, FALSE);
1399 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1401 svp = hv_fetch(action, "psize", 5, FALSE);
1403 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
1405 svp = hv_fetch(action, "lorder", 6, FALSE);
1407 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1412 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1417 croak_and_free("DB_File can only tie an array to a DB_RECNO database");
1419 RETVAL->type = DB_RECNO ;
1421 svp = hv_fetch(action, "flags", 5, FALSE);
1423 int flags = SvIV(*svp) ;
1424 /* remove FIXDLEN, if present */
1425 if (flags & DB_FIXEDLEN) {
1427 flags &= ~DB_FIXEDLEN ;
1431 svp = hv_fetch(action, "cachesize", 9, FALSE);
1433 status = dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
1436 svp = hv_fetch(action, "psize", 5, FALSE);
1438 status = dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
1441 svp = hv_fetch(action, "lorder", 6, FALSE);
1443 status = dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
1446 svp = hv_fetch(action, "bval", 4, FALSE);
1447 if (svp && SvOK(*svp))
1451 value = (int)*SvPV(*svp, n_a) ;
1453 value = (int)SvIV(*svp) ;
1456 (void)dbp->set_re_pad(dbp, value) ;
1459 (void)dbp->set_re_delim(dbp, value) ;
1465 svp = hv_fetch(action, "reclen", 6, FALSE);
1467 u_int32_t len = my_SvUV32(*svp) ;
1468 (void)dbp->set_re_len(dbp, len) ;
1473 (void)dbp->set_re_source(dbp, name) ;
1477 svp = hv_fetch(action, "bfname", 6, FALSE);
1478 if (svp && SvOK(*svp)) {
1479 char * ptr = SvPV(*svp,n_a) ;
1480 name = (char*) n_a ? ptr : NULL ;
1486 (void)dbp->set_flags(dbp, (u_int32_t)DB_RENUMBER) ;
1489 (void)dbp->set_flags(dbp, (u_int32_t)flags) ;
1494 croak_and_free("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1498 u_int32_t Flags = 0 ;
1501 /* Map 1.x flags to 3.x flags */
1502 if ((flags & O_CREAT) == O_CREAT)
1503 Flags |= DB_CREATE ;
1506 if (flags == O_RDONLY)
1508 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1510 Flags |= DB_RDONLY ;
1513 if ((flags & O_TRUNC) == O_TRUNC)
1514 Flags |= DB_TRUNCATE ;
1517 #ifdef AT_LEAST_DB_4_4
1518 /* need this for recno */
1519 if ((flags & O_TRUNC) == O_TRUNC)
1520 Flags |= DB_CREATE ;
1523 #ifdef AT_LEAST_DB_4_1
1524 status = (RETVAL->dbp->open)(RETVAL->dbp, NULL, name, NULL, RETVAL->type,
1527 status = (RETVAL->dbp->open)(RETVAL->dbp, name, NULL, RETVAL->type,
1530 Trace(("open returned %d %s\n", status, db_strerror(status))) ;
1534 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor, 0) ;
1535 Trace(("cursor returned %d %s\n", status, db_strerror(status))) ;
1540 db_close(RETVAL); /* close **dbp handle to prevent mem.leak */
1541 RETVAL->dbp = NULL ;
1547 #endif /* Berkeley DB Version > 2 */
1549 } /* ParseOpenInfo */
1552 #include "constants.h"
1554 MODULE = DB_File PACKAGE = DB_File PREFIX = db_
1556 INCLUDE: constants.xs
1564 SV * sv_err = perl_get_sv(ERR_BUFF, GV_ADD|GV_ADDMULTI) ;
1568 PERL_UNUSED_VAR(sv_err); /* huh? we just retrieved it... */
1570 __getBerkeleyDBInfo() ;
1573 empty.data = &zero ;
1574 empty.size = sizeof(recno_t) ;
1580 db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
1587 char * name = (char *) NULL ;
1588 SV * sv = (SV *) NULL ;
1590 Trace(("In db_DoTie_\n"));
1592 if (items >= 3 && SvOK(ST(2)))
1593 name = (char*) SvPV(ST(2), n_a) ;
1598 RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
1599 Trace(("db_DoTie_ %p\n", RETVAL));
1600 if (RETVAL->dbp == NULL) {
1615 Trace(("DESTROY %p\n", db));
1617 Trace(("DESTROY %p done\n", db));
1619 SvREFCNT_dec(db->hash) ;
1621 SvREFCNT_dec(db->compare) ;
1623 SvREFCNT_dec(db->prefix) ;
1624 if (db->filter_fetch_key)
1625 SvREFCNT_dec(db->filter_fetch_key) ;
1626 if (db->filter_store_key)
1627 SvREFCNT_dec(db->filter_store_key) ;
1628 if (db->filter_fetch_value)
1629 SvREFCNT_dec(db->filter_fetch_value) ;
1630 if (db->filter_store_value)
1631 SvREFCNT_dec(db->filter_store_value) ;
1633 #ifdef DB_VERSION_MAJOR
1640 db_DELETE(db, key, flags=0)
1663 RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
1669 db_FETCH(db, key, flags=0)
1682 RETVAL = db_get(db, key, value, flags) ;
1683 ST(0) = sv_newmortal();
1684 OutputValue(ST(0), value)
1688 db_STORE(db, key, value, flags=0)
1714 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1715 ST(0) = sv_newmortal();
1716 OutputKey(ST(0), key) ;
1722 DBTKEY key = NO_INIT
1733 RETVAL = do_SEQ(db, key, value, R_NEXT) ;
1734 ST(0) = sv_newmortal();
1735 OutputKey(ST(0), key) ;
1739 # These would be nice for RECNO
1759 #ifdef DB_VERSION_MAJOR
1760 /* get the first value */
1761 RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
1766 for (i = items-1 ; i > 0 ; --i)
1768 DBM_ckFilter(ST(i), filter_store_value, "filter_store_value");
1769 value.data = SvPVbyte(ST(i), n_a) ;
1773 key.size = sizeof(int) ;
1774 #ifdef DB_VERSION_MAJOR
1775 RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
1777 RETVAL = (db->dbp->put)(db->dbp, &key, &value, R_IBEFORE) ;
1803 /* First get the final value */
1804 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1805 ST(0) = sv_newmortal();
1809 /* the call to del will trash value, so take a copy now */
1810 OutputValue(ST(0), value) ;
1811 RETVAL = db_del(db, key, R_CURSOR) ;
1813 sv_setsv(ST(0), &PL_sv_undef);
1833 /* get the first value */
1834 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1835 ST(0) = sv_newmortal();
1839 /* the call to del will trash value, so take a copy now */
1840 OutputValue(ST(0), value) ;
1841 RETVAL = db_del(db, key, R_CURSOR) ;
1843 sv_setsv (ST(0), &PL_sv_undef) ;
1866 /* Set the Cursor to the Last element */
1867 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1868 #ifndef DB_VERSION_MAJOR
1873 keyval = *(int*)key.data ;
1876 for (i = 1 ; i < items ; ++i)
1878 DBM_ckFilter(ST(i), filter_store_value, "filter_store_value");
1879 value.data = SvPVbyte(ST(i), n_a) ;
1882 key.data = &keyval ;
1883 key.size = sizeof(int) ;
1884 RETVAL = (Db->put)(Db, TXN &key, &value, 0) ;
1898 ALIAS: FETCHSIZE = 1
1901 RETVAL = GetArrayLength(aTHX_ db) ;
1907 # Now provide an interface to the rest of the DB functionality
1911 db_del(db, key, flags=0)
1919 RETVAL = db_del(db, key, flags) ;
1920 #ifdef DB_VERSION_MAJOR
1923 else if (RETVAL == DB_NOTFOUND)
1931 db_get(db, key, value, flags=0)
1941 RETVAL = db_get(db, key, value, flags) ;
1942 #ifdef DB_VERSION_MAJOR
1945 else if (RETVAL == DB_NOTFOUND)
1953 db_put(db, key, value, flags=0)
1962 RETVAL = db_put(db, key, value, flags) ;
1963 #ifdef DB_VERSION_MAJOR
1966 else if (RETVAL == DB_KEYEXIST)
1971 key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
1980 #ifdef DB_VERSION_MAJOR
1984 status = (db->in_memory
1986 : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
1991 RETVAL = (db->in_memory
1993 : ((db->dbp)->fd)(db->dbp) ) ;
1999 db_sync(db, flags=0)
2006 RETVAL = db_sync(db, flags) ;
2007 #ifdef DB_VERSION_MAJOR
2016 db_seq(db, key, value, flags)
2026 RETVAL = db_seq(db, key, value, flags);
2027 #ifdef DB_VERSION_MAJOR
2030 else if (RETVAL == DB_NOTFOUND)
2039 filter_fetch_key(db, code)
2042 SV * RETVAL = &PL_sv_undef ;
2044 DBM_setFilter(db->filter_fetch_key, code) ;
2047 filter_store_key(db, code)
2050 SV * RETVAL = &PL_sv_undef ;
2052 DBM_setFilter(db->filter_store_key, code) ;
2055 filter_fetch_value(db, code)
2058 SV * RETVAL = &PL_sv_undef ;
2060 DBM_setFilter(db->filter_fetch_value, code) ;
2063 filter_store_value(db, code)
2066 SV * RETVAL = &PL_sv_undef ;
2068 DBM_setFilter(db->filter_store_value, code) ;