B, B::C, perlcc, t/TEST
[p5sagit/p5-mst-13.2.git] / ext / DB_File / DB_File.xs
CommitLineData
a0d0e21e 1/*
2
3 DB_File.xs -- Perl 5 interface to Berkeley DB
4
6ca2e664 5 written by Paul Marquess <Paul.Marquess@btinternet.com>
412e9c57 6 last modified 26th Nov 2001
7 version 1.801
a0d0e21e 8
9 All comments/suggestions/problems are welcome
10
c5da4faf 11 Copyright (c) 1995-2001 Paul Marquess. All rights reserved.
36477c24 12 This program is free software; you can redistribute it and/or
13 modify it under the same terms as Perl itself.
14
3b35bae3 15 Changes:
4633a7c4 16 0.1 - Initial Release
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.
88108326 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
f6b705ef 29 1.03 - Added EXISTS
610ab055 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
33 Makefile.PL
ff68c719 34 1.06 - Minor namespace cleanup: Localized PrintBtree.
36477c24 35 1.07 - Fixed bug with RECNO, where bval wasn't defaulting to "\n".
36 1.08 - No change to DB_File.xs
18d2dc8c 37 1.09 - Default mode for dbopen changed to 0666
a0b8c8c1 38 1.10 - Fixed fd method so that it still returns -1 for
39 in-memory files when db 1.86 is used.
778183f3 40 1.11 - No change to DB_File.xs
68dc0745 41 1.12 - No change to DB_File.xs
1f70e1ea 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
a6ed719b 48 undefined value" warning with db_get and db_seq.
1f70e1ea 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
045291aa 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.
a9fd575d 57 1.59 - No change to DB_File.xs
58 1.60 - Some code tidy up
9d9477b1 59 1.61 - added flagSet macro for DB 2.5.x
60 fixed typo in O_RDONLY test.
6ca2e664 61 1.62 - No change to DB_File.xs
62 1.63 - Fix to alllow DB 2.6.x to build.
20896112 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
ca63f0d2 66 1.65 - Fixed a bug in the PUSH logic.
67 Added BOOT check that using 2.3.4 or greater
9fe6733a 68 1.66 - Added DBM filter code
cad2e5aa 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.
2c2d71f5 72 1.68 - fixed backward compatability bug with R_IAFTER & R_IBEFORE
73 merged in the 5.005_58 changes
a62982a8 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
e07e3419 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 &
80 libdb.a/so.
ccb44e3b 81 1.71 - Support for Berkeley DB version 3.
82 Support for Berkeley DB 2/3's backward compatability mode.
83 Rewrote push
b90e71be 84 1.72 - No change to DB_File.xs
88c74d4b 85 1.73 - No change to DB_File.xs
3245f058 86 1.74 - A call to open needed parenthesised to stop it clashing
87 with a win32 macro.
88 Added Perl core patches 7703 & 7801.
73969f8f 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
92 needed to be changed.
c5da4faf 93 1.76 - No change to DB_File.xs
94 1.77 - Tidied up a few types used in calling newSVpvn.
39793c41 95 1.78 - Core patch 10335, 10372, 10534, 10549, 11051 included.
c6c92ad9 96 1.79 - NEXTKEY ignores the input key.
97 Added lots of casts
07200f1b 98 1.800 - Moved backward compatability code into ppport.h.
99 Use the new constants code.
412e9c57 100 1.801 - No change to DB_File.xs
f6b705ef 101
a0d0e21e 102*/
103
c6c619a9 104#define PERL_NO_GET_CONTEXT
a0d0e21e 105#include "EXTERN.h"
106#include "perl.h"
107#include "XSUB.h"
108
07200f1b 109#ifdef _NOT_CORE
110# include "ppport.h"
cad2e5aa 111#endif
112
640374d0 113/* Mention DB_VERSION_MAJOR_CFG, DB_VERSION_MINOR_CFG, and
114 DB_VERSION_PATCH_CFG here so that Configure pulls them all in. */
115
52e1cb5e 116/* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
117 * shortly #included by the <db.h>) __attribute__ to the possibly
118 * already defined __attribute__, for example by GNUC or by Perl. */
1f70e1ea 119
39793c41 120/* #if DB_VERSION_MAJOR_CFG < 2 */
121#ifndef DB_VERSION_MAJOR
122# undef __attribute__
640374d0 123#endif
124
39793c41 125
c6c619a9 126
ccb44e3b 127#ifdef COMPAT185
128# include <db_185.h>
129#else
130# include <db.h>
131#endif
a0d0e21e 132
39793c41 133/* Wall starts with 5.7.x */
134
135#if PERL_REVISION > 5 || (PERL_REVISION == 5 && PERL_VERSION >= 7)
136
137/* Since we dropped the gccish definition of __attribute__ we will want
138 * to redefine dNOOP, however (so that dTHX continues to work). Yes,
139 * all this means that we can't do attribute checking on the DB_File,
140 * boo, hiss. */
141# ifndef DB_VERSION_MAJOR
142
143# undef dNOOP
144# define dNOOP extern int Perl___notused
145
146 /* Ditto for dXSARGS. */
147# undef dXSARGS
148# define dXSARGS \
149 dSP; dMARK; \
150 I32 ax = mark - PL_stack_base + 1; \
151 I32 items = sp - mark
152
153# endif
154
155/* avoid -Wall; DB_File xsubs never make use of `ix' setup for ALIASes */
156# undef dXSI32
157# define dXSI32 dNOOP
158
159#endif /* Perl >= 5.7 */
b92372bc 160
a0d0e21e 161#include <fcntl.h>
162
1f70e1ea 163/* #define TRACE */
9fe6733a 164#define DBM_FILTERING
1f70e1ea 165
ccb44e3b 166#ifdef TRACE
167# define Trace(x) printf x
168#else
169# define Trace(x)
170#endif
171
1f70e1ea 172
ccb44e3b 173#define DBT_clear(x) Zero(&x, 1, DBT) ;
1f70e1ea 174
175#ifdef DB_VERSION_MAJOR
176
ccb44e3b 177#if DB_VERSION_MAJOR == 2
178# define BERKELEY_DB_1_OR_2
179#endif
180
73969f8f 181#if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)
182# define AT_LEAST_DB_3_2
183#endif
184
1f70e1ea 185/* map version 2 features & constants onto their version 1 equivalent */
186
187#ifdef DB_Prefix_t
2c2d71f5 188# undef DB_Prefix_t
1f70e1ea 189#endif
190#define DB_Prefix_t size_t
191
192#ifdef DB_Hash_t
2c2d71f5 193# undef DB_Hash_t
1f70e1ea 194#endif
195#define DB_Hash_t u_int32_t
196
197/* DBTYPE stays the same */
198/* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
ccb44e3b 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 */
1f70e1ea 204
205/* version 2 has db_recno_t in place of recno_t */
206typedef db_recno_t recno_t;
207
208
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
ccb44e3b 217
a62982a8 218#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
ccb44e3b 219# define R_SETCURSOR 0x800000
a62982a8 220#else
ccb44e3b 221# define R_SETCURSOR (-100)
a62982a8 222#endif
ccb44e3b 223
1f70e1ea 224#define R_RECNOSYNC 0
225#define R_FIXEDLEN DB_FIXEDLEN
226#define R_DUP DB_DUP
227
ccb44e3b 228
1f70e1ea 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
235
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
244
245
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
253
254#define TXN NULL,
255
256#define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
257
258
259#define DBT_flags(x) x.flags = 0
260#define DB_flags(x, v) x |= v
261
9d9477b1 262#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
ccb44e3b 263# define flagSet(flags, bitmask) ((flags) & (bitmask))
9d9477b1 264#else
ccb44e3b 265# define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (bitmask))
9d9477b1 266#endif
267
1f70e1ea 268#else /* db version 1.x */
269
73969f8f 270#define BERKELEY_DB_1
ccb44e3b 271#define BERKELEY_DB_1_OR_2
272
1f70e1ea 273typedef union INFO {
274 HASHINFO hash ;
275 RECNOINFO recno ;
276 BTREEINFO btree ;
277 } INFO ;
278
279
610ab055 280#ifdef mDB_Prefix_t
ccb44e3b 281# ifdef DB_Prefix_t
282# undef DB_Prefix_t
283# endif
284# define DB_Prefix_t mDB_Prefix_t
610ab055 285#endif
286
287#ifdef mDB_Hash_t
ccb44e3b 288# ifdef DB_Hash_t
289# undef DB_Hash_t
290# endif
291# define DB_Hash_t mDB_Hash_t
610ab055 292#endif
293
1f70e1ea 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
300
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
309
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
317
318#define TXN
319
320#define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
321#define DBT_flags(x)
322#define DB_flags(x, v)
9d9477b1 323#define flagSet(flags, bitmask) ((flags) & (bitmask))
1f70e1ea 324
325#endif /* db version 1 */
326
327
328
329#define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, flags)
330#define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, flags)
331#define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
332
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)
9d9477b1 335
1f70e1ea 336#ifdef DB_VERSION_MAJOR
a62982a8 337#define db_DESTROY(db) ( db->cursor->c_close(db->cursor),\
ccb44e3b 338 (db->dbp->close)(db->dbp, 0) )
1f70e1ea 339#define db_close(db) ((db->dbp)->close)(db->dbp, 0)
9d9477b1 340#define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \
1f70e1ea 341 ? ((db->cursor)->c_del)(db->cursor, 0) \
342 : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
343
ccb44e3b 344#else /* ! DB_VERSION_MAJOR */
1f70e1ea 345
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)
350
ccb44e3b 351#endif /* ! DB_VERSION_MAJOR */
1f70e1ea 352
9d9477b1 353
1f70e1ea 354#define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
610ab055 355
8e07c86e 356typedef struct {
357 DBTYPE type ;
358 DB * dbp ;
359 SV * compare ;
360 SV * prefix ;
361 SV * hash ;
a0b8c8c1 362 int in_memory ;
ccb44e3b 363#ifdef BERKELEY_DB_1_OR_2
1f70e1ea 364 INFO info ;
ccb44e3b 365#endif
1f70e1ea 366#ifdef DB_VERSION_MAJOR
367 DBC * cursor ;
368#endif
9fe6733a 369#ifdef DBM_FILTERING
370 SV * filter_fetch_key ;
371 SV * filter_store_key ;
372 SV * filter_fetch_value ;
373 SV * filter_store_value ;
374 int filtering ;
375#endif /* DBM_FILTERING */
376
8e07c86e 377 } DB_File_type;
378
379typedef DB_File_type * DB_File ;
a0d0e21e 380typedef DBT DBTKEY ;
381
9fe6733a 382#ifdef DBM_FILTERING
383
384#define ckFilter(arg,type,name) \
385 if (db->type) { \
386 SV * save_defsv ; \
c6c92ad9 387 /* printf("filtering %s\n", name) ; */ \
9fe6733a 388 if (db->filtering) \
389 croak("recursion detected in %s", name) ; \
390 db->filtering = TRUE ; \
9fe6733a 391 save_defsv = newSVsv(DEFSV) ; \
392 sv_setsv(DEFSV, arg) ; \
393 PUSHMARK(sp) ; \
394 (void) perl_call_sv(db->type, G_DISCARD|G_NOARGS); \
9fe6733a 395 sv_setsv(arg, DEFSV) ; \
cad2e5aa 396 sv_setsv(DEFSV, save_defsv) ; \
9fe6733a 397 SvREFCNT_dec(save_defsv) ; \
9fe6733a 398 db->filtering = FALSE ; \
c6c92ad9 399 /* printf("end of filtering %s\n", name) ; */ \
9fe6733a 400 }
401
402#else
403
404#define ckFilter(arg,type, name)
405
406#endif /* DBM_FILTERING */
407
045291aa 408#define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
a0d0e21e 409
9fe6733a 410#define OutputValue(arg, name) \
411 { if (RETVAL == 0) { \
412 my_sv_setpvn(arg, name.data, name.size) ; \
413 ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
414 } \
88108326 415 }
a0d0e21e 416
9fe6733a 417#define OutputKey(arg, name) \
418 { if (RETVAL == 0) \
419 { \
420 if (db->type != DB_RECNO) { \
421 my_sv_setpvn(arg, name.data, name.size); \
422 } \
423 else \
424 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
425 ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \
426 } \
a0d0e21e 427 }
428
c6c92ad9 429#define my_SvUV32(sv) ((u_int32_t)SvUV(sv))
045291aa 430
39793c41 431#ifdef CAN_PROTOTYPE
432extern void __getBerkeleyDBInfo(void);
433#endif
434
a0d0e21e 435/* Internal Global Data */
07200f1b 436
df3728a2 437#define MY_CXT_KEY "DB_File::_guts" XS_VERSION
438
439typedef struct {
440 recno_t x_Value;
441 recno_t x_zero;
442 DB_File x_CurrentDB;
443 DBTKEY x_empty;
444} my_cxt_t;
445
446START_MY_CXT
447
448#define Value (MY_CXT.x_Value)
449#define zero (MY_CXT.x_zero)
450#define CurrentDB (MY_CXT.x_CurrentDB)
451#define empty (MY_CXT.x_empty)
1f70e1ea 452
453#ifdef DB_VERSION_MAJOR
454
455static int
2c2d71f5 456#ifdef CAN_PROTOTYPE
b76802f5 457db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
2c2d71f5 458#else
459db_put(db, key, value, flags)
460DB_File db ;
461DBTKEY key ;
462DBT value ;
463u_int flags ;
464#endif
1f70e1ea 465{
466 int status ;
467
2c2d71f5 468 if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) {
469 DBC * temp_cursor ;
470 DBT l_key, l_value;
471
472#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
473 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0)
9d9477b1 474#else
2c2d71f5 475 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0)
9d9477b1 476#endif
2c2d71f5 477 return (-1) ;
478
479 memset(&l_key, 0, sizeof(l_key));
480 l_key.data = key.data;
481 l_key.size = key.size;
482 memset(&l_value, 0, sizeof(l_value));
483 l_value.data = value.data;
484 l_value.size = value.size;
485
486 if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) {
487 (void)temp_cursor->c_close(temp_cursor);
488 return (-1);
489 }
490
491 status = temp_cursor->c_put(temp_cursor, &key, &value, flags);
492 (void)temp_cursor->c_close(temp_cursor);
493
494 return (status) ;
495 }
496
497
498 if (flagSet(flags, R_CURSOR)) {
499 return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT);
500 }
9d9477b1 501
2c2d71f5 502 if (flagSet(flags, R_SETCURSOR)) {
503 if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0)
504 return -1 ;
505 return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE);
506
1f70e1ea 507 }
508
509 return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
510
511}
512
513#endif /* DB_VERSION_MAJOR */
514
a0d0e21e 515
516static int
73969f8f 517#ifdef AT_LEAST_DB_3_2
518
519#ifdef CAN_PROTOTYPE
520btree_compare(DB * db, const DBT *key1, const DBT *key2)
521#else
522btree_compare(db, key1, key2)
523DB * db ;
524const DBT * key1 ;
525const DBT * key2 ;
526#endif /* CAN_PROTOTYPE */
527
528#else /* Berkeley DB < 3.2 */
529
2c2d71f5 530#ifdef CAN_PROTOTYPE
b76802f5 531btree_compare(const DBT *key1, const DBT *key2)
2c2d71f5 532#else
533btree_compare(key1, key2)
534const DBT * key1 ;
535const DBT * key2 ;
536#endif
73969f8f 537
538#endif
539
a0d0e21e 540{
2c2d71f5 541#ifdef dTHX
b76802f5 542 dTHX;
2c2d71f5 543#endif
a0d0e21e 544 dSP ;
df3728a2 545 dMY_CXT ;
546 void * data1, * data2 ;
a0d0e21e 547 int retval ;
548 int count ;
549
c5da4faf 550 data1 = (char *) key1->data ;
551 data2 = (char *) key2->data ;
cad2e5aa 552
2c2d71f5 553#ifndef newSVpvn
a0d0e21e 554 /* As newSVpv will assume that the data pointer is a null terminated C
555 string if the size parameter is 0, make sure that data points to an
556 empty string if the length is 0
557 */
558 if (key1->size == 0)
559 data1 = "" ;
560 if (key2->size == 0)
561 data2 = "" ;
2c2d71f5 562#endif
cad2e5aa 563
a0d0e21e 564 ENTER ;
565 SAVETMPS;
566
924508f0 567 PUSHMARK(SP) ;
568 EXTEND(SP,2) ;
2c2d71f5 569 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
570 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
a0d0e21e 571 PUTBACK ;
572
8e07c86e 573 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
a0d0e21e 574
575 SPAGAIN ;
576
577 if (count != 1)
ff0cee69 578 croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
a0d0e21e 579
580 retval = POPi ;
581
582 PUTBACK ;
583 FREETMPS ;
584 LEAVE ;
585 return (retval) ;
586
587}
588
ecfc5424 589static DB_Prefix_t
73969f8f 590#ifdef AT_LEAST_DB_3_2
591
592#ifdef CAN_PROTOTYPE
593btree_prefix(DB * db, const DBT *key1, const DBT *key2)
594#else
595btree_prefix(db, key1, key2)
596Db * db ;
597const DBT * key1 ;
598const DBT * key2 ;
599#endif
600
601#else /* Berkeley DB < 3.2 */
602
2c2d71f5 603#ifdef CAN_PROTOTYPE
b76802f5 604btree_prefix(const DBT *key1, const DBT *key2)
2c2d71f5 605#else
606btree_prefix(key1, key2)
607const DBT * key1 ;
608const DBT * key2 ;
609#endif
73969f8f 610
611#endif
a0d0e21e 612{
2c2d71f5 613#ifdef dTHX
b76802f5 614 dTHX;
2c2d71f5 615#endif
a0d0e21e 616 dSP ;
df3728a2 617 dMY_CXT ;
c5da4faf 618 char * data1, * data2 ;
a0d0e21e 619 int retval ;
620 int count ;
621
c5da4faf 622 data1 = (char *) key1->data ;
623 data2 = (char *) key2->data ;
cad2e5aa 624
2c2d71f5 625#ifndef newSVpvn
a0d0e21e 626 /* As newSVpv will assume that the data pointer is a null terminated C
627 string if the size parameter is 0, make sure that data points to an
628 empty string if the length is 0
629 */
630 if (key1->size == 0)
631 data1 = "" ;
632 if (key2->size == 0)
633 data2 = "" ;
2c2d71f5 634#endif
cad2e5aa 635
a0d0e21e 636 ENTER ;
637 SAVETMPS;
638
924508f0 639 PUSHMARK(SP) ;
640 EXTEND(SP,2) ;
2c2d71f5 641 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
642 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
a0d0e21e 643 PUTBACK ;
644
8e07c86e 645 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
a0d0e21e 646
647 SPAGAIN ;
648
649 if (count != 1)
ff0cee69 650 croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
a0d0e21e 651
652 retval = POPi ;
653
654 PUTBACK ;
655 FREETMPS ;
656 LEAVE ;
657
658 return (retval) ;
659}
660
3245f058 661
73969f8f 662#ifdef BERKELEY_DB_1
a56128cb 663# define HASH_CB_SIZE_TYPE size_t
664#else
665# define HASH_CB_SIZE_TYPE u_int32_t
666#endif
667
ecfc5424 668static DB_Hash_t
73969f8f 669#ifdef AT_LEAST_DB_3_2
670
671#ifdef CAN_PROTOTYPE
672hash_cb(DB * db, const void *data, u_int32_t size)
673#else
674hash_cb(db, data, size)
675DB * db ;
676const void * data ;
677HASH_CB_SIZE_TYPE size ;
678#endif
679
680#else /* Berkeley DB < 3.2 */
681
2c2d71f5 682#ifdef CAN_PROTOTYPE
a56128cb 683hash_cb(const void *data, HASH_CB_SIZE_TYPE size)
2c2d71f5 684#else
685hash_cb(data, size)
686const void * data ;
a56128cb 687HASH_CB_SIZE_TYPE size ;
2c2d71f5 688#endif
73969f8f 689
690#endif
a0d0e21e 691{
2c2d71f5 692#ifdef dTHX
b76802f5 693 dTHX;
2c2d71f5 694#endif
a0d0e21e 695 dSP ;
df3728a2 696 dMY_CXT;
a0d0e21e 697 int retval ;
698 int count ;
cad2e5aa 699
2c2d71f5 700#ifndef newSVpvn
a0d0e21e 701 if (size == 0)
702 data = "" ;
2c2d71f5 703#endif
cad2e5aa 704
610ab055 705 /* DGH - Next two lines added to fix corrupted stack problem */
706 ENTER ;
707 SAVETMPS;
708
924508f0 709 PUSHMARK(SP) ;
610ab055 710
2c2d71f5 711 XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
a0d0e21e 712 PUTBACK ;
713
8e07c86e 714 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
a0d0e21e 715
716 SPAGAIN ;
717
718 if (count != 1)
ff0cee69 719 croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
a0d0e21e 720
721 retval = POPi ;
722
723 PUTBACK ;
724 FREETMPS ;
725 LEAVE ;
726
727 return (retval) ;
728}
729
730
ccb44e3b 731#if defined(TRACE) && defined(BERKELEY_DB_1_OR_2)
a0d0e21e 732
733static void
2c2d71f5 734#ifdef CAN_PROTOTYPE
b76802f5 735PrintHash(INFO *hash)
2c2d71f5 736#else
737PrintHash(hash)
738INFO * hash ;
739#endif
a0d0e21e 740{
741 printf ("HASH Info\n") ;
1f70e1ea 742 printf (" hash = %s\n",
743 (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
744 printf (" bsize = %d\n", hash->db_HA_bsize) ;
745 printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
746 printf (" nelem = %d\n", hash->db_HA_nelem) ;
747 printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
748 printf (" lorder = %d\n", hash->db_HA_lorder) ;
a0d0e21e 749
750}
751
752static void
2c2d71f5 753#ifdef CAN_PROTOTYPE
b76802f5 754PrintRecno(INFO *recno)
2c2d71f5 755#else
756PrintRecno(recno)
757INFO * recno ;
758#endif
a0d0e21e 759{
760 printf ("RECNO Info\n") ;
1f70e1ea 761 printf (" flags = %d\n", recno->db_RE_flags) ;
762 printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
763 printf (" psize = %d\n", recno->db_RE_psize) ;
764 printf (" lorder = %d\n", recno->db_RE_lorder) ;
765 printf (" reclen = %ul\n", (unsigned long)recno->db_RE_reclen) ;
766 printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
767 printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
a0d0e21e 768}
769
ff68c719 770static void
2c2d71f5 771#ifdef CAN_PROTOTYPE
b76802f5 772PrintBtree(INFO *btree)
2c2d71f5 773#else
774PrintBtree(btree)
775INFO * btree ;
776#endif
a0d0e21e 777{
778 printf ("BTREE Info\n") ;
1f70e1ea 779 printf (" compare = %s\n",
780 (btree->db_BT_compare ? "redefined" : "default")) ;
781 printf (" prefix = %s\n",
782 (btree->db_BT_prefix ? "redefined" : "default")) ;
783 printf (" flags = %d\n", btree->db_BT_flags) ;
784 printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
785 printf (" psize = %d\n", btree->db_BT_psize) ;
786#ifndef DB_VERSION_MAJOR
787 printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
788 printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
789#endif
790 printf (" lorder = %d\n", btree->db_BT_lorder) ;
a0d0e21e 791}
792
793#else
794
795#define PrintRecno(recno)
796#define PrintHash(hash)
797#define PrintBtree(btree)
798
799#endif /* TRACE */
800
801
802static I32
2c2d71f5 803#ifdef CAN_PROTOTYPE
b76802f5 804GetArrayLength(pTHX_ DB_File db)
2c2d71f5 805#else
806GetArrayLength(db)
807DB_File db ;
808#endif
a0d0e21e 809{
810 DBT key ;
811 DBT value ;
812 int RETVAL ;
813
ccb44e3b 814 DBT_clear(key) ;
815 DBT_clear(value) ;
1f70e1ea 816 RETVAL = do_SEQ(db, key, value, R_LAST) ;
a0d0e21e 817 if (RETVAL == 0)
818 RETVAL = *(I32 *)key.data ;
1f70e1ea 819 else /* No key means empty file */
a0d0e21e 820 RETVAL = 0 ;
821
a0b8c8c1 822 return ((I32)RETVAL) ;
a0d0e21e 823}
824
88108326 825static recno_t
2c2d71f5 826#ifdef CAN_PROTOTYPE
b76802f5 827GetRecnoKey(pTHX_ DB_File db, I32 value)
2c2d71f5 828#else
829GetRecnoKey(db, value)
830DB_File db ;
831I32 value ;
832#endif
88108326 833{
834 if (value < 0) {
835 /* Get the length of the array */
b76802f5 836 I32 length = GetArrayLength(aTHX_ db) ;
88108326 837
838 /* check for attempt to write before start of array */
839 if (length + value + 1 <= 0)
ff0cee69 840 croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
88108326 841
842 value = length + value + 1 ;
843 }
844 else
845 ++ value ;
846
847 return value ;
a0d0e21e 848}
849
ccb44e3b 850
a0d0e21e 851static DB_File
2c2d71f5 852#ifdef CAN_PROTOTYPE
b76802f5 853ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
2c2d71f5 854#else
855ParseOpenInfo(isHASH, name, flags, mode, sv)
856int isHASH ;
857char * name ;
858int flags ;
859int mode ;
860SV * sv ;
861#endif
a0d0e21e 862{
ccb44e3b 863
864#ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
865
a0d0e21e 866 SV ** svp;
867 HV * action ;
045291aa 868 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
a0d0e21e 869 void * openinfo = NULL ;
045291aa 870 INFO * info = &RETVAL->info ;
2d8e6c8d 871 STRLEN n_a;
df3728a2 872 dMY_CXT;
1f70e1ea 873
874/* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
045291aa 875 Zero(RETVAL, 1, DB_File_type) ;
a0d0e21e 876
88108326 877 /* Default to HASH */
9fe6733a 878#ifdef DBM_FILTERING
879 RETVAL->filtering = 0 ;
880 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
881 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
882#endif /* DBM_FILTERING */
8e07c86e 883 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
884 RETVAL->type = DB_HASH ;
a0d0e21e 885
610ab055 886 /* DGH - Next line added to avoid SEGV on existing hash DB */
887 CurrentDB = RETVAL;
888
a0b8c8c1 889 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
890 RETVAL->in_memory = (name == NULL) ;
891
a0d0e21e 892 if (sv)
893 {
894 if (! SvROK(sv) )
895 croak ("type parameter is not a reference") ;
896
36477c24 897 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
898 if (svp && SvOK(*svp))
899 action = (HV*) SvRV(*svp) ;
900 else
901 croak("internal error") ;
610ab055 902
a0d0e21e 903 if (sv_isa(sv, "DB_File::HASHINFO"))
904 {
05475680 905
906 if (!isHASH)
907 croak("DB_File can only tie an associative array to a DB_HASH database") ;
908
8e07c86e 909 RETVAL->type = DB_HASH ;
610ab055 910 openinfo = (void*)info ;
a0d0e21e 911
912 svp = hv_fetch(action, "hash", 4, FALSE);
913
914 if (svp && SvOK(*svp))
915 {
1f70e1ea 916 info->db_HA_hash = hash_cb ;
8e07c86e 917 RETVAL->hash = newSVsv(*svp) ;
a0d0e21e 918 }
919 else
1f70e1ea 920 info->db_HA_hash = NULL ;
a0d0e21e 921
a0d0e21e 922 svp = hv_fetch(action, "ffactor", 7, FALSE);
1f70e1ea 923 info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
a0d0e21e 924
925 svp = hv_fetch(action, "nelem", 5, FALSE);
1f70e1ea 926 info->db_HA_nelem = svp ? SvIV(*svp) : 0;
a0d0e21e 927
1f70e1ea 928 svp = hv_fetch(action, "bsize", 5, FALSE);
929 info->db_HA_bsize = svp ? SvIV(*svp) : 0;
930
a0d0e21e 931 svp = hv_fetch(action, "cachesize", 9, FALSE);
1f70e1ea 932 info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
a0d0e21e 933
934 svp = hv_fetch(action, "lorder", 6, FALSE);
1f70e1ea 935 info->db_HA_lorder = svp ? SvIV(*svp) : 0;
a0d0e21e 936
937 PrintHash(info) ;
938 }
939 else if (sv_isa(sv, "DB_File::BTREEINFO"))
940 {
05475680 941 if (!isHASH)
942 croak("DB_File can only tie an associative array to a DB_BTREE database");
943
8e07c86e 944 RETVAL->type = DB_BTREE ;
610ab055 945 openinfo = (void*)info ;
a0d0e21e 946
947 svp = hv_fetch(action, "compare", 7, FALSE);
948 if (svp && SvOK(*svp))
949 {
1f70e1ea 950 info->db_BT_compare = btree_compare ;
8e07c86e 951 RETVAL->compare = newSVsv(*svp) ;
a0d0e21e 952 }
953 else
1f70e1ea 954 info->db_BT_compare = NULL ;
a0d0e21e 955
956 svp = hv_fetch(action, "prefix", 6, FALSE);
957 if (svp && SvOK(*svp))
958 {
1f70e1ea 959 info->db_BT_prefix = btree_prefix ;
8e07c86e 960 RETVAL->prefix = newSVsv(*svp) ;
a0d0e21e 961 }
962 else
1f70e1ea 963 info->db_BT_prefix = NULL ;
a0d0e21e 964
965 svp = hv_fetch(action, "flags", 5, FALSE);
1f70e1ea 966 info->db_BT_flags = svp ? SvIV(*svp) : 0;
a0d0e21e 967
968 svp = hv_fetch(action, "cachesize", 9, FALSE);
1f70e1ea 969 info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
a0d0e21e 970
1f70e1ea 971#ifndef DB_VERSION_MAJOR
a0d0e21e 972 svp = hv_fetch(action, "minkeypage", 10, FALSE);
610ab055 973 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
a0d0e21e 974
975 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
610ab055 976 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
1f70e1ea 977#endif
a0d0e21e 978
979 svp = hv_fetch(action, "psize", 5, FALSE);
1f70e1ea 980 info->db_BT_psize = svp ? SvIV(*svp) : 0;
a0d0e21e 981
982 svp = hv_fetch(action, "lorder", 6, FALSE);
1f70e1ea 983 info->db_BT_lorder = svp ? SvIV(*svp) : 0;
a0d0e21e 984
985 PrintBtree(info) ;
986
987 }
988 else if (sv_isa(sv, "DB_File::RECNOINFO"))
989 {
05475680 990 if (isHASH)
991 croak("DB_File can only tie an array to a DB_RECNO database");
992
8e07c86e 993 RETVAL->type = DB_RECNO ;
610ab055 994 openinfo = (void *)info ;
a0d0e21e 995
1f70e1ea 996 info->db_RE_flags = 0 ;
997
a0d0e21e 998 svp = hv_fetch(action, "flags", 5, FALSE);
1f70e1ea 999 info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
1000
1001 svp = hv_fetch(action, "reclen", 6, FALSE);
1002 info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
a0d0e21e 1003
1004 svp = hv_fetch(action, "cachesize", 9, FALSE);
1f70e1ea 1005 info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
a0d0e21e 1006
1007 svp = hv_fetch(action, "psize", 5, FALSE);
1f70e1ea 1008 info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
a0d0e21e 1009
1010 svp = hv_fetch(action, "lorder", 6, FALSE);
1f70e1ea 1011 info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
1012
1013#ifdef DB_VERSION_MAJOR
1014 info->re_source = name ;
1015 name = NULL ;
1016#endif
1017 svp = hv_fetch(action, "bfname", 6, FALSE);
1018 if (svp && SvOK(*svp)) {
2d8e6c8d 1019 char * ptr = SvPV(*svp,n_a) ;
1f70e1ea 1020#ifdef DB_VERSION_MAJOR
2d8e6c8d 1021 name = (char*) n_a ? ptr : NULL ;
1f70e1ea 1022#else
2d8e6c8d 1023 info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
1f70e1ea 1024#endif
1025 }
1026 else
1027#ifdef DB_VERSION_MAJOR
1028 name = NULL ;
1029#else
1030 info->db_RE_bfname = NULL ;
1031#endif
a0d0e21e 1032
1033 svp = hv_fetch(action, "bval", 4, FALSE);
1f70e1ea 1034#ifdef DB_VERSION_MAJOR
a0d0e21e 1035 if (svp && SvOK(*svp))
1036 {
1f70e1ea 1037 int value ;
a0d0e21e 1038 if (SvPOK(*svp))
2d8e6c8d 1039 value = (int)*SvPV(*svp, n_a) ;
a0d0e21e 1040 else
1f70e1ea 1041 value = SvIV(*svp) ;
1042
1043 if (info->flags & DB_FIXEDLEN) {
1044 info->re_pad = value ;
1045 info->flags |= DB_PAD ;
1046 }
1047 else {
1048 info->re_delim = value ;
1049 info->flags |= DB_DELIMITER ;
1050 }
1051
1052 }
1053#else
1054 if (svp && SvOK(*svp))
1055 {
1056 if (SvPOK(*svp))
2d8e6c8d 1057 info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
1f70e1ea 1058 else
1059 info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
1060 DB_flags(info->flags, DB_DELIMITER) ;
1061
a0d0e21e 1062 }
1063 else
1064 {
1f70e1ea 1065 if (info->db_RE_flags & R_FIXEDLEN)
1066 info->db_RE_bval = (u_char) ' ' ;
a0d0e21e 1067 else
1f70e1ea 1068 info->db_RE_bval = (u_char) '\n' ;
1069 DB_flags(info->flags, DB_DELIMITER) ;
a0d0e21e 1070 }
1f70e1ea 1071#endif
a0d0e21e 1072
1f70e1ea 1073#ifdef DB_RENUMBER
1074 info->flags |= DB_RENUMBER ;
1075#endif
1076
a0d0e21e 1077 PrintRecno(info) ;
1078 }
1079 else
1080 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1081 }
1082
1083
88108326 1084 /* OS2 Specific Code */
1085#ifdef OS2
1086#ifdef __EMX__
1087 flags |= O_BINARY;
1088#endif /* __EMX__ */
1089#endif /* OS2 */
a0d0e21e 1090
1f70e1ea 1091#ifdef DB_VERSION_MAJOR
1092
1093 {
1094 int Flags = 0 ;
1095 int status ;
1096
1097 /* Map 1.x flags to 2.x flags */
1098 if ((flags & O_CREAT) == O_CREAT)
1099 Flags |= DB_CREATE ;
1100
1f70e1ea 1101#if O_RDONLY == 0
1102 if (flags == O_RDONLY)
1103#else
20896112 1104 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1f70e1ea 1105#endif
1106 Flags |= DB_RDONLY ;
1107
20896112 1108#ifdef O_TRUNC
1f70e1ea 1109 if ((flags & O_TRUNC) == O_TRUNC)
1110 Flags |= DB_TRUNCATE ;
1111#endif
1112
1113 status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
1114 if (status == 0)
6ca2e664 1115#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
1f70e1ea 1116 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
6ca2e664 1117#else
1118 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1119 0) ;
1120#endif
1f70e1ea 1121
1122 if (status)
1123 RETVAL->dbp = NULL ;
1124
1125 }
1126#else
ccb44e3b 1127
1128#if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
1129 RETVAL->dbp = __db185_open(name, flags, mode, RETVAL->type, openinfo) ;
1130#else
88108326 1131 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
ccb44e3b 1132#endif /* DB_LIBRARY_COMPATIBILITY_API */
1133
1f70e1ea 1134#endif
a0d0e21e 1135
1136 return (RETVAL) ;
ccb44e3b 1137
1138#else /* Berkeley DB Version > 2 */
1139
1140 SV ** svp;
1141 HV * action ;
1142 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
1143 DB * dbp ;
1144 STRLEN n_a;
1145 int status ;
df3728a2 1146 dMY_CXT;
ccb44e3b 1147
1148/* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
1149 Zero(RETVAL, 1, DB_File_type) ;
1150
1151 /* Default to HASH */
1152#ifdef DBM_FILTERING
1153 RETVAL->filtering = 0 ;
1154 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
1155 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
1156#endif /* DBM_FILTERING */
1157 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
1158 RETVAL->type = DB_HASH ;
1159
1160 /* DGH - Next line added to avoid SEGV on existing hash DB */
1161 CurrentDB = RETVAL;
1162
1163 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
1164 RETVAL->in_memory = (name == NULL) ;
1165
1166 status = db_create(&RETVAL->dbp, NULL,0) ;
1167 /* printf("db_create returned %d %s\n", status, db_strerror(status)) ; */
1168 if (status) {
1169 RETVAL->dbp = NULL ;
1170 return (RETVAL) ;
1171 }
1172 dbp = RETVAL->dbp ;
1173
1174 if (sv)
1175 {
1176 if (! SvROK(sv) )
1177 croak ("type parameter is not a reference") ;
1178
1179 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
1180 if (svp && SvOK(*svp))
1181 action = (HV*) SvRV(*svp) ;
1182 else
1183 croak("internal error") ;
1184
1185 if (sv_isa(sv, "DB_File::HASHINFO"))
1186 {
1187
1188 if (!isHASH)
1189 croak("DB_File can only tie an associative array to a DB_HASH database") ;
1190
1191 RETVAL->type = DB_HASH ;
1192
1193 svp = hv_fetch(action, "hash", 4, FALSE);
1194
1195 if (svp && SvOK(*svp))
1196 {
1197 (void)dbp->set_h_hash(dbp, hash_cb) ;
1198 RETVAL->hash = newSVsv(*svp) ;
1199 }
1200
1201 svp = hv_fetch(action, "ffactor", 7, FALSE);
1202 if (svp)
c6c92ad9 1203 (void)dbp->set_h_ffactor(dbp, my_SvUV32(*svp)) ;
ccb44e3b 1204
1205 svp = hv_fetch(action, "nelem", 5, FALSE);
1206 if (svp)
c6c92ad9 1207 (void)dbp->set_h_nelem(dbp, my_SvUV32(*svp)) ;
ccb44e3b 1208
1209 svp = hv_fetch(action, "bsize", 5, FALSE);
1210 if (svp)
c6c92ad9 1211 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp));
ccb44e3b 1212
1213 svp = hv_fetch(action, "cachesize", 9, FALSE);
1214 if (svp)
c6c92ad9 1215 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
ccb44e3b 1216
1217 svp = hv_fetch(action, "lorder", 6, FALSE);
1218 if (svp)
c6c92ad9 1219 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
ccb44e3b 1220
1221 PrintHash(info) ;
1222 }
1223 else if (sv_isa(sv, "DB_File::BTREEINFO"))
1224 {
1225 if (!isHASH)
1226 croak("DB_File can only tie an associative array to a DB_BTREE database");
1227
1228 RETVAL->type = DB_BTREE ;
1229
1230 svp = hv_fetch(action, "compare", 7, FALSE);
1231 if (svp && SvOK(*svp))
1232 {
1233 (void)dbp->set_bt_compare(dbp, btree_compare) ;
1234 RETVAL->compare = newSVsv(*svp) ;
1235 }
1236
1237 svp = hv_fetch(action, "prefix", 6, FALSE);
1238 if (svp && SvOK(*svp))
1239 {
1240 (void)dbp->set_bt_prefix(dbp, btree_prefix) ;
1241 RETVAL->prefix = newSVsv(*svp) ;
1242 }
1243
1244 svp = hv_fetch(action, "flags", 5, FALSE);
1245 if (svp)
c6c92ad9 1246 (void)dbp->set_flags(dbp, my_SvUV32(*svp)) ;
ccb44e3b 1247
1248 svp = hv_fetch(action, "cachesize", 9, FALSE);
1249 if (svp)
c6c92ad9 1250 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
ccb44e3b 1251
1252 svp = hv_fetch(action, "psize", 5, FALSE);
1253 if (svp)
c6c92ad9 1254 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
ccb44e3b 1255
1256 svp = hv_fetch(action, "lorder", 6, FALSE);
1257 if (svp)
c6c92ad9 1258 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
ccb44e3b 1259
1260 PrintBtree(info) ;
1261
1262 }
1263 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1264 {
1265 int fixed = FALSE ;
1266
1267 if (isHASH)
1268 croak("DB_File can only tie an array to a DB_RECNO database");
1269
1270 RETVAL->type = DB_RECNO ;
1271
1272 svp = hv_fetch(action, "flags", 5, FALSE);
1273 if (svp) {
1274 int flags = SvIV(*svp) ;
1275 /* remove FIXDLEN, if present */
1276 if (flags & DB_FIXEDLEN) {
1277 fixed = TRUE ;
1278 flags &= ~DB_FIXEDLEN ;
1279 }
1280 }
1281
1282 svp = hv_fetch(action, "cachesize", 9, FALSE);
1283 if (svp) {
c6c92ad9 1284 status = dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
ccb44e3b 1285 }
1286
1287 svp = hv_fetch(action, "psize", 5, FALSE);
1288 if (svp) {
c6c92ad9 1289 status = dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
ccb44e3b 1290 }
1291
1292 svp = hv_fetch(action, "lorder", 6, FALSE);
1293 if (svp) {
c6c92ad9 1294 status = dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
ccb44e3b 1295 }
1296
1297 svp = hv_fetch(action, "bval", 4, FALSE);
1298 if (svp && SvOK(*svp))
1299 {
1300 int value ;
1301 if (SvPOK(*svp))
1302 value = (int)*SvPV(*svp, n_a) ;
1303 else
c6c92ad9 1304 value = (int)SvIV(*svp) ;
ccb44e3b 1305
1306 if (fixed) {
1307 status = dbp->set_re_pad(dbp, value) ;
1308 }
1309 else {
1310 status = dbp->set_re_delim(dbp, value) ;
1311 }
1312
1313 }
1314
1315 if (fixed) {
1316 svp = hv_fetch(action, "reclen", 6, FALSE);
1317 if (svp) {
c6c92ad9 1318 u_int32_t len = my_SvUV32(*svp) ;
ccb44e3b 1319 status = dbp->set_re_len(dbp, len) ;
1320 }
1321 }
1322
1323 if (name != NULL) {
1324 status = dbp->set_re_source(dbp, name) ;
1325 name = NULL ;
1326 }
1327
1328 svp = hv_fetch(action, "bfname", 6, FALSE);
1329 if (svp && SvOK(*svp)) {
1330 char * ptr = SvPV(*svp,n_a) ;
1331 name = (char*) n_a ? ptr : NULL ;
1332 }
1333 else
1334 name = NULL ;
1335
1336
c6c92ad9 1337 status = dbp->set_flags(dbp, (u_int32_t)DB_RENUMBER) ;
ccb44e3b 1338
1339 if (flags){
c6c92ad9 1340 (void)dbp->set_flags(dbp, (u_int32_t)flags) ;
ccb44e3b 1341 }
1342 PrintRecno(info) ;
1343 }
1344 else
1345 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1346 }
1347
1348 {
c6c92ad9 1349 u_int32_t Flags = 0 ;
ccb44e3b 1350 int status ;
1351
1352 /* Map 1.x flags to 3.x flags */
1353 if ((flags & O_CREAT) == O_CREAT)
1354 Flags |= DB_CREATE ;
1355
1356#if O_RDONLY == 0
1357 if (flags == O_RDONLY)
1358#else
1359 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1360#endif
1361 Flags |= DB_RDONLY ;
1362
1363#ifdef O_TRUNC
1364 if ((flags & O_TRUNC) == O_TRUNC)
1365 Flags |= DB_TRUNCATE ;
1366#endif
1367
3245f058 1368 status = (RETVAL->dbp->open)(RETVAL->dbp, name, NULL, RETVAL->type,
ccb44e3b 1369 Flags, mode) ;
1370 /* printf("open returned %d %s\n", status, db_strerror(status)) ; */
1371
1372 if (status == 0)
1373 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1374 0) ;
1375 /* printf("cursor returned %d %s\n", status, db_strerror(status)) ; */
1376
1377 if (status)
1378 RETVAL->dbp = NULL ;
1379
1380 }
1381
1382 return (RETVAL) ;
1383
1384#endif /* Berkeley DB Version > 2 */
1385
1386} /* ParseOpenInfo */
a0d0e21e 1387
1388
07200f1b 1389#include "constants.h"
a0d0e21e 1390
1391MODULE = DB_File PACKAGE = DB_File PREFIX = db_
1392
07200f1b 1393INCLUDE: constants.xs
1394
1f70e1ea 1395BOOT:
1396 {
df3728a2 1397 MY_CXT_INIT;
ccb44e3b 1398 __getBerkeleyDBInfo() ;
1f70e1ea 1399
ccb44e3b 1400 DBT_clear(empty) ;
1f70e1ea 1401 empty.data = &zero ;
1402 empty.size = sizeof(recno_t) ;
1f70e1ea 1403 }
1404
a0d0e21e 1405
1406
1407DB_File
05475680 1408db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
1409 int isHASH
a0d0e21e 1410 char * dbtype
1411 int flags
1412 int mode
1413 CODE:
1414 {
1415 char * name = (char *) NULL ;
1416 SV * sv = (SV *) NULL ;
2d8e6c8d 1417 STRLEN n_a;
a0d0e21e 1418
05475680 1419 if (items >= 3 && SvOK(ST(2)))
2d8e6c8d 1420 name = (char*) SvPV(ST(2), n_a) ;
a0d0e21e 1421
05475680 1422 if (items == 6)
1423 sv = ST(5) ;
a0d0e21e 1424
b76802f5 1425 RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
4633a7c4 1426 if (RETVAL->dbp == NULL)
1427 RETVAL = NULL ;
a0d0e21e 1428 }
1429 OUTPUT:
1430 RETVAL
1431
a0d0e21e 1432int
1433db_DESTROY(db)
1434 DB_File db
df3728a2 1435 PREINIT:
1436 dMY_CXT;
8e07c86e 1437 INIT:
1438 CurrentDB = db ;
1439 CLEANUP:
1440 if (db->hash)
1441 SvREFCNT_dec(db->hash) ;
1442 if (db->compare)
1443 SvREFCNT_dec(db->compare) ;
1444 if (db->prefix)
1445 SvREFCNT_dec(db->prefix) ;
9fe6733a 1446#ifdef DBM_FILTERING
1447 if (db->filter_fetch_key)
1448 SvREFCNT_dec(db->filter_fetch_key) ;
1449 if (db->filter_store_key)
1450 SvREFCNT_dec(db->filter_store_key) ;
1451 if (db->filter_fetch_value)
1452 SvREFCNT_dec(db->filter_fetch_value) ;
1453 if (db->filter_store_value)
1454 SvREFCNT_dec(db->filter_store_value) ;
1455#endif /* DBM_FILTERING */
eb99164f 1456 safefree(db) ;
1f70e1ea 1457#ifdef DB_VERSION_MAJOR
1458 if (RETVAL > 0)
1459 RETVAL = -1 ;
1460#endif
a0d0e21e 1461
1462
1463int
1464db_DELETE(db, key, flags=0)
1465 DB_File db
1466 DBTKEY key
1467 u_int flags
df3728a2 1468 PREINIT:
1469 dMY_CXT;
8e07c86e 1470 INIT:
1471 CurrentDB = db ;
a0d0e21e 1472
f6b705ef 1473
1474int
1475db_EXISTS(db, key)
1476 DB_File db
1477 DBTKEY key
df3728a2 1478 PREINIT:
1479 dMY_CXT;
f6b705ef 1480 CODE:
1481 {
1482 DBT value ;
1483
ccb44e3b 1484 DBT_clear(value) ;
f6b705ef 1485 CurrentDB = db ;
1f70e1ea 1486 RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
f6b705ef 1487 }
1488 OUTPUT:
1489 RETVAL
1490
c6c619a9 1491void
a0d0e21e 1492db_FETCH(db, key, flags=0)
1493 DB_File db
1494 DBTKEY key
1495 u_int flags
c6c619a9 1496 PREINIT:
07200f1b 1497 dMY_CXT ;
1498 int RETVAL ;
a0d0e21e 1499 CODE:
1500 {
1f70e1ea 1501 DBT value ;
a0d0e21e 1502
ccb44e3b 1503 DBT_clear(value) ;
8e07c86e 1504 CurrentDB = db ;
1f70e1ea 1505 /* RETVAL = ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) ; */
1506 RETVAL = db_get(db, key, value, flags) ;
a0d0e21e 1507 ST(0) = sv_newmortal();
a9fd575d 1508 OutputValue(ST(0), value)
a0d0e21e 1509 }
1510
1511int
1512db_STORE(db, key, value, flags=0)
1513 DB_File db
1514 DBTKEY key
1515 DBT value
1516 u_int flags
df3728a2 1517 PREINIT:
1518 dMY_CXT;
8e07c86e 1519 INIT:
1520 CurrentDB = db ;
a0d0e21e 1521
1522
c6c619a9 1523void
a0d0e21e 1524db_FIRSTKEY(db)
1525 DB_File db
c6c619a9 1526 PREINIT:
07200f1b 1527 dMY_CXT ;
1528 int RETVAL ;
a0d0e21e 1529 CODE:
1530 {
1f70e1ea 1531 DBTKEY key ;
a0d0e21e 1532 DBT value ;
1533
ccb44e3b 1534 DBT_clear(key) ;
1535 DBT_clear(value) ;
8e07c86e 1536 CurrentDB = db ;
1f70e1ea 1537 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
a0d0e21e 1538 ST(0) = sv_newmortal();
a9fd575d 1539 OutputKey(ST(0), key) ;
a0d0e21e 1540 }
1541
c6c619a9 1542void
a0d0e21e 1543db_NEXTKEY(db, key)
1544 DB_File db
0bf2e707 1545 DBTKEY key = NO_INIT
c6c619a9 1546 PREINIT:
07200f1b 1547 dMY_CXT ;
1548 int RETVAL ;
a0d0e21e 1549 CODE:
1550 {
1551 DBT value ;
1552
0bf2e707 1553 DBT_clear(key) ;
ccb44e3b 1554 DBT_clear(value) ;
8e07c86e 1555 CurrentDB = db ;
1f70e1ea 1556 RETVAL = do_SEQ(db, key, value, R_NEXT) ;
a0d0e21e 1557 ST(0) = sv_newmortal();
a9fd575d 1558 OutputKey(ST(0), key) ;
a0d0e21e 1559 }
1560
1561#
1562# These would be nice for RECNO
1563#
1564
1565int
1566unshift(db, ...)
1567 DB_File db
045291aa 1568 ALIAS: UNSHIFT = 1
df3728a2 1569 PREINIT:
1570 dMY_CXT;
a0d0e21e 1571 CODE:
1572 {
1573 DBTKEY key ;
1574 DBT value ;
1575 int i ;
1576 int One ;
2d8e6c8d 1577 STRLEN n_a;
a0d0e21e 1578
ccb44e3b 1579 DBT_clear(key) ;
1580 DBT_clear(value) ;
8e07c86e 1581 CurrentDB = db ;
1f70e1ea 1582#ifdef DB_VERSION_MAJOR
1583 /* get the first value */
1584 RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
1585 RETVAL = 0 ;
1586#else
a0d0e21e 1587 RETVAL = -1 ;
1f70e1ea 1588#endif
a0d0e21e 1589 for (i = items-1 ; i > 0 ; --i)
1590 {
2d8e6c8d 1591 value.data = SvPV(ST(i), n_a) ;
1592 value.size = n_a ;
a0d0e21e 1593 One = 1 ;
1594 key.data = &One ;
1595 key.size = sizeof(int) ;
1f70e1ea 1596#ifdef DB_VERSION_MAJOR
1597 RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
1598#else
b7953727 1599 RETVAL = (db->dbp->put)(db->dbp, &key, &value, R_IBEFORE) ;
1f70e1ea 1600#endif
a0d0e21e 1601 if (RETVAL != 0)
1602 break;
1603 }
1604 }
1605 OUTPUT:
1606 RETVAL
1607
c6c619a9 1608void
a0d0e21e 1609pop(db)
1610 DB_File db
df3728a2 1611 PREINIT:
1612 dMY_CXT;
045291aa 1613 ALIAS: POP = 1
c6c619a9 1614 PREINIT:
07200f1b 1615 I32 RETVAL;
a0d0e21e 1616 CODE:
1617 {
1618 DBTKEY key ;
1619 DBT value ;
1620
ccb44e3b 1621 DBT_clear(key) ;
1622 DBT_clear(value) ;
8e07c86e 1623 CurrentDB = db ;
1f70e1ea 1624
a0d0e21e 1625 /* First get the final value */
1f70e1ea 1626 RETVAL = do_SEQ(db, key, value, R_LAST) ;
a0d0e21e 1627 ST(0) = sv_newmortal();
1628 /* Now delete it */
1629 if (RETVAL == 0)
1630 {
f6b705ef 1631 /* the call to del will trash value, so take a copy now */
a9fd575d 1632 OutputValue(ST(0), value) ;
1f70e1ea 1633 RETVAL = db_del(db, key, R_CURSOR) ;
f6b705ef 1634 if (RETVAL != 0)
6b88bc9c 1635 sv_setsv(ST(0), &PL_sv_undef);
a0d0e21e 1636 }
1637 }
1638
c6c619a9 1639void
a0d0e21e 1640shift(db)
1641 DB_File db
df3728a2 1642 PREINIT:
1643 dMY_CXT;
045291aa 1644 ALIAS: SHIFT = 1
c6c619a9 1645 PREINIT:
07200f1b 1646 I32 RETVAL;
a0d0e21e 1647 CODE:
1648 {
a0d0e21e 1649 DBT value ;
f6b705ef 1650 DBTKEY key ;
a0d0e21e 1651
ccb44e3b 1652 DBT_clear(key) ;
1653 DBT_clear(value) ;
8e07c86e 1654 CurrentDB = db ;
a0d0e21e 1655 /* get the first value */
1f70e1ea 1656 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
a0d0e21e 1657 ST(0) = sv_newmortal();
1658 /* Now delete it */
1659 if (RETVAL == 0)
1660 {
f6b705ef 1661 /* the call to del will trash value, so take a copy now */
a9fd575d 1662 OutputValue(ST(0), value) ;
1f70e1ea 1663 RETVAL = db_del(db, key, R_CURSOR) ;
f6b705ef 1664 if (RETVAL != 0)
6b88bc9c 1665 sv_setsv (ST(0), &PL_sv_undef) ;
a0d0e21e 1666 }
1667 }
1668
1669
1670I32
1671push(db, ...)
1672 DB_File db
df3728a2 1673 PREINIT:
1674 dMY_CXT;
045291aa 1675 ALIAS: PUSH = 1
a0d0e21e 1676 CODE:
1677 {
1678 DBTKEY key ;
1679 DBT value ;
4633a7c4 1680 DB * Db = db->dbp ;
a0d0e21e 1681 int i ;
2d8e6c8d 1682 STRLEN n_a;
ccb44e3b 1683 int keyval ;
a0d0e21e 1684
1f70e1ea 1685 DBT_flags(key) ;
1686 DBT_flags(value) ;
8e07c86e 1687 CurrentDB = db ;
ca63f0d2 1688 /* Set the Cursor to the Last element */
1689 RETVAL = do_SEQ(db, key, value, R_LAST) ;
ccb44e3b 1690#ifndef DB_VERSION_MAJOR
ca63f0d2 1691 if (RETVAL >= 0)
ccb44e3b 1692#endif
ca63f0d2 1693 {
ccb44e3b 1694 if (RETVAL == 0)
1695 keyval = *(int*)key.data ;
1696 else
1697 keyval = 0 ;
1698 for (i = 1 ; i < items ; ++i)
8e07c86e 1699 {
2d8e6c8d 1700 value.data = SvPV(ST(i), n_a) ;
1701 value.size = n_a ;
ccb44e3b 1702 ++ keyval ;
1703 key.data = &keyval ;
1704 key.size = sizeof(int) ;
1705 RETVAL = (Db->put)(Db, TXN &key, &value, 0) ;
8e07c86e 1706 if (RETVAL != 0)
1707 break;
1708 }
a0d0e21e 1709 }
1710 }
1711 OUTPUT:
1712 RETVAL
1713
a0d0e21e 1714I32
1715length(db)
1716 DB_File db
df3728a2 1717 PREINIT:
1718 dMY_CXT;
045291aa 1719 ALIAS: FETCHSIZE = 1
a0d0e21e 1720 CODE:
8e07c86e 1721 CurrentDB = db ;
b76802f5 1722 RETVAL = GetArrayLength(aTHX_ db) ;
a0d0e21e 1723 OUTPUT:
1724 RETVAL
1725
1726
1727#
1728# Now provide an interface to the rest of the DB functionality
1729#
1730
1731int
1732db_del(db, key, flags=0)
1733 DB_File db
1734 DBTKEY key
1735 u_int flags
df3728a2 1736 PREINIT:
1737 dMY_CXT;
1f70e1ea 1738 CODE:
8e07c86e 1739 CurrentDB = db ;
1f70e1ea 1740 RETVAL = db_del(db, key, flags) ;
1741#ifdef DB_VERSION_MAJOR
1742 if (RETVAL > 0)
1743 RETVAL = -1 ;
1744 else if (RETVAL == DB_NOTFOUND)
1745 RETVAL = 1 ;
1746#endif
1747 OUTPUT:
1748 RETVAL
a0d0e21e 1749
1750
1751int
1752db_get(db, key, value, flags=0)
1753 DB_File db
1754 DBTKEY key
a6ed719b 1755 DBT value = NO_INIT
a0d0e21e 1756 u_int flags
df3728a2 1757 PREINIT:
1758 dMY_CXT;
1f70e1ea 1759 CODE:
8e07c86e 1760 CurrentDB = db ;
ccb44e3b 1761 DBT_clear(value) ;
1f70e1ea 1762 RETVAL = db_get(db, key, value, flags) ;
1763#ifdef DB_VERSION_MAJOR
1764 if (RETVAL > 0)
1765 RETVAL = -1 ;
1766 else if (RETVAL == DB_NOTFOUND)
1767 RETVAL = 1 ;
1768#endif
a0d0e21e 1769 OUTPUT:
1f70e1ea 1770 RETVAL
a0d0e21e 1771 value
1772
1773int
1774db_put(db, key, value, flags=0)
1775 DB_File db
1776 DBTKEY key
1777 DBT value
1778 u_int flags
df3728a2 1779 PREINIT:
1780 dMY_CXT;
1f70e1ea 1781 CODE:
8e07c86e 1782 CurrentDB = db ;
1f70e1ea 1783 RETVAL = db_put(db, key, value, flags) ;
1784#ifdef DB_VERSION_MAJOR
1785 if (RETVAL > 0)
1786 RETVAL = -1 ;
1787 else if (RETVAL == DB_KEYEXIST)
1788 RETVAL = 1 ;
1789#endif
a0d0e21e 1790 OUTPUT:
1f70e1ea 1791 RETVAL
9d9477b1 1792 key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
a0d0e21e 1793
1794int
1795db_fd(db)
1796 DB_File db
df3728a2 1797 PREINIT:
07200f1b 1798 dMY_CXT ;
1f70e1ea 1799 CODE:
8e07c86e 1800 CurrentDB = db ;
1f70e1ea 1801#ifdef DB_VERSION_MAJOR
1802 RETVAL = -1 ;
497b47a8 1803 {
1804 int status = 0 ;
1805 status = (db->in_memory
1806 ? -1
1807 : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
1808 if (status != 0)
1809 RETVAL = -1 ;
1810 }
1f70e1ea 1811#else
1812 RETVAL = (db->in_memory
1813 ? -1
1814 : ((db->dbp)->fd)(db->dbp) ) ;
1815#endif
1816 OUTPUT:
1817 RETVAL
a0d0e21e 1818
1819int
1820db_sync(db, flags=0)
1821 DB_File db
1822 u_int flags
df3728a2 1823 PREINIT:
1824 dMY_CXT;
1f70e1ea 1825 CODE:
8e07c86e 1826 CurrentDB = db ;
1f70e1ea 1827 RETVAL = db_sync(db, flags) ;
1828#ifdef DB_VERSION_MAJOR
1829 if (RETVAL > 0)
1830 RETVAL = -1 ;
1831#endif
1832 OUTPUT:
1833 RETVAL
a0d0e21e 1834
1835
1836int
1837db_seq(db, key, value, flags)
1838 DB_File db
1839 DBTKEY key
a6ed719b 1840 DBT value = NO_INIT
a0d0e21e 1841 u_int flags
df3728a2 1842 PREINIT:
1843 dMY_CXT;
1f70e1ea 1844 CODE:
8e07c86e 1845 CurrentDB = db ;
ccb44e3b 1846 DBT_clear(value) ;
1f70e1ea 1847 RETVAL = db_seq(db, key, value, flags);
1848#ifdef DB_VERSION_MAJOR
1849 if (RETVAL > 0)
1850 RETVAL = -1 ;
1851 else if (RETVAL == DB_NOTFOUND)
1852 RETVAL = 1 ;
1853#endif
a0d0e21e 1854 OUTPUT:
1f70e1ea 1855 RETVAL
a0d0e21e 1856 key
1857 value
610ab055 1858
9fe6733a 1859#ifdef DBM_FILTERING
1860
1861#define setFilter(type) \
1862 { \
1863 if (db->type) \
cad2e5aa 1864 RETVAL = sv_mortalcopy(db->type) ; \
1865 ST(0) = RETVAL ; \
9fe6733a 1866 if (db->type && (code == &PL_sv_undef)) { \
1867 SvREFCNT_dec(db->type) ; \
1868 db->type = NULL ; \
1869 } \
1870 else if (code) { \
1871 if (db->type) \
1872 sv_setsv(db->type, code) ; \
1873 else \
1874 db->type = newSVsv(code) ; \
1875 } \
1876 }
1877
1878
1879SV *
1880filter_fetch_key(db, code)
1881 DB_File db
1882 SV * code
1883 SV * RETVAL = &PL_sv_undef ;
1884 CODE:
1885 setFilter(filter_fetch_key) ;
9fe6733a 1886
1887SV *
1888filter_store_key(db, code)
1889 DB_File db
1890 SV * code
1891 SV * RETVAL = &PL_sv_undef ;
1892 CODE:
1893 setFilter(filter_store_key) ;
9fe6733a 1894
1895SV *
1896filter_fetch_value(db, code)
1897 DB_File db
1898 SV * code
1899 SV * RETVAL = &PL_sv_undef ;
1900 CODE:
1901 setFilter(filter_fetch_value) ;
9fe6733a 1902
1903SV *
1904filter_store_value(db, code)
1905 DB_File db
1906 SV * code
1907 SV * RETVAL = &PL_sv_undef ;
1908 CODE:
1909 setFilter(filter_store_value) ;
9fe6733a 1910
1911#endif /* DBM_FILTERING */