xref: /original-bsd/lib/libc/db/recno/rec_delete.c (revision 289f3818)
16b79e351Sbostic /*-
2d374c3f7Sbostic  * Copyright (c) 1990, 1993
3d374c3f7Sbostic  *	The Regents of the University of California.  All rights reserved.
46b79e351Sbostic  *
56b79e351Sbostic  * This code is derived from software contributed to Berkeley by
66b79e351Sbostic  * Mike Olson.
76b79e351Sbostic  *
86b79e351Sbostic  * %sccs.include.redist.c%
96b79e351Sbostic  */
106b79e351Sbostic 
116b79e351Sbostic #if defined(LIBC_SCCS) && !defined(lint)
12*289f3818Sbostic static char sccsid[] = "@(#)rec_delete.c	8.4 (Berkeley) 02/21/94";
136b79e351Sbostic #endif /* LIBC_SCCS and not lint */
146b79e351Sbostic 
156b79e351Sbostic #include <sys/types.h>
162b49cb62Sbostic 
172b49cb62Sbostic #include <errno.h>
186b79e351Sbostic #include <stdio.h>
196b79e351Sbostic #include <string.h>
202b49cb62Sbostic 
2131ddc4efSbostic #include <db.h>
22b4957051Sbostic #include "recno.h"
236b79e351Sbostic 
246b79e351Sbostic static int rec_rdelete __P((BTREE *, recno_t));
256b79e351Sbostic 
266b79e351Sbostic /*
276b79e351Sbostic  * __REC_DELETE -- Delete the item(s) referenced by a key.
286b79e351Sbostic  *
296b79e351Sbostic  * Parameters:
306b79e351Sbostic  *	dbp:	pointer to access method
316b79e351Sbostic  *	key:	key to delete
326b79e351Sbostic  *	flags:	R_CURSOR if deleting what the cursor references
336b79e351Sbostic  *
346b79e351Sbostic  * Returns:
356b79e351Sbostic  *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
366b79e351Sbostic  */
376b79e351Sbostic int
__rec_delete(dbp,key,flags)386b79e351Sbostic __rec_delete(dbp, key, flags)
396b79e351Sbostic 	const DB *dbp;
406b79e351Sbostic 	const DBT *key;
416b79e351Sbostic 	u_int flags;
426b79e351Sbostic {
436b79e351Sbostic 	BTREE *t;
446b79e351Sbostic 	recno_t nrec;
456b79e351Sbostic 	int status;
466b79e351Sbostic 
47b4957051Sbostic 	t = dbp->internal;
4843c22bd4Sbostic 
4943c22bd4Sbostic 	/* Toss any page pinned across calls. */
5043c22bd4Sbostic 	if (t->bt_pinned != NULL) {
5143c22bd4Sbostic 		mpool_put(t->bt_mp, t->bt_pinned, 0);
5243c22bd4Sbostic 		t->bt_pinned = NULL;
5343c22bd4Sbostic 	}
5443c22bd4Sbostic 
55b4957051Sbostic 	switch(flags) {
56b4957051Sbostic 	case 0:
572b49cb62Sbostic 		if ((nrec = *(recno_t *)key->data) == 0)
582b49cb62Sbostic 			goto einval;
59b4957051Sbostic 		if (nrec > t->bt_nrecs)
60b4957051Sbostic 			return (RET_SPECIAL);
616b79e351Sbostic 		--nrec;
626b79e351Sbostic 		status = rec_rdelete(t, nrec);
636b79e351Sbostic 		break;
646b79e351Sbostic 	case R_CURSOR:
65486a4811Sbostic 		if (!ISSET(t, B_SEQINIT))
662b49cb62Sbostic 			goto einval;
672b49cb62Sbostic 		if (t->bt_nrecs == 0)
68b4957051Sbostic 			return (RET_SPECIAL);
69b4957051Sbostic 		status = rec_rdelete(t, t->bt_rcursor - 1);
702b49cb62Sbostic 		if (status == RET_SUCCESS)
71b4957051Sbostic 			--t->bt_rcursor;
726b79e351Sbostic 		break;
736b79e351Sbostic 	default:
742b49cb62Sbostic einval:		errno = EINVAL;
756b79e351Sbostic 		return (RET_ERROR);
766b79e351Sbostic 	}
776b79e351Sbostic 
78f6759fb1Sbostic 	if (status == RET_SUCCESS)
79486a4811Sbostic 		SET(t, B_MODIFIED | R_MODIFIED);
806b79e351Sbostic 	return (status);
816b79e351Sbostic }
826b79e351Sbostic 
836b79e351Sbostic /*
846b79e351Sbostic  * REC_RDELETE -- Delete the data matching the specified key.
856b79e351Sbostic  *
866b79e351Sbostic  * Parameters:
876b79e351Sbostic  *	tree:	tree
886b79e351Sbostic  *	nrec:	record to delete
896b79e351Sbostic  *
906b79e351Sbostic  * Returns:
916b79e351Sbostic  *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
926b79e351Sbostic  */
936b79e351Sbostic static int
rec_rdelete(t,nrec)946b79e351Sbostic rec_rdelete(t, nrec)
956b79e351Sbostic 	BTREE *t;
966b79e351Sbostic 	recno_t nrec;
976b79e351Sbostic {
986b79e351Sbostic 	EPG *e;
996b79e351Sbostic 	PAGE *h;
100b4957051Sbostic 	int status;
1016b79e351Sbostic 
102b4957051Sbostic 	/* Find the record; __rec_search pins the page. */
103ec643737Sbostic 	if ((e = __rec_search(t, nrec, SDELETE)) == NULL)
104b4957051Sbostic 		return (RET_ERROR);
1056b79e351Sbostic 
1066b79e351Sbostic 	/* Delete the record. */
1076b79e351Sbostic 	h = e->page;
1086b79e351Sbostic 	status = __rec_dleaf(t, h, e->index);
109b4957051Sbostic 	if (status != RET_SUCCESS) {
1106b79e351Sbostic 		mpool_put(t->bt_mp, h, 0);
1116b79e351Sbostic 		return (status);
1126b79e351Sbostic 	}
1136b79e351Sbostic 	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
1146b79e351Sbostic 	return (RET_SUCCESS);
1156b79e351Sbostic }
1166b79e351Sbostic 
1176b79e351Sbostic /*
1186b79e351Sbostic  * __REC_DLEAF -- Delete a single record from a recno leaf page.
1196b79e351Sbostic  *
1206b79e351Sbostic  * Parameters:
1216b79e351Sbostic  *	t:	tree
1226b79e351Sbostic  *	index:	index on current page to delete
1236b79e351Sbostic  *
1246b79e351Sbostic  * Returns:
1256b79e351Sbostic  *	RET_SUCCESS, RET_ERROR.
1266b79e351Sbostic  */
1276b79e351Sbostic int
__rec_dleaf(t,h,index)1286b79e351Sbostic __rec_dleaf(t, h, index)
1296b79e351Sbostic 	BTREE *t;
1306b79e351Sbostic 	PAGE *h;
131*289f3818Sbostic 	indx_t index;
1326b79e351Sbostic {
1336b79e351Sbostic 	register RLEAF *rl;
134*289f3818Sbostic 	register indx_t *ip, cnt, offset;
1356b79e351Sbostic 	register size_t nbytes;
1366b79e351Sbostic 	char *from;
1376b79e351Sbostic 	void *to;
1386b79e351Sbostic 
1396b79e351Sbostic 	/*
1406b79e351Sbostic 	 * Delete a record from a recno leaf page.  Internal records are never
1416b79e351Sbostic 	 * deleted from internal pages, regardless of the records that caused
1426b79e351Sbostic 	 * them to be added being deleted.  Pages made empty by deletion are
1436b79e351Sbostic 	 * not reclaimed.  They are, however, made available for reuse.
1446b79e351Sbostic 	 *
1456b79e351Sbostic 	 * Pack the remaining entries at the end of the page, shift the indices
1466b79e351Sbostic 	 * down, overwriting the deleted record and its index.  If the record
1476b79e351Sbostic 	 * uses overflow pages, make them available for reuse.
1486b79e351Sbostic 	 */
1496b79e351Sbostic 	to = rl = GETRLEAF(h, index);
1506b79e351Sbostic 	if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR)
1516b79e351Sbostic 		return (RET_ERROR);
1526b79e351Sbostic 	nbytes = NRLEAF(rl);
1536b79e351Sbostic 
1546b79e351Sbostic 	/*
1556b79e351Sbostic 	 * Compress the key/data pairs.  Compress and adjust the [BR]LEAF
1566b79e351Sbostic 	 * offsets.  Reset the headers.
1576b79e351Sbostic 	 */
1586b79e351Sbostic 	from = (char *)h + h->upper;
15968e0032fSbostic 	memmove(from + nbytes, from, (char *)to - from);
1606b79e351Sbostic 	h->upper += nbytes;
1616b79e351Sbostic 
1626b79e351Sbostic 	offset = h->linp[index];
1636b79e351Sbostic 	for (cnt = &h->linp[index] - (ip = &h->linp[0]); cnt--; ++ip)
1646b79e351Sbostic 		if (ip[0] < offset)
1656b79e351Sbostic 			ip[0] += nbytes;
1666b79e351Sbostic 	for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip)
1676b79e351Sbostic 		ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
168b6ca0705Sbostic 	h->lower -= sizeof(indx_t);
169f6759fb1Sbostic 	--t->bt_nrecs;
1706b79e351Sbostic 	return (RET_SUCCESS);
1716b79e351Sbostic }
172