3 DB_File.xs -- Perl 5 interface to Berkeley DB
5 written by Paul Marquess (pmarquess@bfsec.bt.co.uk)
6 last modified 20th Nov 1997
9 All comments/suggestions/problems are welcome
11 Copyright (c) 1995, 1996, 1997 Paul Marquess. All rights reserved.
12 This program is free software; you can redistribute it and/or
13 modify it under the same terms as Perl itself.
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.
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
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
34 1.06 - Minor namespace cleanup: Localized PrintBtree.
35 1.07 - Fixed bug with RECNO, where bval wasn't defaulting to "\n".
36 1.08 - No change to DB_File.xs
37 1.09 - Default mode for dbopen changed to 0666
38 1.10 - Fixed fd method so that it still returns -1 for
39 in-memory files when db 1.86 is used.
40 1.11 - No change to DB_File.xs
41 1.12 - No change to DB_File.xs
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
48 undefined value" warning with db_get and db_seq.
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
62 /* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
63 * shortly #included by the <db.h>) __attribute__ to the possibly
64 * already defined __attribute__, for example by GNUC or by Perl. */
76 #ifdef DB_VERSION_MAJOR
78 /* map version 2 features & constants onto their version 1 equivalent */
83 #define DB_Prefix_t size_t
88 #define DB_Hash_t u_int32_t
90 /* DBTYPE stays the same */
91 /* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
92 typedef DB_INFO INFO ;
94 /* version 2 has db_recno_t in place of recno_t */
95 typedef db_recno_t recno_t;
98 #define R_CURSOR DB_SET_RANGE
99 #define R_FIRST DB_FIRST
100 #define R_IAFTER DB_AFTER
101 #define R_IBEFORE DB_BEFORE
102 #define R_LAST DB_LAST
103 #define R_NEXT DB_NEXT
104 #define R_NOOVERWRITE DB_NOOVERWRITE
105 #define R_PREV DB_PREV
106 #define R_SETCURSOR 0
107 #define R_RECNOSYNC 0
108 #define R_FIXEDLEN DB_FIXEDLEN
111 #define db_HA_hash h_hash
112 #define db_HA_ffactor h_ffactor
113 #define db_HA_nelem h_nelem
114 #define db_HA_bsize db_pagesize
115 #define db_HA_cachesize db_cachesize
116 #define db_HA_lorder db_lorder
118 #define db_BT_compare bt_compare
119 #define db_BT_prefix bt_prefix
120 #define db_BT_flags flags
121 #define db_BT_psize db_pagesize
122 #define db_BT_cachesize db_cachesize
123 #define db_BT_lorder db_lorder
124 #define db_BT_maxkeypage
125 #define db_BT_minkeypage
128 #define db_RE_reclen re_len
129 #define db_RE_flags flags
130 #define db_RE_bval re_pad
131 #define db_RE_bfname re_source
132 #define db_RE_psize db_pagesize
133 #define db_RE_cachesize db_cachesize
134 #define db_RE_lorder db_lorder
138 #define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
141 #define DBT_flags(x) x.flags = 0
142 #define DB_flags(x, v) x |= v
144 #else /* db version 1.x */
157 #define DB_Prefix_t mDB_Prefix_t
164 #define DB_Hash_t mDB_Hash_t
167 #define db_HA_hash hash.hash
168 #define db_HA_ffactor hash.ffactor
169 #define db_HA_nelem hash.nelem
170 #define db_HA_bsize hash.bsize
171 #define db_HA_cachesize hash.cachesize
172 #define db_HA_lorder hash.lorder
174 #define db_BT_compare btree.compare
175 #define db_BT_prefix btree.prefix
176 #define db_BT_flags btree.flags
177 #define db_BT_psize btree.psize
178 #define db_BT_cachesize btree.cachesize
179 #define db_BT_lorder btree.lorder
180 #define db_BT_maxkeypage btree.maxkeypage
181 #define db_BT_minkeypage btree.minkeypage
183 #define db_RE_reclen recno.reclen
184 #define db_RE_flags recno.flags
185 #define db_RE_bval recno.bval
186 #define db_RE_bfname recno.bfname
187 #define db_RE_psize recno.psize
188 #define db_RE_cachesize recno.cachesize
189 #define db_RE_lorder recno.lorder
193 #define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
195 #define DB_flags(x, v)
197 #endif /* db version 1 */
201 #define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, flags)
202 #define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, flags)
203 #define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
205 #define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
206 #define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
207 #ifdef DB_VERSION_MAJOR
208 #define db_DESTROY(db) ((db->dbp)->close)(db->dbp, 0)
209 #define db_close(db) ((db->dbp)->close)(db->dbp, 0)
210 #define db_del(db, key, flags) ((flags & R_CURSOR) \
211 ? ((db->cursor)->c_del)(db->cursor, 0) \
212 : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
216 #define db_DESTROY(db) ((db->dbp)->close)(db->dbp)
217 #define db_close(db) ((db->dbp)->close)(db->dbp)
218 #define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
219 #define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
223 #define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
233 #ifdef DB_VERSION_MAJOR
238 typedef DB_File_type * DB_File ;
242 #define OutputValue(arg, name) \
243 { if (RETVAL == 0) { \
244 sv_setpvn(arg, name.data, name.size) ; \
248 #define OutputKey(arg, name) \
251 if (db->type != DB_RECNO) { \
252 sv_setpvn(arg, name.data, name.size); \
255 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
259 /* Internal Global Data */
260 static recno_t Value ;
261 static recno_t zero = 0 ;
262 static DB_File CurrentDB ;
263 static DBTKEY empty ;
265 #ifdef DB_VERSION_MAJOR
268 db_put(db, key, value, flags)
277 if (flags & R_CURSOR) {
278 status = ((db->cursor)->c_del)(db->cursor, 0);
285 return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
289 #endif /* DB_VERSION_MAJOR */
294 SV * ver_sv = perl_get_sv("DB_File::db_version", TRUE) ;
295 #ifdef DB_VERSION_MAJOR
296 int Major, Minor, Patch ;
298 (void)db_version(&Major, &Minor, &Patch) ;
300 /* check that libdb is recent enough */
301 if (Major == 2 && Minor == 0 && Patch < 5)
302 croak("DB_File needs Berkeley DB 2.0.5 or greater, you have %d.%d.%d\n",
303 Major, Minor, Patch) ;
306 sv_setpvf(ver_sv, "%d.%d", Major, Minor) ;
310 sprintf(buffer, "%d.%d", Major, Minor) ;
311 sv_setpv(ver_sv, buffer) ;
316 sv_setiv(ver_sv, 1) ;
323 btree_compare(key1, key2)
328 void * data1, * data2 ;
335 /* As newSVpv will assume that the data pointer is a null terminated C
336 string if the size parameter is 0, make sure that data points to an
337 empty string if the length is 0
349 PUSHs(sv_2mortal(newSVpv(data1,key1->size)));
350 PUSHs(sv_2mortal(newSVpv(data2,key2->size)));
353 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
358 croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
370 btree_prefix(key1, key2)
375 void * data1, * data2 ;
382 /* As newSVpv will assume that the data pointer is a null terminated C
383 string if the size parameter is 0, make sure that data points to an
384 empty string if the length is 0
396 PUSHs(sv_2mortal(newSVpv(data1,key1->size)));
397 PUSHs(sv_2mortal(newSVpv(data2,key2->size)));
400 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
405 croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
428 /* DGH - Next two lines added to fix corrupted stack problem */
434 XPUSHs(sv_2mortal(newSVpv((char*)data,size)));
437 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
442 croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
460 printf ("HASH Info\n") ;
461 printf (" hash = %s\n",
462 (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
463 printf (" bsize = %d\n", hash->db_HA_bsize) ;
464 printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
465 printf (" nelem = %d\n", hash->db_HA_nelem) ;
466 printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
467 printf (" lorder = %d\n", hash->db_HA_lorder) ;
475 printf ("RECNO Info\n") ;
476 printf (" flags = %d\n", recno->db_RE_flags) ;
477 printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
478 printf (" psize = %d\n", recno->db_RE_psize) ;
479 printf (" lorder = %d\n", recno->db_RE_lorder) ;
480 printf (" reclen = %ul\n", (unsigned long)recno->db_RE_reclen) ;
481 printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
482 printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
489 printf ("BTREE Info\n") ;
490 printf (" compare = %s\n",
491 (btree->db_BT_compare ? "redefined" : "default")) ;
492 printf (" prefix = %s\n",
493 (btree->db_BT_prefix ? "redefined" : "default")) ;
494 printf (" flags = %d\n", btree->db_BT_flags) ;
495 printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
496 printf (" psize = %d\n", btree->db_BT_psize) ;
497 #ifndef DB_VERSION_MAJOR
498 printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
499 printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
501 printf (" lorder = %d\n", btree->db_BT_lorder) ;
506 #define PrintRecno(recno)
507 #define PrintHash(hash)
508 #define PrintBtree(btree)
523 RETVAL = do_SEQ(db, key, value, R_LAST) ;
525 RETVAL = *(I32 *)key.data ;
526 else /* No key means empty file */
529 return ((I32)RETVAL) ;
533 GetRecnoKey(db, value)
538 /* Get the length of the array */
539 I32 length = GetArrayLength(db) ;
541 /* check for attempt to write before start of array */
542 if (length + value + 1 <= 0)
543 croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
545 value = length + value + 1 ;
554 ParseOpenInfo(isHASH, name, flags, mode, sv)
563 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
564 void * openinfo = NULL ;
565 INFO * info = &RETVAL->info ;
567 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
568 Zero(RETVAL, 1, DB_File_type) ;
570 /* Default to HASH */
571 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
572 RETVAL->type = DB_HASH ;
574 /* DGH - Next line added to avoid SEGV on existing hash DB */
577 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
578 RETVAL->in_memory = (name == NULL) ;
583 croak ("type parameter is not a reference") ;
585 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
586 if (svp && SvOK(*svp))
587 action = (HV*) SvRV(*svp) ;
589 croak("internal error") ;
591 if (sv_isa(sv, "DB_File::HASHINFO"))
595 croak("DB_File can only tie an associative array to a DB_HASH database") ;
597 RETVAL->type = DB_HASH ;
598 openinfo = (void*)info ;
600 svp = hv_fetch(action, "hash", 4, FALSE);
602 if (svp && SvOK(*svp))
604 info->db_HA_hash = hash_cb ;
605 RETVAL->hash = newSVsv(*svp) ;
608 info->db_HA_hash = NULL ;
610 svp = hv_fetch(action, "ffactor", 7, FALSE);
611 info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
613 svp = hv_fetch(action, "nelem", 5, FALSE);
614 info->db_HA_nelem = svp ? SvIV(*svp) : 0;
616 svp = hv_fetch(action, "bsize", 5, FALSE);
617 info->db_HA_bsize = svp ? SvIV(*svp) : 0;
619 svp = hv_fetch(action, "cachesize", 9, FALSE);
620 info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
622 svp = hv_fetch(action, "lorder", 6, FALSE);
623 info->db_HA_lorder = svp ? SvIV(*svp) : 0;
627 else if (sv_isa(sv, "DB_File::BTREEINFO"))
630 croak("DB_File can only tie an associative array to a DB_BTREE database");
632 RETVAL->type = DB_BTREE ;
633 openinfo = (void*)info ;
635 svp = hv_fetch(action, "compare", 7, FALSE);
636 if (svp && SvOK(*svp))
638 info->db_BT_compare = btree_compare ;
639 RETVAL->compare = newSVsv(*svp) ;
642 info->db_BT_compare = NULL ;
644 svp = hv_fetch(action, "prefix", 6, FALSE);
645 if (svp && SvOK(*svp))
647 info->db_BT_prefix = btree_prefix ;
648 RETVAL->prefix = newSVsv(*svp) ;
651 info->db_BT_prefix = NULL ;
653 svp = hv_fetch(action, "flags", 5, FALSE);
654 info->db_BT_flags = svp ? SvIV(*svp) : 0;
656 svp = hv_fetch(action, "cachesize", 9, FALSE);
657 info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
659 #ifndef DB_VERSION_MAJOR
660 svp = hv_fetch(action, "minkeypage", 10, FALSE);
661 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
663 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
664 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
667 svp = hv_fetch(action, "psize", 5, FALSE);
668 info->db_BT_psize = svp ? SvIV(*svp) : 0;
670 svp = hv_fetch(action, "lorder", 6, FALSE);
671 info->db_BT_lorder = svp ? SvIV(*svp) : 0;
676 else if (sv_isa(sv, "DB_File::RECNOINFO"))
679 croak("DB_File can only tie an array to a DB_RECNO database");
681 RETVAL->type = DB_RECNO ;
682 openinfo = (void *)info ;
684 info->db_RE_flags = 0 ;
686 svp = hv_fetch(action, "flags", 5, FALSE);
687 info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
689 svp = hv_fetch(action, "reclen", 6, FALSE);
690 info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
692 svp = hv_fetch(action, "cachesize", 9, FALSE);
693 info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
695 svp = hv_fetch(action, "psize", 5, FALSE);
696 info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
698 svp = hv_fetch(action, "lorder", 6, FALSE);
699 info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
701 #ifdef DB_VERSION_MAJOR
702 info->re_source = name ;
705 svp = hv_fetch(action, "bfname", 6, FALSE);
706 if (svp && SvOK(*svp)) {
707 char * ptr = SvPV(*svp,na) ;
708 #ifdef DB_VERSION_MAJOR
709 name = (char*) na ? ptr : NULL ;
711 info->db_RE_bfname = (char*) (na ? ptr : NULL) ;
715 #ifdef DB_VERSION_MAJOR
718 info->db_RE_bfname = NULL ;
721 svp = hv_fetch(action, "bval", 4, FALSE);
722 #ifdef DB_VERSION_MAJOR
723 if (svp && SvOK(*svp))
727 value = (int)*SvPV(*svp, na) ;
731 if (info->flags & DB_FIXEDLEN) {
732 info->re_pad = value ;
733 info->flags |= DB_PAD ;
736 info->re_delim = value ;
737 info->flags |= DB_DELIMITER ;
742 if (svp && SvOK(*svp))
745 info->db_RE_bval = (u_char)*SvPV(*svp, na) ;
747 info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
748 DB_flags(info->flags, DB_DELIMITER) ;
753 if (info->db_RE_flags & R_FIXEDLEN)
754 info->db_RE_bval = (u_char) ' ' ;
756 info->db_RE_bval = (u_char) '\n' ;
757 DB_flags(info->flags, DB_DELIMITER) ;
762 info->flags |= DB_RENUMBER ;
768 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
772 /* OS2 Specific Code */
779 #ifdef DB_VERSION_MAJOR
785 /* Map 1.x flags to 2.x flags */
786 if ((flags & O_CREAT) == O_CREAT)
790 if ((flags & O_NONBLOCK) == O_NONBLOCK)
795 if (flags == O_RDONLY)
797 if (flags & O_RDONLY) == O_RDONLY)
802 if ((flags & O_TRUNC) == O_TRUNC)
803 Flags |= DB_TRUNCATE ;
806 status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
808 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
815 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
826 croak("DB_File::%s not implemented on this architecture", s);
840 if (strEQ(name, "BTREEMAGIC"))
846 if (strEQ(name, "BTREEVERSION"))
856 if (strEQ(name, "DB_LOCK"))
862 if (strEQ(name, "DB_SHMEM"))
868 if (strEQ(name, "DB_TXN"))
882 if (strEQ(name, "HASHMAGIC"))
888 if (strEQ(name, "HASHVERSION"))
904 if (strEQ(name, "MAX_PAGE_NUMBER"))
905 #ifdef MAX_PAGE_NUMBER
906 return (U32)MAX_PAGE_NUMBER;
910 if (strEQ(name, "MAX_PAGE_OFFSET"))
911 #ifdef MAX_PAGE_OFFSET
912 return MAX_PAGE_OFFSET;
916 if (strEQ(name, "MAX_REC_NUMBER"))
917 #ifdef MAX_REC_NUMBER
918 return (U32)MAX_REC_NUMBER;
932 if (strEQ(name, "RET_ERROR"))
938 if (strEQ(name, "RET_SPECIAL"))
944 if (strEQ(name, "RET_SUCCESS"))
950 if (strEQ(name, "R_CURSOR"))
956 if (strEQ(name, "R_DUP"))
962 if (strEQ(name, "R_FIRST"))
968 if (strEQ(name, "R_FIXEDLEN"))
974 if (strEQ(name, "R_IAFTER"))
980 if (strEQ(name, "R_IBEFORE"))
986 if (strEQ(name, "R_LAST"))
992 if (strEQ(name, "R_NEXT"))
998 if (strEQ(name, "R_NOKEY"))
1004 if (strEQ(name, "R_NOOVERWRITE"))
1005 #ifdef R_NOOVERWRITE
1006 return R_NOOVERWRITE;
1010 if (strEQ(name, "R_PREV"))
1016 if (strEQ(name, "R_RECNOSYNC"))
1022 if (strEQ(name, "R_SETCURSOR"))
1028 if (strEQ(name, "R_SNAPSHOT"))
1062 MODULE = DB_File PACKAGE = DB_File PREFIX = db_
1068 empty.data = &zero ;
1069 empty.size = sizeof(recno_t) ;
1080 db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
1087 char * name = (char *) NULL ;
1088 SV * sv = (SV *) NULL ;
1090 if (items >= 3 && SvOK(ST(2)))
1091 name = (char*) SvPV(ST(2), na) ;
1096 RETVAL = ParseOpenInfo(isHASH, name, flags, mode, sv) ;
1097 if (RETVAL->dbp == NULL)
1110 SvREFCNT_dec(db->hash) ;
1112 SvREFCNT_dec(db->compare) ;
1114 SvREFCNT_dec(db->prefix) ;
1116 #ifdef DB_VERSION_MAJOR
1123 db_DELETE(db, key, flags=0)
1141 RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
1147 db_FETCH(db, key, flags=0)
1157 /* RETVAL = ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) ; */
1158 RETVAL = db_get(db, key, value, flags) ;
1159 ST(0) = sv_newmortal();
1161 sv_setpvn(ST(0), value.data, value.size);
1165 db_STORE(db, key, value, flags=0)
1186 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1187 ST(0) = sv_newmortal();
1190 if (db->type != DB_RECNO)
1191 sv_setpvn(ST(0), key.data, key.size);
1193 sv_setiv(ST(0), (I32)*(I32*)key.data - 1);
1208 RETVAL = do_SEQ(db, key, value, R_NEXT) ;
1209 ST(0) = sv_newmortal();
1212 if (db->type != DB_RECNO)
1213 sv_setpvn(ST(0), key.data, key.size);
1215 sv_setiv(ST(0), (I32)*(I32*)key.data - 1);
1220 # These would be nice for RECNO
1237 #ifdef DB_VERSION_MAJOR
1238 /* get the first value */
1239 RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
1244 for (i = items-1 ; i > 0 ; --i)
1246 value.data = SvPV(ST(i), na) ;
1250 key.size = sizeof(int) ;
1251 #ifdef DB_VERSION_MAJOR
1252 RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
1254 RETVAL = (Db->put)(Db, &key, &value, R_IBEFORE) ;
1276 /* First get the final value */
1277 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1278 ST(0) = sv_newmortal();
1282 /* the call to del will trash value, so take a copy now */
1283 sv_setpvn(ST(0), value.data, value.size);
1284 RETVAL = db_del(db, key, R_CURSOR) ;
1286 sv_setsv(ST(0), &sv_undef);
1302 /* get the first value */
1303 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1304 ST(0) = sv_newmortal();
1308 /* the call to del will trash value, so take a copy now */
1309 sv_setpvn(ST(0), value.data, value.size);
1310 RETVAL = db_del(db, key, R_CURSOR) ;
1312 sv_setsv (ST(0), &sv_undef) ;
1323 DBTKEY * keyptr = &key ;
1331 /* Set the Cursor to the Last element */
1332 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1337 #ifdef DB_VERSION_MAJOR
1338 for (i = 1 ; i < items ; ++i)
1341 ++ (* (int*)key.data) ;
1342 value.data = SvPV(ST(i), na) ;
1344 RETVAL = (Db->put)(Db, NULL, &key, &value, 0) ;
1349 for (i = items - 1 ; i > 0 ; --i)
1351 value.data = SvPV(ST(i), na) ;
1353 RETVAL = (Db->put)(Db, keyptr, &value, R_IAFTER) ;
1369 RETVAL = GetArrayLength(db) ;
1375 # Now provide an interface to the rest of the DB functionality
1379 db_del(db, key, flags=0)
1385 RETVAL = db_del(db, key, flags) ;
1386 #ifdef DB_VERSION_MAJOR
1389 else if (RETVAL == DB_NOTFOUND)
1397 db_get(db, key, value, flags=0)
1405 RETVAL = db_get(db, key, value, flags) ;
1406 #ifdef DB_VERSION_MAJOR
1409 else if (RETVAL == DB_NOTFOUND)
1417 db_put(db, key, value, flags=0)
1424 RETVAL = db_put(db, key, value, flags) ;
1425 #ifdef DB_VERSION_MAJOR
1428 else if (RETVAL == DB_KEYEXIST)
1433 key if (flags & (R_IAFTER|R_IBEFORE)) OutputKey(ST(1), key);
1441 #ifdef DB_VERSION_MAJOR
1443 status = (db->in_memory
1445 : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
1449 RETVAL = (db->in_memory
1451 : ((db->dbp)->fd)(db->dbp) ) ;
1457 db_sync(db, flags=0)
1462 RETVAL = db_sync(db, flags) ;
1463 #ifdef DB_VERSION_MAJOR
1472 db_seq(db, key, value, flags)
1480 RETVAL = db_seq(db, key, value, flags);
1481 #ifdef DB_VERSION_MAJOR
1484 else if (RETVAL == DB_NOTFOUND)