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