This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
integrate change#3115 from maint-5.005
[perl5.git] / ext / DB_File / DB_File.xs
CommitLineData
a0d0e21e
LW
1/*
2
3 DB_File.xs -- Perl 5 interface to Berkeley DB
4
6ca2e664 5 written by Paul Marquess <Paul.Marquess@btinternet.com>
ca63f0d2
GS
6 last modified 6th March 1999
7 version 1.65
a0d0e21e
LW
8
9 All comments/suggestions/problems are welcome
10
20896112 11 Copyright (c) 1995-9 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
LW
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
PM
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
PM
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
PM
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
PM
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
PM
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
PM
57 1.59 - No change to DB_File.xs
58 1.60 - Some code tidy up
9d9477b1
PM
59 1.61 - added flagSet macro for DB 2.5.x
60 fixed typo in O_RDONLY test.
6ca2e664
PM
61 1.62 - No change to DB_File.xs
62 1.63 - Fix to alllow DB 2.6.x to build.
20896112
PM
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
GS
66 1.65 - Fixed a bug in the PUSH logic.
67 Added BOOT check that using 2.3.4 or greater
1f70e1ea
PM
68
69
f6b705ef 70
a0d0e21e
LW
71*/
72
73#include "EXTERN.h"
74#include "perl.h"
75#include "XSUB.h"
76
cceca5ed
GS
77#ifndef PERL_VERSION
78#include "patchlevel.h"
20896112
PM
79#define PERL_REVISION 5
80#define PERL_VERSION PATCHLEVEL
81#define PERL_SUBVERSION SUBVERSION
82#endif
83
84#if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 ))
85
86# define PL_sv_undef sv_undef
87# define PL_na na
88
cceca5ed
GS
89#endif
90
52e1cb5e
JH
91/* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
92 * shortly #included by the <db.h>) __attribute__ to the possibly
93 * already defined __attribute__, for example by GNUC or by Perl. */
1f70e1ea 94
52e1cb5e
JH
95#undef __attribute__
96
045291aa
PM
97/* If Perl has been compiled with Threads support,the symbol op will
98 be defined here. This clashes with a field name in db.h, so get rid of it.
99 */
100#ifdef op
101#undef op
102#endif
a0d0e21e
LW
103#include <db.h>
104
105#include <fcntl.h>
106
1f70e1ea
PM
107/* #define TRACE */
108
109
110
111#ifdef DB_VERSION_MAJOR
112
113/* map version 2 features & constants onto their version 1 equivalent */
114
115#ifdef DB_Prefix_t
116#undef DB_Prefix_t
117#endif
118#define DB_Prefix_t size_t
119
120#ifdef DB_Hash_t
121#undef DB_Hash_t
122#endif
123#define DB_Hash_t u_int32_t
124
125/* DBTYPE stays the same */
126/* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
127typedef DB_INFO INFO ;
128
129/* version 2 has db_recno_t in place of recno_t */
130typedef db_recno_t recno_t;
131
132
133#define R_CURSOR DB_SET_RANGE
134#define R_FIRST DB_FIRST
135#define R_IAFTER DB_AFTER
136#define R_IBEFORE DB_BEFORE
137#define R_LAST DB_LAST
138#define R_NEXT DB_NEXT
139#define R_NOOVERWRITE DB_NOOVERWRITE
140#define R_PREV DB_PREV
141#define R_SETCURSOR 0
142#define R_RECNOSYNC 0
143#define R_FIXEDLEN DB_FIXEDLEN
144#define R_DUP DB_DUP
145
146#define db_HA_hash h_hash
147#define db_HA_ffactor h_ffactor
148#define db_HA_nelem h_nelem
149#define db_HA_bsize db_pagesize
150#define db_HA_cachesize db_cachesize
151#define db_HA_lorder db_lorder
152
153#define db_BT_compare bt_compare
154#define db_BT_prefix bt_prefix
155#define db_BT_flags flags
156#define db_BT_psize db_pagesize
157#define db_BT_cachesize db_cachesize
158#define db_BT_lorder db_lorder
159#define db_BT_maxkeypage
160#define db_BT_minkeypage
161
162
163#define db_RE_reclen re_len
164#define db_RE_flags flags
165#define db_RE_bval re_pad
166#define db_RE_bfname re_source
167#define db_RE_psize db_pagesize
168#define db_RE_cachesize db_cachesize
169#define db_RE_lorder db_lorder
170
171#define TXN NULL,
172
173#define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
174
175
176#define DBT_flags(x) x.flags = 0
177#define DB_flags(x, v) x |= v
178
9d9477b1
PM
179#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
180#define flagSet(flags, bitmask) ((flags) & (bitmask))
181#else
182#define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (bitmask))
183#endif
184
1f70e1ea
PM
185#else /* db version 1.x */
186
187typedef union INFO {
188 HASHINFO hash ;
189 RECNOINFO recno ;
190 BTREEINFO btree ;
191 } INFO ;
192
193
610ab055
PM
194#ifdef mDB_Prefix_t
195#ifdef DB_Prefix_t
196#undef DB_Prefix_t
197#endif
198#define DB_Prefix_t mDB_Prefix_t
199#endif
200
201#ifdef mDB_Hash_t
202#ifdef DB_Hash_t
203#undef DB_Hash_t
204#endif
205#define DB_Hash_t mDB_Hash_t
206#endif
207
1f70e1ea
PM
208#define db_HA_hash hash.hash
209#define db_HA_ffactor hash.ffactor
210#define db_HA_nelem hash.nelem
211#define db_HA_bsize hash.bsize
212#define db_HA_cachesize hash.cachesize
213#define db_HA_lorder hash.lorder
214
215#define db_BT_compare btree.compare
216#define db_BT_prefix btree.prefix
217#define db_BT_flags btree.flags
218#define db_BT_psize btree.psize
219#define db_BT_cachesize btree.cachesize
220#define db_BT_lorder btree.lorder
221#define db_BT_maxkeypage btree.maxkeypage
222#define db_BT_minkeypage btree.minkeypage
223
224#define db_RE_reclen recno.reclen
225#define db_RE_flags recno.flags
226#define db_RE_bval recno.bval
227#define db_RE_bfname recno.bfname
228#define db_RE_psize recno.psize
229#define db_RE_cachesize recno.cachesize
230#define db_RE_lorder recno.lorder
231
232#define TXN
233
234#define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
235#define DBT_flags(x)
236#define DB_flags(x, v)
9d9477b1 237#define flagSet(flags, bitmask) ((flags) & (bitmask))
1f70e1ea
PM
238
239#endif /* db version 1 */
240
241
242
243#define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, flags)
244#define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, flags)
245#define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
246
247#define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
248#define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
9d9477b1 249
1f70e1ea
PM
250#ifdef DB_VERSION_MAJOR
251#define db_DESTROY(db) ((db->dbp)->close)(db->dbp, 0)
252#define db_close(db) ((db->dbp)->close)(db->dbp, 0)
9d9477b1 253#define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \
1f70e1ea
PM
254 ? ((db->cursor)->c_del)(db->cursor, 0) \
255 : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
256
257#else
258
259#define db_DESTROY(db) ((db->dbp)->close)(db->dbp)
260#define db_close(db) ((db->dbp)->close)(db->dbp)
261#define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
262#define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
263
264#endif
265
9d9477b1 266
1f70e1ea 267#define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
610ab055 268
8e07c86e
AD
269typedef struct {
270 DBTYPE type ;
271 DB * dbp ;
272 SV * compare ;
273 SV * prefix ;
274 SV * hash ;
a0b8c8c1 275 int in_memory ;
1f70e1ea
PM
276 INFO info ;
277#ifdef DB_VERSION_MAJOR
278 DBC * cursor ;
279#endif
8e07c86e
AD
280 } DB_File_type;
281
282typedef DB_File_type * DB_File ;
a0d0e21e
LW
283typedef DBT DBTKEY ;
284
045291aa 285#define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
a0d0e21e 286
88108326 287#define OutputValue(arg, name) \
288 { if (RETVAL == 0) { \
045291aa 289 my_sv_setpvn(arg, name.data, name.size) ; \
88108326 290 } \
291 }
a0d0e21e
LW
292
293#define OutputKey(arg, name) \
1f70e1ea 294 { if (RETVAL == 0) \
a0d0e21e 295 { \
88108326 296 if (db->type != DB_RECNO) { \
045291aa 297 my_sv_setpvn(arg, name.data, name.size); \
88108326 298 } \
a0d0e21e
LW
299 else \
300 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
301 } \
302 }
303
045291aa 304
a0d0e21e 305/* Internal Global Data */
8e07c86e 306static recno_t Value ;
8e07c86e 307static recno_t zero = 0 ;
1f70e1ea
PM
308static DB_File CurrentDB ;
309static DBTKEY empty ;
310
311#ifdef DB_VERSION_MAJOR
312
313static int
314db_put(db, key, value, flags)
315DB_File db ;
316DBTKEY key ;
317DBT value ;
318u_int flags ;
319
320{
321 int status ;
322
9d9477b1 323 if (flagSet(flags, R_CURSOR)) {
1f70e1ea
PM
324 status = ((db->cursor)->c_del)(db->cursor, 0);
325 if (status != 0)
326 return status ;
327
9d9477b1 328#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
1f70e1ea 329 flags &= ~R_CURSOR ;
9d9477b1
PM
330#else
331 flags &= ~DB_OPFLAGS_MASK ;
332#endif
333
1f70e1ea
PM
334 }
335
336 return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
337
338}
339
340#endif /* DB_VERSION_MAJOR */
341
342static void
343GetVersionInfo()
344{
345 SV * ver_sv = perl_get_sv("DB_File::db_version", TRUE) ;
346#ifdef DB_VERSION_MAJOR
347 int Major, Minor, Patch ;
348
349 (void)db_version(&Major, &Minor, &Patch) ;
350
ca63f0d2
GS
351 /* check that libdb is recent enough -- we need 2.3.4 or greater */
352 if (Major == 2 && (Minor < 3 || (Minor == 3 && Patch < 4)))
353 croak("DB_File needs Berkeley DB 2.3.4 or greater, you have %d.%d.%d\n",
1f70e1ea
PM
354 Major, Minor, Patch) ;
355
cceca5ed 356#if PERL_VERSION > 3
1f70e1ea
PM
357 sv_setpvf(ver_sv, "%d.%d", Major, Minor) ;
358#else
359 {
360 char buffer[40] ;
361 sprintf(buffer, "%d.%d", Major, Minor) ;
362 sv_setpv(ver_sv, buffer) ;
363 }
364#endif
365
366#else
367 sv_setiv(ver_sv, 1) ;
368#endif
369
370}
a0d0e21e
LW
371
372
373static int
374btree_compare(key1, key2)
375const DBT * key1 ;
376const DBT * key2 ;
377{
378 dSP ;
379 void * data1, * data2 ;
380 int retval ;
381 int count ;
382
383 data1 = key1->data ;
384 data2 = key2->data ;
385
386 /* As newSVpv will assume that the data pointer is a null terminated C
387 string if the size parameter is 0, make sure that data points to an
388 empty string if the length is 0
389 */
390 if (key1->size == 0)
391 data1 = "" ;
392 if (key2->size == 0)
393 data2 = "" ;
394
395 ENTER ;
396 SAVETMPS;
397
924508f0
GS
398 PUSHMARK(SP) ;
399 EXTEND(SP,2) ;
a0d0e21e
LW
400 PUSHs(sv_2mortal(newSVpv(data1,key1->size)));
401 PUSHs(sv_2mortal(newSVpv(data2,key2->size)));
402 PUTBACK ;
403
8e07c86e 404 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
a0d0e21e
LW
405
406 SPAGAIN ;
407
408 if (count != 1)
ff0cee69 409 croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
a0d0e21e
LW
410
411 retval = POPi ;
412
413 PUTBACK ;
414 FREETMPS ;
415 LEAVE ;
416 return (retval) ;
417
418}
419
ecfc5424 420static DB_Prefix_t
a0d0e21e
LW
421btree_prefix(key1, key2)
422const DBT * key1 ;
423const DBT * key2 ;
424{
425 dSP ;
426 void * data1, * data2 ;
427 int retval ;
428 int count ;
429
430 data1 = key1->data ;
431 data2 = key2->data ;
432
433 /* As newSVpv will assume that the data pointer is a null terminated C
434 string if the size parameter is 0, make sure that data points to an
435 empty string if the length is 0
436 */
437 if (key1->size == 0)
438 data1 = "" ;
439 if (key2->size == 0)
440 data2 = "" ;
441
442 ENTER ;
443 SAVETMPS;
444
924508f0
GS
445 PUSHMARK(SP) ;
446 EXTEND(SP,2) ;
a0d0e21e
LW
447 PUSHs(sv_2mortal(newSVpv(data1,key1->size)));
448 PUSHs(sv_2mortal(newSVpv(data2,key2->size)));
449 PUTBACK ;
450
8e07c86e 451 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
a0d0e21e
LW
452
453 SPAGAIN ;
454
455 if (count != 1)
ff0cee69 456 croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
a0d0e21e
LW
457
458 retval = POPi ;
459
460 PUTBACK ;
461 FREETMPS ;
462 LEAVE ;
463
464 return (retval) ;
465}
466
ecfc5424 467static DB_Hash_t
a0d0e21e
LW
468hash_cb(data, size)
469const void * data ;
470size_t size ;
471{
472 dSP ;
473 int retval ;
474 int count ;
475
476 if (size == 0)
477 data = "" ;
478
610ab055
PM
479 /* DGH - Next two lines added to fix corrupted stack problem */
480 ENTER ;
481 SAVETMPS;
482
924508f0 483 PUSHMARK(SP) ;
610ab055 484
a0d0e21e
LW
485 XPUSHs(sv_2mortal(newSVpv((char*)data,size)));
486 PUTBACK ;
487
8e07c86e 488 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
a0d0e21e
LW
489
490 SPAGAIN ;
491
492 if (count != 1)
ff0cee69 493 croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
a0d0e21e
LW
494
495 retval = POPi ;
496
497 PUTBACK ;
498 FREETMPS ;
499 LEAVE ;
500
501 return (retval) ;
502}
503
504
505#ifdef TRACE
506
507static void
508PrintHash(hash)
1f70e1ea 509INFO * hash ;
a0d0e21e
LW
510{
511 printf ("HASH Info\n") ;
1f70e1ea
PM
512 printf (" hash = %s\n",
513 (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
514 printf (" bsize = %d\n", hash->db_HA_bsize) ;
515 printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
516 printf (" nelem = %d\n", hash->db_HA_nelem) ;
517 printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
518 printf (" lorder = %d\n", hash->db_HA_lorder) ;
a0d0e21e
LW
519
520}
521
522static void
523PrintRecno(recno)
1f70e1ea 524INFO * recno ;
a0d0e21e
LW
525{
526 printf ("RECNO Info\n") ;
1f70e1ea
PM
527 printf (" flags = %d\n", recno->db_RE_flags) ;
528 printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
529 printf (" psize = %d\n", recno->db_RE_psize) ;
530 printf (" lorder = %d\n", recno->db_RE_lorder) ;
531 printf (" reclen = %ul\n", (unsigned long)recno->db_RE_reclen) ;
532 printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
533 printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
a0d0e21e
LW
534}
535
ff68c719 536static void
a0d0e21e 537PrintBtree(btree)
1f70e1ea 538INFO * btree ;
a0d0e21e
LW
539{
540 printf ("BTREE Info\n") ;
1f70e1ea
PM
541 printf (" compare = %s\n",
542 (btree->db_BT_compare ? "redefined" : "default")) ;
543 printf (" prefix = %s\n",
544 (btree->db_BT_prefix ? "redefined" : "default")) ;
545 printf (" flags = %d\n", btree->db_BT_flags) ;
546 printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
547 printf (" psize = %d\n", btree->db_BT_psize) ;
548#ifndef DB_VERSION_MAJOR
549 printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
550 printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
551#endif
552 printf (" lorder = %d\n", btree->db_BT_lorder) ;
a0d0e21e
LW
553}
554
555#else
556
557#define PrintRecno(recno)
558#define PrintHash(hash)
559#define PrintBtree(btree)
560
561#endif /* TRACE */
562
563
564static I32
565GetArrayLength(db)
1f70e1ea 566DB_File db ;
a0d0e21e
LW
567{
568 DBT key ;
569 DBT value ;
570 int RETVAL ;
571
1f70e1ea
PM
572 DBT_flags(key) ;
573 DBT_flags(value) ;
574 RETVAL = do_SEQ(db, key, value, R_LAST) ;
a0d0e21e
LW
575 if (RETVAL == 0)
576 RETVAL = *(I32 *)key.data ;
1f70e1ea 577 else /* No key means empty file */
a0d0e21e
LW
578 RETVAL = 0 ;
579
a0b8c8c1 580 return ((I32)RETVAL) ;
a0d0e21e
LW
581}
582
88108326 583static recno_t
584GetRecnoKey(db, value)
585DB_File db ;
586I32 value ;
587{
588 if (value < 0) {
589 /* Get the length of the array */
1f70e1ea 590 I32 length = GetArrayLength(db) ;
88108326 591
592 /* check for attempt to write before start of array */
593 if (length + value + 1 <= 0)
ff0cee69 594 croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
88108326 595
596 value = length + value + 1 ;
597 }
598 else
599 ++ value ;
600
601 return value ;
a0d0e21e
LW
602}
603
604static DB_File
05475680
PM
605ParseOpenInfo(isHASH, name, flags, mode, sv)
606int isHASH ;
a0d0e21e
LW
607char * name ;
608int flags ;
609int mode ;
610SV * sv ;
a0d0e21e
LW
611{
612 SV ** svp;
613 HV * action ;
045291aa 614 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
a0d0e21e 615 void * openinfo = NULL ;
045291aa 616 INFO * info = &RETVAL->info ;
2d8e6c8d 617 STRLEN n_a;
1f70e1ea
PM
618
619/* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
045291aa 620 Zero(RETVAL, 1, DB_File_type) ;
a0d0e21e 621
88108326 622 /* Default to HASH */
8e07c86e
AD
623 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
624 RETVAL->type = DB_HASH ;
a0d0e21e 625
610ab055
PM
626 /* DGH - Next line added to avoid SEGV on existing hash DB */
627 CurrentDB = RETVAL;
628
a0b8c8c1
PM
629 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
630 RETVAL->in_memory = (name == NULL) ;
631
a0d0e21e
LW
632 if (sv)
633 {
634 if (! SvROK(sv) )
635 croak ("type parameter is not a reference") ;
636
36477c24 637 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
638 if (svp && SvOK(*svp))
639 action = (HV*) SvRV(*svp) ;
640 else
641 croak("internal error") ;
610ab055 642
a0d0e21e
LW
643 if (sv_isa(sv, "DB_File::HASHINFO"))
644 {
05475680
PM
645
646 if (!isHASH)
647 croak("DB_File can only tie an associative array to a DB_HASH database") ;
648
8e07c86e 649 RETVAL->type = DB_HASH ;
610ab055 650 openinfo = (void*)info ;
a0d0e21e
LW
651
652 svp = hv_fetch(action, "hash", 4, FALSE);
653
654 if (svp && SvOK(*svp))
655 {
1f70e1ea 656 info->db_HA_hash = hash_cb ;
8e07c86e 657 RETVAL->hash = newSVsv(*svp) ;
a0d0e21e
LW
658 }
659 else
1f70e1ea 660 info->db_HA_hash = NULL ;
a0d0e21e 661
a0d0e21e 662 svp = hv_fetch(action, "ffactor", 7, FALSE);
1f70e1ea 663 info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
a0d0e21e
LW
664
665 svp = hv_fetch(action, "nelem", 5, FALSE);
1f70e1ea 666 info->db_HA_nelem = svp ? SvIV(*svp) : 0;
a0d0e21e 667
1f70e1ea
PM
668 svp = hv_fetch(action, "bsize", 5, FALSE);
669 info->db_HA_bsize = svp ? SvIV(*svp) : 0;
670
a0d0e21e 671 svp = hv_fetch(action, "cachesize", 9, FALSE);
1f70e1ea 672 info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
a0d0e21e
LW
673
674 svp = hv_fetch(action, "lorder", 6, FALSE);
1f70e1ea 675 info->db_HA_lorder = svp ? SvIV(*svp) : 0;
a0d0e21e
LW
676
677 PrintHash(info) ;
678 }
679 else if (sv_isa(sv, "DB_File::BTREEINFO"))
680 {
05475680
PM
681 if (!isHASH)
682 croak("DB_File can only tie an associative array to a DB_BTREE database");
683
8e07c86e 684 RETVAL->type = DB_BTREE ;
610ab055 685 openinfo = (void*)info ;
a0d0e21e
LW
686
687 svp = hv_fetch(action, "compare", 7, FALSE);
688 if (svp && SvOK(*svp))
689 {
1f70e1ea 690 info->db_BT_compare = btree_compare ;
8e07c86e 691 RETVAL->compare = newSVsv(*svp) ;
a0d0e21e
LW
692 }
693 else
1f70e1ea 694 info->db_BT_compare = NULL ;
a0d0e21e
LW
695
696 svp = hv_fetch(action, "prefix", 6, FALSE);
697 if (svp && SvOK(*svp))
698 {
1f70e1ea 699 info->db_BT_prefix = btree_prefix ;
8e07c86e 700 RETVAL->prefix = newSVsv(*svp) ;
a0d0e21e
LW
701 }
702 else
1f70e1ea 703 info->db_BT_prefix = NULL ;
a0d0e21e
LW
704
705 svp = hv_fetch(action, "flags", 5, FALSE);
1f70e1ea 706 info->db_BT_flags = svp ? SvIV(*svp) : 0;
a0d0e21e
LW
707
708 svp = hv_fetch(action, "cachesize", 9, FALSE);
1f70e1ea 709 info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
a0d0e21e 710
1f70e1ea 711#ifndef DB_VERSION_MAJOR
a0d0e21e 712 svp = hv_fetch(action, "minkeypage", 10, FALSE);
610ab055 713 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
a0d0e21e
LW
714
715 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
610ab055 716 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
1f70e1ea 717#endif
a0d0e21e
LW
718
719 svp = hv_fetch(action, "psize", 5, FALSE);
1f70e1ea 720 info->db_BT_psize = svp ? SvIV(*svp) : 0;
a0d0e21e
LW
721
722 svp = hv_fetch(action, "lorder", 6, FALSE);
1f70e1ea 723 info->db_BT_lorder = svp ? SvIV(*svp) : 0;
a0d0e21e
LW
724
725 PrintBtree(info) ;
726
727 }
728 else if (sv_isa(sv, "DB_File::RECNOINFO"))
729 {
05475680
PM
730 if (isHASH)
731 croak("DB_File can only tie an array to a DB_RECNO database");
732
8e07c86e 733 RETVAL->type = DB_RECNO ;
610ab055 734 openinfo = (void *)info ;
a0d0e21e 735
1f70e1ea
PM
736 info->db_RE_flags = 0 ;
737
a0d0e21e 738 svp = hv_fetch(action, "flags", 5, FALSE);
1f70e1ea
PM
739 info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
740
741 svp = hv_fetch(action, "reclen", 6, FALSE);
742 info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
a0d0e21e
LW
743
744 svp = hv_fetch(action, "cachesize", 9, FALSE);
1f70e1ea 745 info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
a0d0e21e
LW
746
747 svp = hv_fetch(action, "psize", 5, FALSE);
1f70e1ea 748 info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
a0d0e21e
LW
749
750 svp = hv_fetch(action, "lorder", 6, FALSE);
1f70e1ea
PM
751 info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
752
753#ifdef DB_VERSION_MAJOR
754 info->re_source = name ;
755 name = NULL ;
756#endif
757 svp = hv_fetch(action, "bfname", 6, FALSE);
758 if (svp && SvOK(*svp)) {
2d8e6c8d 759 char * ptr = SvPV(*svp,n_a) ;
1f70e1ea 760#ifdef DB_VERSION_MAJOR
2d8e6c8d 761 name = (char*) n_a ? ptr : NULL ;
1f70e1ea 762#else
2d8e6c8d 763 info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
1f70e1ea
PM
764#endif
765 }
766 else
767#ifdef DB_VERSION_MAJOR
768 name = NULL ;
769#else
770 info->db_RE_bfname = NULL ;
771#endif
a0d0e21e
LW
772
773 svp = hv_fetch(action, "bval", 4, FALSE);
1f70e1ea 774#ifdef DB_VERSION_MAJOR
a0d0e21e
LW
775 if (svp && SvOK(*svp))
776 {
1f70e1ea 777 int value ;
a0d0e21e 778 if (SvPOK(*svp))
2d8e6c8d 779 value = (int)*SvPV(*svp, n_a) ;
a0d0e21e 780 else
1f70e1ea
PM
781 value = SvIV(*svp) ;
782
783 if (info->flags & DB_FIXEDLEN) {
784 info->re_pad = value ;
785 info->flags |= DB_PAD ;
786 }
787 else {
788 info->re_delim = value ;
789 info->flags |= DB_DELIMITER ;
790 }
791
792 }
793#else
794 if (svp && SvOK(*svp))
795 {
796 if (SvPOK(*svp))
2d8e6c8d 797 info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
1f70e1ea
PM
798 else
799 info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
800 DB_flags(info->flags, DB_DELIMITER) ;
801
a0d0e21e
LW
802 }
803 else
804 {
1f70e1ea
PM
805 if (info->db_RE_flags & R_FIXEDLEN)
806 info->db_RE_bval = (u_char) ' ' ;
a0d0e21e 807 else
1f70e1ea
PM
808 info->db_RE_bval = (u_char) '\n' ;
809 DB_flags(info->flags, DB_DELIMITER) ;
a0d0e21e 810 }
1f70e1ea 811#endif
a0d0e21e 812
1f70e1ea
PM
813#ifdef DB_RENUMBER
814 info->flags |= DB_RENUMBER ;
815#endif
816
a0d0e21e
LW
817 PrintRecno(info) ;
818 }
819 else
820 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
821 }
822
823
88108326 824 /* OS2 Specific Code */
825#ifdef OS2
826#ifdef __EMX__
827 flags |= O_BINARY;
828#endif /* __EMX__ */
829#endif /* OS2 */
a0d0e21e 830
1f70e1ea
PM
831#ifdef DB_VERSION_MAJOR
832
833 {
834 int Flags = 0 ;
835 int status ;
836
837 /* Map 1.x flags to 2.x flags */
838 if ((flags & O_CREAT) == O_CREAT)
839 Flags |= DB_CREATE ;
840
1f70e1ea
PM
841#if O_RDONLY == 0
842 if (flags == O_RDONLY)
843#else
20896112 844 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1f70e1ea
PM
845#endif
846 Flags |= DB_RDONLY ;
847
20896112 848#ifdef O_TRUNC
1f70e1ea
PM
849 if ((flags & O_TRUNC) == O_TRUNC)
850 Flags |= DB_TRUNCATE ;
851#endif
852
853 status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
854 if (status == 0)
6ca2e664 855#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
1f70e1ea 856 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
6ca2e664
PM
857#else
858 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
859 0) ;
860#endif
1f70e1ea
PM
861
862 if (status)
863 RETVAL->dbp = NULL ;
864
865 }
866#else
88108326 867 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
1f70e1ea 868#endif
a0d0e21e
LW
869
870 return (RETVAL) ;
871}
872
873
874static int
875not_here(s)
876char *s;
877{
878 croak("DB_File::%s not implemented on this architecture", s);
879 return -1;
880}
881
882static double
883constant(name, arg)
884char *name;
885int arg;
886{
887 errno = 0;
888 switch (*name) {
889 case 'A':
890 break;
891 case 'B':
892 if (strEQ(name, "BTREEMAGIC"))
893#ifdef BTREEMAGIC
894 return BTREEMAGIC;
895#else
896 goto not_there;
897#endif
898 if (strEQ(name, "BTREEVERSION"))
899#ifdef BTREEVERSION
900 return BTREEVERSION;
901#else
902 goto not_there;
903#endif
904 break;
905 case 'C':
906 break;
907 case 'D':
908 if (strEQ(name, "DB_LOCK"))
909#ifdef DB_LOCK
910 return DB_LOCK;
911#else
912 goto not_there;
913#endif
914 if (strEQ(name, "DB_SHMEM"))
915#ifdef DB_SHMEM
916 return DB_SHMEM;
917#else
918 goto not_there;
919#endif
920 if (strEQ(name, "DB_TXN"))
921#ifdef DB_TXN
922 return (U32)DB_TXN;
923#else
924 goto not_there;
925#endif
926 break;
927 case 'E':
928 break;
929 case 'F':
930 break;
931 case 'G':
932 break;
933 case 'H':
934 if (strEQ(name, "HASHMAGIC"))
935#ifdef HASHMAGIC
936 return HASHMAGIC;
937#else
938 goto not_there;
939#endif
940 if (strEQ(name, "HASHVERSION"))
941#ifdef HASHVERSION
942 return HASHVERSION;
943#else
944 goto not_there;
945#endif
946 break;
947 case 'I':
948 break;
949 case 'J':
950 break;
951 case 'K':
952 break;
953 case 'L':
954 break;
955 case 'M':
956 if (strEQ(name, "MAX_PAGE_NUMBER"))
957#ifdef MAX_PAGE_NUMBER
958 return (U32)MAX_PAGE_NUMBER;
959#else
960 goto not_there;
961#endif
962 if (strEQ(name, "MAX_PAGE_OFFSET"))
963#ifdef MAX_PAGE_OFFSET
964 return MAX_PAGE_OFFSET;
965#else
966 goto not_there;
967#endif
968 if (strEQ(name, "MAX_REC_NUMBER"))
969#ifdef MAX_REC_NUMBER
970 return (U32)MAX_REC_NUMBER;
971#else
972 goto not_there;
973#endif
974 break;
975 case 'N':
976 break;
977 case 'O':
978 break;
979 case 'P':
980 break;
981 case 'Q':
982 break;
983 case 'R':
984 if (strEQ(name, "RET_ERROR"))
985#ifdef RET_ERROR
986 return RET_ERROR;
987#else
988 goto not_there;
989#endif
990 if (strEQ(name, "RET_SPECIAL"))
991#ifdef RET_SPECIAL
992 return RET_SPECIAL;
993#else
994 goto not_there;
995#endif
996 if (strEQ(name, "RET_SUCCESS"))
997#ifdef RET_SUCCESS
998 return RET_SUCCESS;
999#else
1000 goto not_there;
1001#endif
1002 if (strEQ(name, "R_CURSOR"))
1003#ifdef R_CURSOR
1004 return R_CURSOR;
1005#else
1006 goto not_there;
1007#endif
1008 if (strEQ(name, "R_DUP"))
1009#ifdef R_DUP
1010 return R_DUP;
1011#else
1012 goto not_there;
1013#endif
1014 if (strEQ(name, "R_FIRST"))
1015#ifdef R_FIRST
1016 return R_FIRST;
1017#else
1018 goto not_there;
1019#endif
1020 if (strEQ(name, "R_FIXEDLEN"))
1021#ifdef R_FIXEDLEN
1022 return R_FIXEDLEN;
1023#else
1024 goto not_there;
1025#endif
1026 if (strEQ(name, "R_IAFTER"))
1027#ifdef R_IAFTER
1028 return R_IAFTER;
1029#else
1030 goto not_there;
1031#endif
1032 if (strEQ(name, "R_IBEFORE"))
1033#ifdef R_IBEFORE
1034 return R_IBEFORE;
1035#else
1036 goto not_there;
1037#endif
1038 if (strEQ(name, "R_LAST"))
1039#ifdef R_LAST
1040 return R_LAST;
1041#else
1042 goto not_there;
1043#endif
1044 if (strEQ(name, "R_NEXT"))
1045#ifdef R_NEXT
1046 return R_NEXT;
1047#else
1048 goto not_there;
1049#endif
1050 if (strEQ(name, "R_NOKEY"))
1051#ifdef R_NOKEY
1052 return R_NOKEY;
1053#else
1054 goto not_there;
1055#endif
1056 if (strEQ(name, "R_NOOVERWRITE"))
1057#ifdef R_NOOVERWRITE
1058 return R_NOOVERWRITE;
1059#else
1060 goto not_there;
1061#endif
1062 if (strEQ(name, "R_PREV"))
1063#ifdef R_PREV
1064 return R_PREV;
1065#else
1066 goto not_there;
1067#endif
1068 if (strEQ(name, "R_RECNOSYNC"))
1069#ifdef R_RECNOSYNC
1070 return R_RECNOSYNC;
1071#else
1072 goto not_there;
1073#endif
1074 if (strEQ(name, "R_SETCURSOR"))
1075#ifdef R_SETCURSOR
1076 return R_SETCURSOR;
1077#else
1078 goto not_there;
1079#endif
1080 if (strEQ(name, "R_SNAPSHOT"))
1081#ifdef R_SNAPSHOT
1082 return R_SNAPSHOT;
1083#else
1084 goto not_there;
1085#endif
1086 break;
1087 case 'S':
1088 break;
1089 case 'T':
1090 break;
1091 case 'U':
1092 break;
1093 case 'V':
1094 break;
1095 case 'W':
1096 break;
1097 case 'X':
1098 break;
1099 case 'Y':
1100 break;
1101 case 'Z':
1102 break;
1103 case '_':
a0d0e21e
LW
1104 break;
1105 }
1106 errno = EINVAL;
1107 return 0;
1108
1109not_there:
1110 errno = ENOENT;
1111 return 0;
1112}
1113
1114MODULE = DB_File PACKAGE = DB_File PREFIX = db_
1115
1f70e1ea
PM
1116BOOT:
1117 {
1118 GetVersionInfo() ;
1119
1120 empty.data = &zero ;
1121 empty.size = sizeof(recno_t) ;
1122 DBT_flags(empty) ;
1123 }
1124
a0d0e21e
LW
1125double
1126constant(name,arg)
1127 char * name
1128 int arg
1129
1130
1131DB_File
05475680
PM
1132db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
1133 int isHASH
a0d0e21e
LW
1134 char * dbtype
1135 int flags
1136 int mode
1137 CODE:
1138 {
1139 char * name = (char *) NULL ;
1140 SV * sv = (SV *) NULL ;
2d8e6c8d 1141 STRLEN n_a;
a0d0e21e 1142
05475680 1143 if (items >= 3 && SvOK(ST(2)))
2d8e6c8d 1144 name = (char*) SvPV(ST(2), n_a) ;
a0d0e21e 1145
05475680
PM
1146 if (items == 6)
1147 sv = ST(5) ;
a0d0e21e 1148
05475680 1149 RETVAL = ParseOpenInfo(isHASH, name, flags, mode, sv) ;
4633a7c4
LW
1150 if (RETVAL->dbp == NULL)
1151 RETVAL = NULL ;
a0d0e21e
LW
1152 }
1153 OUTPUT:
1154 RETVAL
1155
a0d0e21e
LW
1156int
1157db_DESTROY(db)
1158 DB_File db
8e07c86e
AD
1159 INIT:
1160 CurrentDB = db ;
1161 CLEANUP:
1162 if (db->hash)
1163 SvREFCNT_dec(db->hash) ;
1164 if (db->compare)
1165 SvREFCNT_dec(db->compare) ;
1166 if (db->prefix)
1167 SvREFCNT_dec(db->prefix) ;
1168 Safefree(db) ;
1f70e1ea
PM
1169#ifdef DB_VERSION_MAJOR
1170 if (RETVAL > 0)
1171 RETVAL = -1 ;
1172#endif
a0d0e21e
LW
1173
1174
1175int
1176db_DELETE(db, key, flags=0)
1177 DB_File db
1178 DBTKEY key
1179 u_int flags
8e07c86e
AD
1180 INIT:
1181 CurrentDB = db ;
a0d0e21e 1182
f6b705ef 1183
1184int
1185db_EXISTS(db, key)
1186 DB_File db
1187 DBTKEY key
1188 CODE:
1189 {
1190 DBT value ;
1191
1f70e1ea 1192 DBT_flags(value) ;
f6b705ef 1193 CurrentDB = db ;
1f70e1ea 1194 RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
f6b705ef 1195 }
1196 OUTPUT:
1197 RETVAL
1198
a0d0e21e
LW
1199int
1200db_FETCH(db, key, flags=0)
1201 DB_File db
1202 DBTKEY key
1203 u_int flags
1204 CODE:
1205 {
1f70e1ea 1206 DBT value ;
a0d0e21e 1207
1f70e1ea 1208 DBT_flags(value) ;
8e07c86e 1209 CurrentDB = db ;
1f70e1ea
PM
1210 /* RETVAL = ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) ; */
1211 RETVAL = db_get(db, key, value, flags) ;
a0d0e21e 1212 ST(0) = sv_newmortal();
a9fd575d 1213 OutputValue(ST(0), value)
a0d0e21e
LW
1214 }
1215
1216int
1217db_STORE(db, key, value, flags=0)
1218 DB_File db
1219 DBTKEY key
1220 DBT value
1221 u_int flags
8e07c86e
AD
1222 INIT:
1223 CurrentDB = db ;
a0d0e21e
LW
1224
1225
1226int
1227db_FIRSTKEY(db)
1228 DB_File db
1229 CODE:
1230 {
1f70e1ea 1231 DBTKEY key ;
a0d0e21e
LW
1232 DBT value ;
1233
1f70e1ea
PM
1234 DBT_flags(key) ;
1235 DBT_flags(value) ;
8e07c86e 1236 CurrentDB = db ;
1f70e1ea 1237 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
a0d0e21e 1238 ST(0) = sv_newmortal();
a9fd575d 1239 OutputKey(ST(0), key) ;
a0d0e21e
LW
1240 }
1241
1242int
1243db_NEXTKEY(db, key)
1244 DB_File db
1245 DBTKEY key
1246 CODE:
1247 {
1248 DBT value ;
1249
1f70e1ea 1250 DBT_flags(value) ;
8e07c86e 1251 CurrentDB = db ;
1f70e1ea 1252 RETVAL = do_SEQ(db, key, value, R_NEXT) ;
a0d0e21e 1253 ST(0) = sv_newmortal();
a9fd575d 1254 OutputKey(ST(0), key) ;
a0d0e21e
LW
1255 }
1256
1257#
1258# These would be nice for RECNO
1259#
1260
1261int
1262unshift(db, ...)
1263 DB_File db
045291aa 1264 ALIAS: UNSHIFT = 1
a0d0e21e
LW
1265 CODE:
1266 {
1267 DBTKEY key ;
1268 DBT value ;
1269 int i ;
1270 int One ;
4633a7c4 1271 DB * Db = db->dbp ;
2d8e6c8d 1272 STRLEN n_a;
a0d0e21e 1273
1f70e1ea
PM
1274 DBT_flags(key) ;
1275 DBT_flags(value) ;
8e07c86e 1276 CurrentDB = db ;
1f70e1ea
PM
1277#ifdef DB_VERSION_MAJOR
1278 /* get the first value */
1279 RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
1280 RETVAL = 0 ;
1281#else
a0d0e21e 1282 RETVAL = -1 ;
1f70e1ea 1283#endif
a0d0e21e
LW
1284 for (i = items-1 ; i > 0 ; --i)
1285 {
2d8e6c8d
GS
1286 value.data = SvPV(ST(i), n_a) ;
1287 value.size = n_a ;
a0d0e21e
LW
1288 One = 1 ;
1289 key.data = &One ;
1290 key.size = sizeof(int) ;
1f70e1ea
PM
1291#ifdef DB_VERSION_MAJOR
1292 RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
1293#else
4633a7c4 1294 RETVAL = (Db->put)(Db, &key, &value, R_IBEFORE) ;
1f70e1ea 1295#endif
a0d0e21e
LW
1296 if (RETVAL != 0)
1297 break;
1298 }
1299 }
1300 OUTPUT:
1301 RETVAL
1302
1303I32
1304pop(db)
1305 DB_File db
045291aa 1306 ALIAS: POP = 1
a0d0e21e
LW
1307 CODE:
1308 {
1309 DBTKEY key ;
1310 DBT value ;
1311
1f70e1ea
PM
1312 DBT_flags(key) ;
1313 DBT_flags(value) ;
8e07c86e 1314 CurrentDB = db ;
1f70e1ea 1315
a0d0e21e 1316 /* First get the final value */
1f70e1ea 1317 RETVAL = do_SEQ(db, key, value, R_LAST) ;
a0d0e21e
LW
1318 ST(0) = sv_newmortal();
1319 /* Now delete it */
1320 if (RETVAL == 0)
1321 {
f6b705ef 1322 /* the call to del will trash value, so take a copy now */
a9fd575d 1323 OutputValue(ST(0), value) ;
1f70e1ea 1324 RETVAL = db_del(db, key, R_CURSOR) ;
f6b705ef 1325 if (RETVAL != 0)
6b88bc9c 1326 sv_setsv(ST(0), &PL_sv_undef);
a0d0e21e
LW
1327 }
1328 }
1329
1330I32
1331shift(db)
1332 DB_File db
045291aa 1333 ALIAS: SHIFT = 1
a0d0e21e
LW
1334 CODE:
1335 {
a0d0e21e 1336 DBT value ;
f6b705ef 1337 DBTKEY key ;
a0d0e21e 1338
1f70e1ea
PM
1339 DBT_flags(key) ;
1340 DBT_flags(value) ;
8e07c86e 1341 CurrentDB = db ;
a0d0e21e 1342 /* get the first value */
1f70e1ea 1343 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
a0d0e21e
LW
1344 ST(0) = sv_newmortal();
1345 /* Now delete it */
1346 if (RETVAL == 0)
1347 {
f6b705ef 1348 /* the call to del will trash value, so take a copy now */
a9fd575d 1349 OutputValue(ST(0), value) ;
1f70e1ea 1350 RETVAL = db_del(db, key, R_CURSOR) ;
f6b705ef 1351 if (RETVAL != 0)
6b88bc9c 1352 sv_setsv (ST(0), &PL_sv_undef) ;
a0d0e21e
LW
1353 }
1354 }
1355
1356
1357I32
1358push(db, ...)
1359 DB_File db
045291aa 1360 ALIAS: PUSH = 1
a0d0e21e
LW
1361 CODE:
1362 {
1363 DBTKEY key ;
1364 DBT value ;
4633a7c4 1365 DB * Db = db->dbp ;
a0d0e21e 1366 int i ;
2d8e6c8d 1367 STRLEN n_a;
a0d0e21e 1368
1f70e1ea
PM
1369 DBT_flags(key) ;
1370 DBT_flags(value) ;
8e07c86e 1371 CurrentDB = db ;
1f70e1ea 1372#ifdef DB_VERSION_MAJOR
ca63f0d2
GS
1373 RETVAL = 0 ;
1374 key = empty ;
1f70e1ea
PM
1375 for (i = 1 ; i < items ; ++i)
1376 {
2d8e6c8d
GS
1377 value.data = SvPV(ST(i), n_a) ;
1378 value.size = n_a ;
ca63f0d2 1379 RETVAL = (Db->put)(Db, NULL, &key, &value, DB_APPEND) ;
1f70e1ea
PM
1380 if (RETVAL != 0)
1381 break;
1382 }
1383#else
ca63f0d2
GS
1384 /* Set the Cursor to the Last element */
1385 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1386 if (RETVAL >= 0)
1387 {
1388 if (RETVAL == 1)
1389 key = empty ;
8e07c86e
AD
1390 for (i = items - 1 ; i > 0 ; --i)
1391 {
2d8e6c8d
GS
1392 value.data = SvPV(ST(i), n_a) ;
1393 value.size = n_a ;
ca63f0d2 1394 RETVAL = (Db->put)(Db, &key, &value, R_IAFTER) ;
8e07c86e
AD
1395 if (RETVAL != 0)
1396 break;
1397 }
a0d0e21e 1398 }
ca63f0d2 1399#endif
a0d0e21e
LW
1400 }
1401 OUTPUT:
1402 RETVAL
1403
1404
1405I32
1406length(db)
1407 DB_File db
045291aa 1408 ALIAS: FETCHSIZE = 1
a0d0e21e 1409 CODE:
8e07c86e 1410 CurrentDB = db ;
1f70e1ea 1411 RETVAL = GetArrayLength(db) ;
a0d0e21e
LW
1412 OUTPUT:
1413 RETVAL
1414
1415
1416#
1417# Now provide an interface to the rest of the DB functionality
1418#
1419
1420int
1421db_del(db, key, flags=0)
1422 DB_File db
1423 DBTKEY key
1424 u_int flags
1f70e1ea 1425 CODE:
8e07c86e 1426 CurrentDB = db ;
1f70e1ea
PM
1427 RETVAL = db_del(db, key, flags) ;
1428#ifdef DB_VERSION_MAJOR
1429 if (RETVAL > 0)
1430 RETVAL = -1 ;
1431 else if (RETVAL == DB_NOTFOUND)
1432 RETVAL = 1 ;
1433#endif
1434 OUTPUT:
1435 RETVAL
a0d0e21e
LW
1436
1437
1438int
1439db_get(db, key, value, flags=0)
1440 DB_File db
1441 DBTKEY key
a6ed719b 1442 DBT value = NO_INIT
a0d0e21e 1443 u_int flags
1f70e1ea 1444 CODE:
8e07c86e 1445 CurrentDB = db ;
1f70e1ea
PM
1446 DBT_flags(value) ;
1447 RETVAL = db_get(db, key, value, flags) ;
1448#ifdef DB_VERSION_MAJOR
1449 if (RETVAL > 0)
1450 RETVAL = -1 ;
1451 else if (RETVAL == DB_NOTFOUND)
1452 RETVAL = 1 ;
1453#endif
a0d0e21e 1454 OUTPUT:
1f70e1ea 1455 RETVAL
a0d0e21e
LW
1456 value
1457
1458int
1459db_put(db, key, value, flags=0)
1460 DB_File db
1461 DBTKEY key
1462 DBT value
1463 u_int flags
1f70e1ea 1464 CODE:
8e07c86e 1465 CurrentDB = db ;
1f70e1ea
PM
1466 RETVAL = db_put(db, key, value, flags) ;
1467#ifdef DB_VERSION_MAJOR
1468 if (RETVAL > 0)
1469 RETVAL = -1 ;
1470 else if (RETVAL == DB_KEYEXIST)
1471 RETVAL = 1 ;
1472#endif
a0d0e21e 1473 OUTPUT:
1f70e1ea 1474 RETVAL
9d9477b1 1475 key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
a0d0e21e
LW
1476
1477int
1478db_fd(db)
1479 DB_File db
1f70e1ea
PM
1480 int status = 0 ;
1481 CODE:
8e07c86e 1482 CurrentDB = db ;
1f70e1ea
PM
1483#ifdef DB_VERSION_MAJOR
1484 RETVAL = -1 ;
1485 status = (db->in_memory
1486 ? -1
1487 : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
1488 if (status != 0)
1489 RETVAL = -1 ;
1490#else
1491 RETVAL = (db->in_memory
1492 ? -1
1493 : ((db->dbp)->fd)(db->dbp) ) ;
1494#endif
1495 OUTPUT:
1496 RETVAL
a0d0e21e
LW
1497
1498int
1499db_sync(db, flags=0)
1500 DB_File db
1501 u_int flags
1f70e1ea 1502 CODE:
8e07c86e 1503 CurrentDB = db ;
1f70e1ea
PM
1504 RETVAL = db_sync(db, flags) ;
1505#ifdef DB_VERSION_MAJOR
1506 if (RETVAL > 0)
1507 RETVAL = -1 ;
1508#endif
1509 OUTPUT:
1510 RETVAL
a0d0e21e
LW
1511
1512
1513int
1514db_seq(db, key, value, flags)
1515 DB_File db
1516 DBTKEY key
a6ed719b 1517 DBT value = NO_INIT
a0d0e21e 1518 u_int flags
1f70e1ea 1519 CODE:
8e07c86e 1520 CurrentDB = db ;
1f70e1ea
PM
1521 DBT_flags(value) ;
1522 RETVAL = db_seq(db, key, value, flags);
1523#ifdef DB_VERSION_MAJOR
1524 if (RETVAL > 0)
1525 RETVAL = -1 ;
1526 else if (RETVAL == DB_NOTFOUND)
1527 RETVAL = 1 ;
1528#endif
a0d0e21e 1529 OUTPUT:
1f70e1ea 1530 RETVAL
a0d0e21e
LW
1531 key
1532 value
610ab055 1533