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