/*-
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Mike Olson.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#endif /* LIBC_SCCS and not lint */
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "db-int.h"
#include "btree.h"
/*
* __bt_delete
* Delete the item(s) referenced by a key.
*
* Return RET_SPECIAL if the key is not found.
*/
int
{
BTREE *t;
CURSOR *c;
PAGE *h;
int status;
/* Toss any page pinned across calls. */
}
/* Check for change to a read-only tree. */
return (RET_ERROR);
}
switch (flags) {
case 0:
break;
case R_CURSOR:
/*
* If flags is R_CURSOR, delete the cursor. Must already
* have started a scan and not have already deleted it.
*/
c = &t->bt_cursor;
return (RET_SPECIAL);
return (RET_ERROR);
/*
* If the page is about to be emptied, we'll need to
* delete it, which means we have to acquire a stack.
*/
if (NEXTINDEX(h) == 1)
if (__bt_stkacq(t, &h, &t->bt_cursor))
return (RET_ERROR);
if (__bt_pdelete(t, h))
return (RET_ERROR);
} else
break;
}
/* FALLTHROUGH */
default:
return (RET_ERROR);
}
if (status == RET_SUCCESS)
F_SET(t, B_MODIFIED);
return (status);
}
/*
* __bt_stkacq --
* Acquire a stack so we can delete a cursor entry.
*
* Parameters:
* t: tree
* hp: pointer to current, pinned PAGE pointer
* c: pointer to the cursor
*
* Returns:
* 0 on success, 1 on failure
*/
static int
BTREE *t;
CURSOR *c;
{
EPG *e;
PAGE *h;
/*
* Find the first occurrence of the key in the tree. Toss the
* currently locked page so we don't hit an already-locked page.
*/
h = *hp;
return (1);
h = e->page;
/* See if we got it in one shot. */
goto ret;
/*
* Move right, looking for the page. At each move we have to move
* up the stack until we don't have to move to the next page. If
* we have to change pages at an internal level, we have to fix the
* stack back up.
*/
break;
/* Move up the stack. */
/* Get the parent page. */
return (1);
/* Move to the next index. */
break;
}
}
/* Restore the stack. */
while (level--) {
/* Push the next level down onto the stack. */
/* Lose the currently pinned page. */
/* Get the next level down. */
return (1);
idx = 0;
}
return (1);
}
goto ret;
/* Reacquire the original stack. */
return (1);
h = e->page;
/*
* Move left, looking for the page. At each move we have to move
* up the stack until we don't have to change pages to move to the
* next page. If we have to change pages at an internal level, we
* have to fix the stack back up.
*/
break;
/* Move up the stack. */
/* Get the parent page. */
return (1);
/* Move to the next index. */
break;
}
}
/* Restore the stack. */
while (level--) {
/* Push the next level down onto the stack. */
/* Lose the currently pinned page. */
/* Get the next level down. */
return (1);
}
return (1);
}
}
/*
* __bt_bdelete --
*
* Parameters:
* t: tree
* key: key to delete
*
* Returns:
* RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
*/
static int
BTREE *t;
{
EPG *e;
PAGE *h;
deleted = 0;
/* Find any matching record; __bt_search pins the page. */
if (!exact) {
}
/*
* Delete forward, then delete backward, from the found key. If
* there are duplicates and we reach either side of the page, do
* the key search again, so that we get them all.
*/
redo = 0;
h = e->page;
do {
return (RET_ERROR);
}
if (NEXTINDEX(h) == 0) {
if (__bt_pdelete(t, h))
return (RET_ERROR);
} else
return (RET_SUCCESS);
}
deleted = 1;
/* Check for right-hand edge of the page. */
redo = 1;
/* Delete from the key to the beginning of the page. */
while (e->index-- > 0) {
break;
return (RET_ERROR);
}
if (e->index == 0)
redo = 1;
}
/* Check for an empty page. */
if (NEXTINDEX(h) == 0) {
if (__bt_pdelete(t, h))
return (RET_ERROR);
goto loop;
}
/* Put the page. */
if (redo)
goto loop;
return (RET_SUCCESS);
}
/*
* __bt_pdelete --
* Delete a single page from the tree.
*
* Parameters:
* t: tree
* h: leaf page
*
* Returns:
* RET_SUCCESS, RET_ERROR.
*
* Side-effects:
* mpool_put's the page
*/
static int
__bt_pdelete(t, h)
BTREE *t;
PAGE *h;
{
char *from;
/*
* Walk the parent page stack -- a LIFO stack of the pages that were
* traversed when we searched for the page where the delete occurred.
* Each stack entry is a page number and a page index offset. The
* offset is for the page traversed on the search. We've just deleted
* a page, so we have to delete the key from the parent page.
*
* If the delete from the parent page makes it empty, this process may
* continue all the way up the tree. We stop if we reach the root page
* (which is never deleted, it's just not worth the effort) or if the
* delete does not empty the page.
*/
/* Get the parent page. */
return (RET_ERROR);
/* Free any overflow pages. */
return (RET_ERROR);
}
/*
* Free the parent if it has only the one key and it's not the
* root page. If it's the rootpage, turn it back into an empty
* leaf page.
*/
} else {
return (RET_ERROR);
continue;
}
else {
/* Pack remaining key items at the end of the page. */
/* Adjust indices' offsets, shift the indices down. */
}
break;
}
/* Free the leaf page, as long as it wasn't the root. */
return (RET_SUCCESS);
}
return (__bt_relink(t, h) || __bt_free(t, h));
}
/*
* __bt_dleaf --
* Delete a single record from a leaf page.
*
* Parameters:
* t: tree
* key: referenced key
* h: page
* idx: index on page to delete
*
* Returns:
* RET_SUCCESS, RET_ERROR.
*/
int
BTREE *t;
PAGE *h;
{
void *to;
char *from;
/* If this record is referenced by the cursor, delete the cursor. */
return (RET_ERROR);
/* If the entry uses overflow pages, make them available for reuse. */
return (RET_ERROR);
return (RET_ERROR);
/* Adjust the indices' offsets, shift the indices down. */
/* If the cursor is on this page, adjust it as necessary. */
return (RET_SUCCESS);
}
/*
* __bt_curdel --
* Delete the cursor.
*
* Parameters:
* t: tree
* key: referenced key (or NULL)
* h: page
* idx: idx on page to delete
*
* Returns:
* RET_SUCCESS, RET_ERROR.
*/
static int
BTREE *t;
PAGE *h;
{
CURSOR *c;
EPG e;
/*
* If there are duplicates, move forward or backward to one.
* Otherwise, copy the key into the cursor area.
*/
c = &t->bt_cursor;
curcopy = 0;
/*
* We're going to have to do comparisons. If we weren't
* provided a copy of the key, i.e. the user is deleting
* the current cursor position, get one.
*/
e.page = h;
return (status);
curcopy = 1;
}
/* Check previous key, if not at the beginning of the page. */
if (idx > 0) {
e.page = h;
F_SET(c, CURS_BEFORE);
goto dup2;
}
}
/* Check next key, if not at the end of the page. */
e.page = h;
F_SET(c, CURS_AFTER);
goto dup2;
}
}
/* Check previous key if at the beginning of the page. */
return (RET_ERROR);
F_SET(c, CURS_BEFORE);
goto dup1;
}
}
/* Check next key if at the end of the page. */
return (RET_ERROR);
e.index = 0;
F_SET(c, CURS_AFTER);
return (RET_SUCCESS);
}
}
}
e.page = h;
F_SET(c, CURS_ACQUIRE);
return (RET_SUCCESS);
}
return (status);
}
/*
* __bt_relink --
* Link around a deleted page.
*
* Parameters:
* t: tree
* h: page to be deleted
*/
static int
__bt_relink(t, h)
BTREE *t;
PAGE *h;
{
return (RET_ERROR);
}
return (RET_ERROR);
}
return (0);
}