This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
This is my patch patch.1m for perl5.001.
[perl5.git] / ext / DB_File / DB_File.xs
CommitLineData
a0d0e21e
LW
1/*
2
3 DB_File.xs -- Perl 5 interface to Berkeley DB
4
5 written by Paul Marquess (pmarquess@bfsec.bt.co.uk)
3b35bae3
AD
6 last modified 19th May 1995
7 version 0.2
a0d0e21e
LW
8
9 All comments/suggestions/problems are welcome
10
3b35bae3
AD
11 Changes:
12 0.1 - Initial Release
13 0.2 - No longer bombs out if dbopen returns an error.
a0d0e21e
LW
14*/
15
16#include "EXTERN.h"
17#include "perl.h"
18#include "XSUB.h"
19
20#include <db.h>
21
22#include <fcntl.h>
23
a0d0e21e
LW
24typedef DB * DB_File;
25typedef DBT DBTKEY ;
26
27union INFO {
28 HASHINFO hash ;
29 RECNOINFO recno ;
30 BTREEINFO btree ;
31 } ;
32
33typedef struct {
34 SV * sub ;
35 } CallBackInfo ;
36
37
38/* #define TRACE */
39
40#define db_DESTROY(db) (db->close)(db)
41#define db_DELETE(db, key, flags) (db->del)(db, &key, flags)
42#define db_STORE(db, key, value, flags) (db->put)(db, &key, &value, flags)
43#define db_FETCH(db, key, flags) (db->get)(db, &key, &value, flags)
44
45#define db_close(db) (db->close)(db)
46#define db_del(db, key, flags) (db->del)(db, &key, flags)
47#define db_fd(db) (db->fd)(db)
48#define db_put(db, key, value, flags) (db->put)(db, &key, &value, flags)
49#define db_get(db, key, value, flags) (db->get)(db, &key, &value, flags)
50#define db_seq(db, key, value, flags) (db->seq)(db, &key, &value, flags)
51#define db_sync(db, flags) (db->sync)(db, flags)
52
53
54#define OutputValue(arg, name) \
55 { if (RETVAL == 0) sv_setpvn(arg, name.data, name.size) ; }
56
57#define OutputKey(arg, name) \
58 { if (RETVAL == 0) \
59 { \
60 if (db->close != DB_recno_close) \
61 sv_setpvn(arg, name.data, name.size); \
62 else \
63 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
64 } \
65 }
66
67/* Internal Global Data */
68
69static recno_t Value ;
70static int (*DB_recno_close)() = NULL ;
71
72static CallBackInfo hash_callback = { 0 } ;
73static CallBackInfo compare_callback = { 0 } ;
74static CallBackInfo prefix_callback = { 0 } ;
75
76
77static int
78btree_compare(key1, key2)
79const DBT * key1 ;
80const DBT * key2 ;
81{
82 dSP ;
83 void * data1, * data2 ;
84 int retval ;
85 int count ;
86
87 data1 = key1->data ;
88 data2 = key2->data ;
89
90 /* As newSVpv will assume that the data pointer is a null terminated C
91 string if the size parameter is 0, make sure that data points to an
92 empty string if the length is 0
93 */
94 if (key1->size == 0)
95 data1 = "" ;
96 if (key2->size == 0)
97 data2 = "" ;
98
99 ENTER ;
100 SAVETMPS;
101
102 PUSHMARK(sp) ;
103 EXTEND(sp,2) ;
104 PUSHs(sv_2mortal(newSVpv(data1,key1->size)));
105 PUSHs(sv_2mortal(newSVpv(data2,key2->size)));
106 PUTBACK ;
107
108 count = perl_call_sv(compare_callback.sub, G_SCALAR);
109
110 SPAGAIN ;
111
112 if (count != 1)
113 croak ("DB_File btree_compare: expected 1 return value from %s, got %d\n", count) ;
114
115 retval = POPi ;
116
117 PUTBACK ;
118 FREETMPS ;
119 LEAVE ;
120 return (retval) ;
121
122}
123
ecfc5424 124static DB_Prefix_t
a0d0e21e
LW
125btree_prefix(key1, key2)
126const DBT * key1 ;
127const DBT * key2 ;
128{
129 dSP ;
130 void * data1, * data2 ;
131 int retval ;
132 int count ;
133
134 data1 = key1->data ;
135 data2 = key2->data ;
136
137 /* As newSVpv will assume that the data pointer is a null terminated C
138 string if the size parameter is 0, make sure that data points to an
139 empty string if the length is 0
140 */
141 if (key1->size == 0)
142 data1 = "" ;
143 if (key2->size == 0)
144 data2 = "" ;
145
146 ENTER ;
147 SAVETMPS;
148
149 PUSHMARK(sp) ;
150 EXTEND(sp,2) ;
151 PUSHs(sv_2mortal(newSVpv(data1,key1->size)));
152 PUSHs(sv_2mortal(newSVpv(data2,key2->size)));
153 PUTBACK ;
154
155 count = perl_call_sv(prefix_callback.sub, G_SCALAR);
156
157 SPAGAIN ;
158
159 if (count != 1)
160 croak ("DB_File btree_prefix: expected 1 return value from %s, got %d\n", count) ;
161
162 retval = POPi ;
163
164 PUTBACK ;
165 FREETMPS ;
166 LEAVE ;
167
168 return (retval) ;
169}
170
ecfc5424 171static DB_Hash_t
a0d0e21e
LW
172hash_cb(data, size)
173const void * data ;
174size_t size ;
175{
176 dSP ;
177 int retval ;
178 int count ;
179
180 if (size == 0)
181 data = "" ;
182
183 PUSHMARK(sp) ;
184 XPUSHs(sv_2mortal(newSVpv((char*)data,size)));
185 PUTBACK ;
186
187 count = perl_call_sv(hash_callback.sub, G_SCALAR);
188
189 SPAGAIN ;
190
191 if (count != 1)
192 croak ("DB_File hash_cb: expected 1 return value from %s, got %d\n", count) ;
193
194 retval = POPi ;
195
196 PUTBACK ;
197 FREETMPS ;
198 LEAVE ;
199
200 return (retval) ;
201}
202
203
204#ifdef TRACE
205
206static void
207PrintHash(hash)
208HASHINFO hash ;
209{
210 printf ("HASH Info\n") ;
211 printf (" hash = %s\n", (hash.hash != NULL ? "redefined" : "default")) ;
212 printf (" bsize = %d\n", hash.bsize) ;
213 printf (" ffactor = %d\n", hash.ffactor) ;
214 printf (" nelem = %d\n", hash.nelem) ;
215 printf (" cachesize = %d\n", hash.cachesize) ;
216 printf (" lorder = %d\n", hash.lorder) ;
217
218}
219
220static void
221PrintRecno(recno)
222RECNOINFO recno ;
223{
224 printf ("RECNO Info\n") ;
225 printf (" flags = %d\n", recno.flags) ;
226 printf (" cachesize = %d\n", recno.cachesize) ;
227 printf (" psize = %d\n", recno.psize) ;
228 printf (" lorder = %d\n", recno.lorder) ;
229 printf (" reclen = %d\n", recno.reclen) ;
230 printf (" bval = %d\n", recno.bval) ;
231 printf (" bfname = %s\n", recno.bfname) ;
232}
233
234PrintBtree(btree)
235BTREEINFO btree ;
236{
237 printf ("BTREE Info\n") ;
238 printf (" compare = %s\n", (btree.compare ? "redefined" : "default")) ;
239 printf (" prefix = %s\n", (btree.prefix ? "redefined" : "default")) ;
240 printf (" flags = %d\n", btree.flags) ;
241 printf (" cachesize = %d\n", btree.cachesize) ;
242 printf (" psize = %d\n", btree.psize) ;
243 printf (" maxkeypage = %d\n", btree.maxkeypage) ;
244 printf (" minkeypage = %d\n", btree.minkeypage) ;
245 printf (" lorder = %d\n", btree.lorder) ;
246}
247
248#else
249
250#define PrintRecno(recno)
251#define PrintHash(hash)
252#define PrintBtree(btree)
253
254#endif /* TRACE */
255
256
257static I32
258GetArrayLength(db)
259DB_File db ;
260{
261 DBT key ;
262 DBT value ;
263 int RETVAL ;
264
265 RETVAL = (db->seq)(db, &key, &value, R_LAST) ;
266 if (RETVAL == 0)
267 RETVAL = *(I32 *)key.data ;
268 else if (RETVAL == 1) /* No key means empty file */
269 RETVAL = 0 ;
270
271 return (RETVAL) ;
272}
273
274static DB_File
275ParseOpenInfo(name, flags, mode, sv, string)
276char * name ;
277int flags ;
278int mode ;
279SV * sv ;
280char * string ;
281{
282 SV ** svp;
283 HV * action ;
284 union INFO info ;
285 DB_File RETVAL ;
286 void * openinfo = NULL ;
287 DBTYPE type = DB_HASH ;
288
289
290 if (sv)
291 {
292 if (! SvROK(sv) )
293 croak ("type parameter is not a reference") ;
294
295 action = (HV*)SvRV(sv);
296 if (sv_isa(sv, "DB_File::HASHINFO"))
297 {
298 type = DB_HASH ;
299 openinfo = (void*)&info ;
300
301 svp = hv_fetch(action, "hash", 4, FALSE);
302
303 if (svp && SvOK(*svp))
304 {
305 info.hash.hash = hash_cb ;
306 hash_callback.sub = *svp ;
307 }
308 else
309 info.hash.hash = NULL ;
310
311 svp = hv_fetch(action, "bsize", 5, FALSE);
312 info.hash.bsize = svp ? SvIV(*svp) : 0;
313
314 svp = hv_fetch(action, "ffactor", 7, FALSE);
315 info.hash.ffactor = svp ? SvIV(*svp) : 0;
316
317 svp = hv_fetch(action, "nelem", 5, FALSE);
318 info.hash.nelem = svp ? SvIV(*svp) : 0;
319
320 svp = hv_fetch(action, "cachesize", 9, FALSE);
321 info.hash.cachesize = svp ? SvIV(*svp) : 0;
322
323 svp = hv_fetch(action, "lorder", 6, FALSE);
324 info.hash.lorder = svp ? SvIV(*svp) : 0;
325
326 PrintHash(info) ;
327 }
328 else if (sv_isa(sv, "DB_File::BTREEINFO"))
329 {
330 type = DB_BTREE ;
331 openinfo = (void*)&info ;
332
333 svp = hv_fetch(action, "compare", 7, FALSE);
334 if (svp && SvOK(*svp))
335 {
336 info.btree.compare = btree_compare ;
337 compare_callback.sub = *svp ;
338 }
339 else
340 info.btree.compare = NULL ;
341
342 svp = hv_fetch(action, "prefix", 6, FALSE);
343 if (svp && SvOK(*svp))
344 {
345 info.btree.prefix = btree_prefix ;
346 prefix_callback.sub = *svp ;
347 }
348 else
349 info.btree.prefix = NULL ;
350
351 svp = hv_fetch(action, "flags", 5, FALSE);
352 info.btree.flags = svp ? SvIV(*svp) : 0;
353
354 svp = hv_fetch(action, "cachesize", 9, FALSE);
355 info.btree.cachesize = svp ? SvIV(*svp) : 0;
356
357 svp = hv_fetch(action, "minkeypage", 10, FALSE);
358 info.btree.minkeypage = svp ? SvIV(*svp) : 0;
359
360 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
361 info.btree.maxkeypage = svp ? SvIV(*svp) : 0;
362
363 svp = hv_fetch(action, "psize", 5, FALSE);
364 info.btree.psize = svp ? SvIV(*svp) : 0;
365
366 svp = hv_fetch(action, "lorder", 6, FALSE);
367 info.btree.lorder = svp ? SvIV(*svp) : 0;
368
369 PrintBtree(info) ;
370
371 }
372 else if (sv_isa(sv, "DB_File::RECNOINFO"))
373 {
374 type = DB_RECNO ;
375 openinfo = (void *)&info ;
376
377 svp = hv_fetch(action, "flags", 5, FALSE);
378 info.recno.flags = (u_long) svp ? SvIV(*svp) : 0;
379
380 svp = hv_fetch(action, "cachesize", 9, FALSE);
381 info.recno.cachesize = (u_int) svp ? SvIV(*svp) : 0;
382
383 svp = hv_fetch(action, "psize", 5, FALSE);
384 info.recno.psize = (int) svp ? SvIV(*svp) : 0;
385
386 svp = hv_fetch(action, "lorder", 6, FALSE);
387 info.recno.lorder = (int) svp ? SvIV(*svp) : 0;
388
389 svp = hv_fetch(action, "reclen", 6, FALSE);
390 info.recno.reclen = (size_t) svp ? SvIV(*svp) : 0;
391
392 svp = hv_fetch(action, "bval", 4, FALSE);
393 if (svp && SvOK(*svp))
394 {
395 if (SvPOK(*svp))
396 info.recno.bval = (u_char)*SvPV(*svp, na) ;
397 else
398 info.recno.bval = (u_char)(unsigned long) SvIV(*svp) ;
399 }
400 else
401 {
402 if (info.recno.flags & R_FIXEDLEN)
403 info.recno.bval = (u_char) ' ' ;
404 else
405 info.recno.bval = (u_char) '\n' ;
406 }
407
408 svp = hv_fetch(action, "bfname", 6, FALSE);
409 info.recno.bfname = (char *) svp ? SvPV(*svp,na) : 0;
410
411 PrintRecno(info) ;
412 }
413 else
414 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
415 }
416
417
418 RETVAL = dbopen(name, flags, mode, type, openinfo) ;
419
a0d0e21e
LW
420 /* kludge mode on: RETVAL->type for DB_RECNO is set to DB_BTREE
421 so remember a DB_RECNO by saving the address
422 of one of it's internal routines
423 */
3b35bae3 424 if (RETVAL && type == DB_RECNO)
a0d0e21e
LW
425 DB_recno_close = RETVAL->close ;
426
427
428 return (RETVAL) ;
429}
430
431
432static int
433not_here(s)
434char *s;
435{
436 croak("DB_File::%s not implemented on this architecture", s);
437 return -1;
438}
439
440static double
441constant(name, arg)
442char *name;
443int arg;
444{
445 errno = 0;
446 switch (*name) {
447 case 'A':
448 break;
449 case 'B':
450 if (strEQ(name, "BTREEMAGIC"))
451#ifdef BTREEMAGIC
452 return BTREEMAGIC;
453#else
454 goto not_there;
455#endif
456 if (strEQ(name, "BTREEVERSION"))
457#ifdef BTREEVERSION
458 return BTREEVERSION;
459#else
460 goto not_there;
461#endif
462 break;
463 case 'C':
464 break;
465 case 'D':
466 if (strEQ(name, "DB_LOCK"))
467#ifdef DB_LOCK
468 return DB_LOCK;
469#else
470 goto not_there;
471#endif
472 if (strEQ(name, "DB_SHMEM"))
473#ifdef DB_SHMEM
474 return DB_SHMEM;
475#else
476 goto not_there;
477#endif
478 if (strEQ(name, "DB_TXN"))
479#ifdef DB_TXN
480 return (U32)DB_TXN;
481#else
482 goto not_there;
483#endif
484 break;
485 case 'E':
486 break;
487 case 'F':
488 break;
489 case 'G':
490 break;
491 case 'H':
492 if (strEQ(name, "HASHMAGIC"))
493#ifdef HASHMAGIC
494 return HASHMAGIC;
495#else
496 goto not_there;
497#endif
498 if (strEQ(name, "HASHVERSION"))
499#ifdef HASHVERSION
500 return HASHVERSION;
501#else
502 goto not_there;
503#endif
504 break;
505 case 'I':
506 break;
507 case 'J':
508 break;
509 case 'K':
510 break;
511 case 'L':
512 break;
513 case 'M':
514 if (strEQ(name, "MAX_PAGE_NUMBER"))
515#ifdef MAX_PAGE_NUMBER
516 return (U32)MAX_PAGE_NUMBER;
517#else
518 goto not_there;
519#endif
520 if (strEQ(name, "MAX_PAGE_OFFSET"))
521#ifdef MAX_PAGE_OFFSET
522 return MAX_PAGE_OFFSET;
523#else
524 goto not_there;
525#endif
526 if (strEQ(name, "MAX_REC_NUMBER"))
527#ifdef MAX_REC_NUMBER
528 return (U32)MAX_REC_NUMBER;
529#else
530 goto not_there;
531#endif
532 break;
533 case 'N':
534 break;
535 case 'O':
536 break;
537 case 'P':
538 break;
539 case 'Q':
540 break;
541 case 'R':
542 if (strEQ(name, "RET_ERROR"))
543#ifdef RET_ERROR
544 return RET_ERROR;
545#else
546 goto not_there;
547#endif
548 if (strEQ(name, "RET_SPECIAL"))
549#ifdef RET_SPECIAL
550 return RET_SPECIAL;
551#else
552 goto not_there;
553#endif
554 if (strEQ(name, "RET_SUCCESS"))
555#ifdef RET_SUCCESS
556 return RET_SUCCESS;
557#else
558 goto not_there;
559#endif
560 if (strEQ(name, "R_CURSOR"))
561#ifdef R_CURSOR
562 return R_CURSOR;
563#else
564 goto not_there;
565#endif
566 if (strEQ(name, "R_DUP"))
567#ifdef R_DUP
568 return R_DUP;
569#else
570 goto not_there;
571#endif
572 if (strEQ(name, "R_FIRST"))
573#ifdef R_FIRST
574 return R_FIRST;
575#else
576 goto not_there;
577#endif
578 if (strEQ(name, "R_FIXEDLEN"))
579#ifdef R_FIXEDLEN
580 return R_FIXEDLEN;
581#else
582 goto not_there;
583#endif
584 if (strEQ(name, "R_IAFTER"))
585#ifdef R_IAFTER
586 return R_IAFTER;
587#else
588 goto not_there;
589#endif
590 if (strEQ(name, "R_IBEFORE"))
591#ifdef R_IBEFORE
592 return R_IBEFORE;
593#else
594 goto not_there;
595#endif
596 if (strEQ(name, "R_LAST"))
597#ifdef R_LAST
598 return R_LAST;
599#else
600 goto not_there;
601#endif
602 if (strEQ(name, "R_NEXT"))
603#ifdef R_NEXT
604 return R_NEXT;
605#else
606 goto not_there;
607#endif
608 if (strEQ(name, "R_NOKEY"))
609#ifdef R_NOKEY
610 return R_NOKEY;
611#else
612 goto not_there;
613#endif
614 if (strEQ(name, "R_NOOVERWRITE"))
615#ifdef R_NOOVERWRITE
616 return R_NOOVERWRITE;
617#else
618 goto not_there;
619#endif
620 if (strEQ(name, "R_PREV"))
621#ifdef R_PREV
622 return R_PREV;
623#else
624 goto not_there;
625#endif
626 if (strEQ(name, "R_RECNOSYNC"))
627#ifdef R_RECNOSYNC
628 return R_RECNOSYNC;
629#else
630 goto not_there;
631#endif
632 if (strEQ(name, "R_SETCURSOR"))
633#ifdef R_SETCURSOR
634 return R_SETCURSOR;
635#else
636 goto not_there;
637#endif
638 if (strEQ(name, "R_SNAPSHOT"))
639#ifdef R_SNAPSHOT
640 return R_SNAPSHOT;
641#else
642 goto not_there;
643#endif
644 break;
645 case 'S':
646 break;
647 case 'T':
648 break;
649 case 'U':
650 break;
651 case 'V':
652 break;
653 case 'W':
654 break;
655 case 'X':
656 break;
657 case 'Y':
658 break;
659 case 'Z':
660 break;
661 case '_':
662 if (strEQ(name, "__R_UNUSED"))
663#ifdef __R_UNUSED
664 return __R_UNUSED;
665#else
666 goto not_there;
667#endif
668 break;
669 }
670 errno = EINVAL;
671 return 0;
672
673not_there:
674 errno = ENOENT;
675 return 0;
676}
677
678MODULE = DB_File PACKAGE = DB_File PREFIX = db_
679
680double
681constant(name,arg)
682 char * name
683 int arg
684
685
686DB_File
687db_TIEHASH(dbtype, name=undef, flags=O_RDWR, mode=0640, type=DB_HASH)
688 char * dbtype
689 int flags
690 int mode
691 CODE:
692 {
693 char * name = (char *) NULL ;
694 SV * sv = (SV *) NULL ;
695
696 if (items >= 2 && SvOK(ST(1)))
697 name = (char*) SvPV(ST(1), na) ;
698
699 if (items == 5)
700 sv = ST(4) ;
701
702 RETVAL = ParseOpenInfo(name, flags, mode, sv, "new") ;
703 }
704 OUTPUT:
705 RETVAL
706
707BOOT:
708 newXS("DB_File::TIEARRAY", XS_DB_File_db_TIEHASH, file);
709
710int
711db_DESTROY(db)
712 DB_File db
713
714
715int
716db_DELETE(db, key, flags=0)
717 DB_File db
718 DBTKEY key
719 u_int flags
720
721int
722db_FETCH(db, key, flags=0)
723 DB_File db
724 DBTKEY key
725 u_int flags
726 CODE:
727 {
728 DBT value ;
729
730 RETVAL = (db->get)(db, &key, &value, flags) ;
731 ST(0) = sv_newmortal();
732 if (RETVAL == 0)
733 sv_setpvn(ST(0), value.data, value.size);
734 }
735
736int
737db_STORE(db, key, value, flags=0)
738 DB_File db
739 DBTKEY key
740 DBT value
741 u_int flags
742
743
744int
745db_FIRSTKEY(db)
746 DB_File db
747 CODE:
748 {
749 DBTKEY key ;
750 DBT value ;
751
752 RETVAL = (db->seq)(db, &key, &value, R_FIRST) ;
753 ST(0) = sv_newmortal();
754 if (RETVAL == 0)
755 {
756 if (db->type != DB_RECNO)
757 sv_setpvn(ST(0), key.data, key.size);
758 else
759 sv_setiv(ST(0), (I32)*(I32*)key.data - 1);
760 }
761 }
762
763int
764db_NEXTKEY(db, key)
765 DB_File db
766 DBTKEY key
767 CODE:
768 {
769 DBT value ;
770
771 RETVAL = (db->seq)(db, &key, &value, R_NEXT) ;
772 ST(0) = sv_newmortal();
773 if (RETVAL == 0)
774 {
775 if (db->type != DB_RECNO)
776 sv_setpvn(ST(0), key.data, key.size);
777 else
778 sv_setiv(ST(0), (I32)*(I32*)key.data - 1);
779 }
780 }
781
782#
783# These would be nice for RECNO
784#
785
786int
787unshift(db, ...)
788 DB_File db
789 CODE:
790 {
791 DBTKEY key ;
792 DBT value ;
793 int i ;
794 int One ;
795
796 RETVAL = -1 ;
797 for (i = items-1 ; i > 0 ; --i)
798 {
799 value.data = SvPV(ST(i), na) ;
800 value.size = na ;
801 One = 1 ;
802 key.data = &One ;
803 key.size = sizeof(int) ;
804 RETVAL = (db->put)(db, &key, &value, R_IBEFORE) ;
805 if (RETVAL != 0)
806 break;
807 }
808 }
809 OUTPUT:
810 RETVAL
811
812I32
813pop(db)
814 DB_File db
815 CODE:
816 {
817 DBTKEY key ;
818 DBT value ;
819
820 /* First get the final value */
821 RETVAL = (db->seq)(db, &key, &value, R_LAST) ;
822 ST(0) = sv_newmortal();
823 /* Now delete it */
824 if (RETVAL == 0)
825 {
826 RETVAL = (db->del)(db, &key, R_CURSOR) ;
827 if (RETVAL == 0)
828 sv_setpvn(ST(0), value.data, value.size);
829 }
830 }
831
832I32
833shift(db)
834 DB_File db
835 CODE:
836 {
837 DBTKEY key ;
838 DBT value ;
839
840 /* get the first value */
841 RETVAL = (db->seq)(db, &key, &value, R_FIRST) ;
842 ST(0) = sv_newmortal();
843 /* Now delete it */
844 if (RETVAL == 0)
845 {
846 RETVAL = (db->del)(db, &key, R_CURSOR) ;
847 if (RETVAL == 0)
848 sv_setpvn(ST(0), value.data, value.size);
849 }
850 }
851
852
853I32
854push(db, ...)
855 DB_File db
856 CODE:
857 {
858 DBTKEY key ;
859 DBT value ;
860 int i ;
861
862 /* Set the Cursor to the Last element */
863 RETVAL = (db->seq)(db, &key, &value, R_LAST) ;
864 if (RETVAL == 0)
865 {
866 /* for (i = 1 ; i < items ; ++i) */
867 for (i = items - 1 ; i > 0 ; --i)
868 {
869 value.data = SvPV(ST(i), na) ;
870 value.size = na ;
871 RETVAL = (db->put)(db, &key, &value, R_IAFTER) ;
872 if (RETVAL != 0)
873 break;
874 }
875 }
876 }
877 OUTPUT:
878 RETVAL
879
880
881I32
882length(db)
883 DB_File db
884 CODE:
885 RETVAL = GetArrayLength(db) ;
886 OUTPUT:
887 RETVAL
888
889
890#
891# Now provide an interface to the rest of the DB functionality
892#
893
894int
895db_del(db, key, flags=0)
896 DB_File db
897 DBTKEY key
898 u_int flags
899
900
901int
902db_get(db, key, value, flags=0)
903 DB_File db
904 DBTKEY key
905 DBT value
906 u_int flags
907 OUTPUT:
908 value
909
910int
911db_put(db, key, value, flags=0)
912 DB_File db
913 DBTKEY key
914 DBT value
915 u_int flags
916 OUTPUT:
917 key if (flags & (R_IAFTER|R_IBEFORE)) OutputKey(ST(1), key);
918
919int
920db_fd(db)
921 DB_File db
922
923int
924db_sync(db, flags=0)
925 DB_File db
926 u_int flags
927
928
929int
930db_seq(db, key, value, flags)
931 DB_File db
932 DBTKEY key
933 DBT value
934 u_int flags
935 OUTPUT:
936 key
937 value