3 DB_File.xs -- Perl 5 interface to Berkeley DB
5 written by Paul Marquess (pmarquess@bfsec.bt.co.uk)
6 last modified 2nd Feb 1998
9 All comments/suggestions/problems are welcome
11 Copyright (c) 1995, 1996, 1997, 1998 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
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.
66 /* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
67 * shortly #included by the <db.h>) __attribute__ to the possibly
68 * already defined __attribute__, for example by GNUC or by Perl. */
72 /* If Perl has been compiled with Threads support,the symbol op will
73 be defined here. This clashes with a field name in db.h, so get rid of it.
86 #ifdef DB_VERSION_MAJOR
88 /* map version 2 features & constants onto their version 1 equivalent */
93 #define DB_Prefix_t size_t
98 #define DB_Hash_t u_int32_t
100 /* DBTYPE stays the same */
101 /* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
102 typedef DB_INFO INFO ;
104 /* version 2 has db_recno_t in place of recno_t */
105 typedef db_recno_t recno_t;
108 #define R_CURSOR DB_SET_RANGE
109 #define R_FIRST DB_FIRST
110 #define R_IAFTER DB_AFTER
111 #define R_IBEFORE DB_BEFORE
112 #define R_LAST DB_LAST
113 #define R_NEXT DB_NEXT
114 #define R_NOOVERWRITE DB_NOOVERWRITE
115 #define R_PREV DB_PREV
116 #define R_SETCURSOR 0
117 #define R_RECNOSYNC 0
118 #define R_FIXEDLEN DB_FIXEDLEN
121 #define db_HA_hash h_hash
122 #define db_HA_ffactor h_ffactor
123 #define db_HA_nelem h_nelem
124 #define db_HA_bsize db_pagesize
125 #define db_HA_cachesize db_cachesize
126 #define db_HA_lorder db_lorder
128 #define db_BT_compare bt_compare
129 #define db_BT_prefix bt_prefix
130 #define db_BT_flags flags
131 #define db_BT_psize db_pagesize
132 #define db_BT_cachesize db_cachesize
133 #define db_BT_lorder db_lorder
134 #define db_BT_maxkeypage
135 #define db_BT_minkeypage
138 #define db_RE_reclen re_len
139 #define db_RE_flags flags
140 #define db_RE_bval re_pad
141 #define db_RE_bfname re_source
142 #define db_RE_psize db_pagesize
143 #define db_RE_cachesize db_cachesize
144 #define db_RE_lorder db_lorder
148 #define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
151 #define DBT_flags(x) x.flags = 0
152 #define DB_flags(x, v) x |= v
154 #else /* db version 1.x */
167 #define DB_Prefix_t mDB_Prefix_t
174 #define DB_Hash_t mDB_Hash_t
177 #define db_HA_hash hash.hash
178 #define db_HA_ffactor hash.ffactor
179 #define db_HA_nelem hash.nelem
180 #define db_HA_bsize hash.bsize
181 #define db_HA_cachesize hash.cachesize
182 #define db_HA_lorder hash.lorder
184 #define db_BT_compare btree.compare
185 #define db_BT_prefix btree.prefix
186 #define db_BT_flags btree.flags
187 #define db_BT_psize btree.psize
188 #define db_BT_cachesize btree.cachesize
189 #define db_BT_lorder btree.lorder
190 #define db_BT_maxkeypage btree.maxkeypage
191 #define db_BT_minkeypage btree.minkeypage
193 #define db_RE_reclen recno.reclen
194 #define db_RE_flags recno.flags
195 #define db_RE_bval recno.bval
196 #define db_RE_bfname recno.bfname
197 #define db_RE_psize recno.psize
198 #define db_RE_cachesize recno.cachesize
199 #define db_RE_lorder recno.lorder
203 #define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
205 #define DB_flags(x, v)
207 #endif /* db version 1 */
211 #define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, flags)
212 #define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, flags)
213 #define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
215 #define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
216 #define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
217 #ifdef DB_VERSION_MAJOR
218 #define db_DESTROY(db) ((db->dbp)->close)(db->dbp, 0)
219 #define db_close(db) ((db->dbp)->close)(db->dbp, 0)
220 #define db_del(db, key, flags) ((flags & R_CURSOR) \
221 ? ((db->cursor)->c_del)(db->cursor, 0) \
222 : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
226 #define db_DESTROY(db) ((db->dbp)->close)(db->dbp)
227 #define db_close(db) ((db->dbp)->close)(db->dbp)
228 #define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
229 #define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
233 #define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
243 #ifdef DB_VERSION_MAJOR
248 typedef DB_File_type * DB_File ;
251 #define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
253 #define OutputValue(arg, name) \
254 { if (RETVAL == 0) { \
255 my_sv_setpvn(arg, name.data, name.size) ; \
259 #define OutputKey(arg, name) \
262 if (db->type != DB_RECNO) { \
263 my_sv_setpvn(arg, name.data, name.size); \
266 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
271 /* Internal Global Data */
272 static recno_t Value ;
273 static recno_t zero = 0 ;
274 static DB_File CurrentDB ;
275 static DBTKEY empty ;
277 #ifdef DB_VERSION_MAJOR
280 db_put(db, key, value, flags)
289 if (flags & R_CURSOR) {
290 status = ((db->cursor)->c_del)(db->cursor, 0);
297 return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
301 #endif /* DB_VERSION_MAJOR */
306 SV * ver_sv = perl_get_sv("DB_File::db_version", TRUE) ;
307 #ifdef DB_VERSION_MAJOR
308 int Major, Minor, Patch ;
310 (void)db_version(&Major, &Minor, &Patch) ;
312 /* check that libdb is recent enough */
313 if (Major == 2 && Minor == 0 && Patch < 5)
314 croak("DB_File needs Berkeley DB 2.0.5 or greater, you have %d.%d.%d\n",
315 Major, Minor, Patch) ;
318 sv_setpvf(ver_sv, "%d.%d", Major, Minor) ;
322 sprintf(buffer, "%d.%d", Major, Minor) ;
323 sv_setpv(ver_sv, buffer) ;
328 sv_setiv(ver_sv, 1) ;
335 btree_compare(key1, key2)
340 void * data1, * data2 ;
347 /* As newSVpv will assume that the data pointer is a null terminated C
348 string if the size parameter is 0, make sure that data points to an
349 empty string if the length is 0
361 PUSHs(sv_2mortal(newSVpv(data1,key1->size)));
362 PUSHs(sv_2mortal(newSVpv(data2,key2->size)));
365 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
370 croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
382 btree_prefix(key1, key2)
387 void * data1, * data2 ;
394 /* As newSVpv will assume that the data pointer is a null terminated C
395 string if the size parameter is 0, make sure that data points to an
396 empty string if the length is 0
408 PUSHs(sv_2mortal(newSVpv(data1,key1->size)));
409 PUSHs(sv_2mortal(newSVpv(data2,key2->size)));
412 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
417 croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
440 /* DGH - Next two lines added to fix corrupted stack problem */
446 XPUSHs(sv_2mortal(newSVpv((char*)data,size)));
449 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
454 croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
472 printf ("HASH Info\n") ;
473 printf (" hash = %s\n",
474 (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
475 printf (" bsize = %d\n", hash->db_HA_bsize) ;
476 printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
477 printf (" nelem = %d\n", hash->db_HA_nelem) ;
478 printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
479 printf (" lorder = %d\n", hash->db_HA_lorder) ;
487 printf ("RECNO Info\n") ;
488 printf (" flags = %d\n", recno->db_RE_flags) ;
489 printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
490 printf (" psize = %d\n", recno->db_RE_psize) ;
491 printf (" lorder = %d\n", recno->db_RE_lorder) ;
492 printf (" reclen = %ul\n", (unsigned long)recno->db_RE_reclen) ;
493 printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
494 printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
501 printf ("BTREE Info\n") ;
502 printf (" compare = %s\n",
503 (btree->db_BT_compare ? "redefined" : "default")) ;
504 printf (" prefix = %s\n",
505 (btree->db_BT_prefix ? "redefined" : "default")) ;
506 printf (" flags = %d\n", btree->db_BT_flags) ;
507 printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
508 printf (" psize = %d\n", btree->db_BT_psize) ;
509 #ifndef DB_VERSION_MAJOR
510 printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
511 printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
513 printf (" lorder = %d\n", btree->db_BT_lorder) ;
518 #define PrintRecno(recno)
519 #define PrintHash(hash)
520 #define PrintBtree(btree)
535 RETVAL = do_SEQ(db, key, value, R_LAST) ;
536 if (RETVAL < 0 && errno == EBADF)
540 key.size = sizeof(oops);
541 db_get(db, key, value, 0);
542 RETVAL = do_SEQ(db, key, value, R_LAST) ;
545 RETVAL = *(I32 *)key.data ;
546 else /* No key means empty file */
549 return ((I32)RETVAL) ;
553 GetRecnoKey(db, value)
558 /* Get the length of the array */
559 I32 length = GetArrayLength(db) ;
561 /* check for attempt to write before start of array */
562 if (length + value + 1 <= 0)
563 croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
565 value = length + value + 1 ;
574 ParseOpenInfo(isHASH, name, flags, mode, sv)
583 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
584 void * openinfo = NULL ;
585 INFO * info = &RETVAL->info ;
587 /* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
588 Zero(RETVAL, 1, DB_File_type) ;
590 /* Default to HASH */
591 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
592 RETVAL->type = DB_HASH ;
594 /* DGH - Next line added to avoid SEGV on existing hash DB */
597 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
598 RETVAL->in_memory = (name == NULL) ;
603 croak ("type parameter is not a reference") ;
605 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
606 if (svp && SvOK(*svp))
607 action = (HV*) SvRV(*svp) ;
609 croak("internal error") ;
611 if (sv_isa(sv, "DB_File::HASHINFO"))
615 croak("DB_File can only tie an associative array to a DB_HASH database") ;
617 RETVAL->type = DB_HASH ;
618 openinfo = (void*)info ;
620 svp = hv_fetch(action, "hash", 4, FALSE);
622 if (svp && SvOK(*svp))
624 info->db_HA_hash = hash_cb ;
625 RETVAL->hash = newSVsv(*svp) ;
628 info->db_HA_hash = NULL ;
630 svp = hv_fetch(action, "ffactor", 7, FALSE);
631 info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
633 svp = hv_fetch(action, "nelem", 5, FALSE);
634 info->db_HA_nelem = svp ? SvIV(*svp) : 0;
636 svp = hv_fetch(action, "bsize", 5, FALSE);
637 info->db_HA_bsize = svp ? SvIV(*svp) : 0;
639 svp = hv_fetch(action, "cachesize", 9, FALSE);
640 info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
642 svp = hv_fetch(action, "lorder", 6, FALSE);
643 info->db_HA_lorder = svp ? SvIV(*svp) : 0;
647 else if (sv_isa(sv, "DB_File::BTREEINFO"))
650 croak("DB_File can only tie an associative array to a DB_BTREE database");
652 RETVAL->type = DB_BTREE ;
653 openinfo = (void*)info ;
655 svp = hv_fetch(action, "compare", 7, FALSE);
656 if (svp && SvOK(*svp))
658 info->db_BT_compare = btree_compare ;
659 RETVAL->compare = newSVsv(*svp) ;
662 info->db_BT_compare = NULL ;
664 svp = hv_fetch(action, "prefix", 6, FALSE);
665 if (svp && SvOK(*svp))
667 info->db_BT_prefix = btree_prefix ;
668 RETVAL->prefix = newSVsv(*svp) ;
671 info->db_BT_prefix = NULL ;
673 svp = hv_fetch(action, "flags", 5, FALSE);
674 info->db_BT_flags = svp ? SvIV(*svp) : 0;
676 svp = hv_fetch(action, "cachesize", 9, FALSE);
677 info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
679 #ifndef DB_VERSION_MAJOR
680 svp = hv_fetch(action, "minkeypage", 10, FALSE);
681 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
683 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
684 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
687 svp = hv_fetch(action, "psize", 5, FALSE);
688 info->db_BT_psize = svp ? SvIV(*svp) : 0;
690 svp = hv_fetch(action, "lorder", 6, FALSE);
691 info->db_BT_lorder = svp ? SvIV(*svp) : 0;
696 else if (sv_isa(sv, "DB_File::RECNOINFO"))
699 croak("DB_File can only tie an array to a DB_RECNO database");
701 RETVAL->type = DB_RECNO ;
702 openinfo = (void *)info ;
704 info->db_RE_flags = 0 ;
706 svp = hv_fetch(action, "flags", 5, FALSE);
707 info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
709 svp = hv_fetch(action, "reclen", 6, FALSE);
710 info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
712 svp = hv_fetch(action, "cachesize", 9, FALSE);
713 info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
715 svp = hv_fetch(action, "psize", 5, FALSE);
716 info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
718 svp = hv_fetch(action, "lorder", 6, FALSE);
719 info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
721 #ifdef DB_VERSION_MAJOR
722 info->re_source = name ;
725 svp = hv_fetch(action, "bfname", 6, FALSE);
726 if (svp && SvOK(*svp)) {
727 char * ptr = SvPV(*svp,na) ;
728 #ifdef DB_VERSION_MAJOR
729 name = (char*) na ? ptr : NULL ;
731 info->db_RE_bfname = (char*) (na ? ptr : NULL) ;
735 #ifdef DB_VERSION_MAJOR
738 info->db_RE_bfname = NULL ;
741 svp = hv_fetch(action, "bval", 4, FALSE);
742 #ifdef DB_VERSION_MAJOR
743 if (svp && SvOK(*svp))
747 value = (int)*SvPV(*svp, na) ;
751 if (info->flags & DB_FIXEDLEN) {
752 info->re_pad = value ;
753 info->flags |= DB_PAD ;
756 info->re_delim = value ;
757 info->flags |= DB_DELIMITER ;
762 if (svp && SvOK(*svp))
765 info->db_RE_bval = (u_char)*SvPV(*svp, na) ;
767 info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
768 DB_flags(info->flags, DB_DELIMITER) ;
773 if (info->db_RE_flags & R_FIXEDLEN)
774 info->db_RE_bval = (u_char) ' ' ;
776 info->db_RE_bval = (u_char) '\n' ;
777 DB_flags(info->flags, DB_DELIMITER) ;
782 info->flags |= DB_RENUMBER ;
788 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
792 /* OS2 Specific Code */
799 #ifdef DB_VERSION_MAJOR
805 /* Map 1.x flags to 2.x flags */
806 if ((flags & O_CREAT) == O_CREAT)
810 if ((flags & O_NONBLOCK) == O_NONBLOCK)
815 if (flags == O_RDONLY)
817 if (flags & O_RDONLY) == O_RDONLY)
822 if ((flags & O_TRUNC) == O_TRUNC)
823 Flags |= DB_TRUNCATE ;
826 status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
828 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
835 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
846 croak("DB_File::%s not implemented on this architecture", s);
860 if (strEQ(name, "BTREEMAGIC"))
866 if (strEQ(name, "BTREEVERSION"))
876 if (strEQ(name, "DB_LOCK"))
882 if (strEQ(name, "DB_SHMEM"))
888 if (strEQ(name, "DB_TXN"))
902 if (strEQ(name, "HASHMAGIC"))
908 if (strEQ(name, "HASHVERSION"))
924 if (strEQ(name, "MAX_PAGE_NUMBER"))
925 #ifdef MAX_PAGE_NUMBER
926 return (U32)MAX_PAGE_NUMBER;
930 if (strEQ(name, "MAX_PAGE_OFFSET"))
931 #ifdef MAX_PAGE_OFFSET
932 return MAX_PAGE_OFFSET;
936 if (strEQ(name, "MAX_REC_NUMBER"))
937 #ifdef MAX_REC_NUMBER
938 return (U32)MAX_REC_NUMBER;
952 if (strEQ(name, "RET_ERROR"))
958 if (strEQ(name, "RET_SPECIAL"))
964 if (strEQ(name, "RET_SUCCESS"))
970 if (strEQ(name, "R_CURSOR"))
976 if (strEQ(name, "R_DUP"))
982 if (strEQ(name, "R_FIRST"))
988 if (strEQ(name, "R_FIXEDLEN"))
994 if (strEQ(name, "R_IAFTER"))
1000 if (strEQ(name, "R_IBEFORE"))
1006 if (strEQ(name, "R_LAST"))
1012 if (strEQ(name, "R_NEXT"))
1018 if (strEQ(name, "R_NOKEY"))
1024 if (strEQ(name, "R_NOOVERWRITE"))
1025 #ifdef R_NOOVERWRITE
1026 return R_NOOVERWRITE;
1030 if (strEQ(name, "R_PREV"))
1036 if (strEQ(name, "R_RECNOSYNC"))
1042 if (strEQ(name, "R_SETCURSOR"))
1048 if (strEQ(name, "R_SNAPSHOT"))
1082 MODULE = DB_File PACKAGE = DB_File PREFIX = db_
1088 empty.data = &zero ;
1089 empty.size = sizeof(recno_t) ;
1100 db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
1107 char * name = (char *) NULL ;
1108 SV * sv = (SV *) NULL ;
1110 if (items >= 3 && SvOK(ST(2)))
1111 name = (char*) SvPV(ST(2), na) ;
1116 RETVAL = ParseOpenInfo(isHASH, name, flags, mode, sv) ;
1117 if (RETVAL->dbp == NULL)
1130 SvREFCNT_dec(db->hash) ;
1132 SvREFCNT_dec(db->compare) ;
1134 SvREFCNT_dec(db->prefix) ;
1136 #ifdef DB_VERSION_MAJOR
1143 db_DELETE(db, key, flags=0)
1161 RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
1167 db_FETCH(db, key, flags=0)
1177 /* RETVAL = ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) ; */
1178 RETVAL = db_get(db, key, value, flags) ;
1179 ST(0) = sv_newmortal();
1181 my_sv_setpvn(ST(0), value.data, value.size);
1185 db_STORE(db, key, value, flags=0)
1206 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1207 ST(0) = sv_newmortal();
1210 if (db->type != DB_RECNO)
1211 my_sv_setpvn(ST(0), key.data, key.size);
1213 sv_setiv(ST(0), (I32)*(I32*)key.data - 1);
1228 RETVAL = do_SEQ(db, key, value, R_NEXT) ;
1229 ST(0) = sv_newmortal();
1232 if (db->type != DB_RECNO)
1233 my_sv_setpvn(ST(0), key.data, key.size);
1235 sv_setiv(ST(0), (I32)*(I32*)key.data - 1);
1240 # These would be nice for RECNO
1258 #ifdef DB_VERSION_MAJOR
1259 /* get the first value */
1260 RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
1265 for (i = items-1 ; i > 0 ; --i)
1267 value.data = SvPV(ST(i), na) ;
1271 key.size = sizeof(int) ;
1272 #ifdef DB_VERSION_MAJOR
1273 RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
1275 RETVAL = (Db->put)(Db, &key, &value, R_IBEFORE) ;
1298 /* First get the final value */
1299 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1300 ST(0) = sv_newmortal();
1304 /* the call to del will trash value, so take a copy now */
1305 my_sv_setpvn(ST(0), value.data, value.size);
1306 RETVAL = db_del(db, key, R_CURSOR) ;
1308 sv_setsv(ST(0), &sv_undef);
1325 /* get the first value */
1326 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
1327 ST(0) = sv_newmortal();
1331 /* the call to del will trash value, so take a copy now */
1332 my_sv_setpvn(ST(0), value.data, value.size);
1333 RETVAL = db_del(db, key, R_CURSOR) ;
1335 sv_setsv (ST(0), &sv_undef) ;
1347 DBTKEY * keyptr = &key ;
1355 /* Set the Cursor to the Last element */
1356 RETVAL = do_SEQ(db, key, value, R_LAST) ;
1361 #ifdef DB_VERSION_MAJOR
1362 for (i = 1 ; i < items ; ++i)
1365 ++ (* (int*)key.data) ;
1366 value.data = SvPV(ST(i), na) ;
1368 RETVAL = (Db->put)(Db, NULL, &key, &value, 0) ;
1373 for (i = items - 1 ; i > 0 ; --i)
1375 value.data = SvPV(ST(i), na) ;
1377 RETVAL = (Db->put)(Db, keyptr, &value, R_IAFTER) ;
1391 ALIAS: FETCHSIZE = 1
1394 RETVAL = GetArrayLength(db) ;
1400 # Now provide an interface to the rest of the DB functionality
1404 db_del(db, key, flags=0)
1410 RETVAL = db_del(db, key, flags) ;
1411 #ifdef DB_VERSION_MAJOR
1414 else if (RETVAL == DB_NOTFOUND)
1422 db_get(db, key, value, flags=0)
1430 RETVAL = db_get(db, key, value, flags) ;
1431 #ifdef DB_VERSION_MAJOR
1434 else if (RETVAL == DB_NOTFOUND)
1442 db_put(db, key, value, flags=0)
1449 RETVAL = db_put(db, key, value, flags) ;
1450 #ifdef DB_VERSION_MAJOR
1453 else if (RETVAL == DB_KEYEXIST)
1458 key if (flags & (R_IAFTER|R_IBEFORE)) OutputKey(ST(1), key);
1466 #ifdef DB_VERSION_MAJOR
1468 status = (db->in_memory
1470 : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
1474 RETVAL = (db->in_memory
1476 : ((db->dbp)->fd)(db->dbp) ) ;
1482 db_sync(db, flags=0)
1487 RETVAL = db_sync(db, flags) ;
1488 #ifdef DB_VERSION_MAJOR
1497 db_seq(db, key, value, flags)
1505 RETVAL = db_seq(db, key, value, flags);
1506 #ifdef DB_VERSION_MAJOR
1509 else if (RETVAL == DB_NOTFOUND)