/*-1* SPDX-License-Identifier: BSD-3-Clause2*3* Copyright (c) 1990, 1993, 19944* The Regents of the University of California. All rights reserved.5*6* This code is derived from software contributed to Berkeley by7* Mike Olson.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12* 1. Redistributions of source code must retain the above copyright13* notice, this list of conditions and the following disclaimer.14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17* 3. Neither the name of the University nor the names of its contributors18* may be used to endorse or promote products derived from this software19* without specific prior written permission.20*21* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND22* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE23* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE24* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE25* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL26* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS27* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)28* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT29* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY30* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF31* SUCH DAMAGE.32*/3334#include <sys/types.h>3536#include <errno.h>37#include <stdio.h>38#include <string.h>3940#include <db.h>41#include "recno.h"4243static int rec_rdelete(BTREE *, recno_t);4445/*46* __REC_DELETE -- Delete the item(s) referenced by a key.47*48* Parameters:49* dbp: pointer to access method50* key: key to delete51* flags: R_CURSOR if deleting what the cursor references52*53* Returns:54* RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.55*/56int57__rec_delete(const DB *dbp, const DBT *key, u_int flags)58{59BTREE *t;60recno_t nrec;61int status;6263t = dbp->internal;6465/* Toss any page pinned across calls. */66if (t->bt_pinned != NULL) {67mpool_put(t->bt_mp, t->bt_pinned, 0);68t->bt_pinned = NULL;69}7071switch(flags) {72case 0:73if ((nrec = *(recno_t *)key->data) == 0)74goto einval;75if (nrec > t->bt_nrecs)76return (RET_SPECIAL);77--nrec;78status = rec_rdelete(t, nrec);79break;80case R_CURSOR:81if (!F_ISSET(&t->bt_cursor, CURS_INIT))82goto einval;83if (t->bt_nrecs == 0)84return (RET_SPECIAL);85status = rec_rdelete(t, t->bt_cursor.rcursor - 1);86if (status == RET_SUCCESS)87--t->bt_cursor.rcursor;88break;89default:90einval: errno = EINVAL;91return (RET_ERROR);92}9394if (status == RET_SUCCESS)95F_SET(t, B_MODIFIED | R_MODIFIED);96return (status);97}9899/*100* REC_RDELETE -- Delete the data matching the specified key.101*102* Parameters:103* tree: tree104* nrec: record to delete105*106* Returns:107* RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.108*/109static int110rec_rdelete(BTREE *t, recno_t nrec)111{112EPG *e;113PAGE *h;114int status;115116/* Find the record; __rec_search pins the page. */117if ((e = __rec_search(t, nrec, SDELETE)) == NULL)118return (RET_ERROR);119120/* Delete the record. */121h = e->page;122status = __rec_dleaf(t, h, e->index);123if (status != RET_SUCCESS) {124mpool_put(t->bt_mp, h, 0);125return (status);126}127mpool_put(t->bt_mp, h, MPOOL_DIRTY);128return (RET_SUCCESS);129}130131/*132* __REC_DLEAF -- Delete a single record from a recno leaf page.133*134* Parameters:135* t: tree136* idx: index on current page to delete137*138* Returns:139* RET_SUCCESS, RET_ERROR.140*/141int142__rec_dleaf(BTREE *t, PAGE *h, u_int32_t idx)143{144RLEAF *rl;145indx_t *ip, cnt, offset;146u_int32_t nbytes;147char *from;148void *to;149150/*151* Delete a record from a recno leaf page. Internal records are never152* deleted from internal pages, regardless of the records that caused153* them to be added being deleted. Pages made empty by deletion are154* not reclaimed. They are, however, made available for reuse.155*156* Pack the remaining entries at the end of the page, shift the indices157* down, overwriting the deleted record and its index. If the record158* uses overflow pages, make them available for reuse.159*/160to = rl = GETRLEAF(h, idx);161if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR)162return (RET_ERROR);163nbytes = NRLEAF(rl);164165/*166* Compress the key/data pairs. Compress and adjust the [BR]LEAF167* offsets. Reset the headers.168*/169from = (char *)h + h->upper;170memmove(from + nbytes, from, (char *)to - from);171h->upper += nbytes;172173offset = h->linp[idx];174for (cnt = &h->linp[idx] - (ip = &h->linp[0]); cnt--; ++ip)175if (ip[0] < offset)176ip[0] += nbytes;177for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip)178ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];179h->lower -= sizeof(indx_t);180--t->bt_nrecs;181return (RET_SUCCESS);182}183184185