blob: b454fd96b38c321be55f0705a84052814b4d1dc8 [file] [log] [blame]
/*
* Name: delete
* Input: root node of index, root
* search index key, searchKey
* search non-key list, searchNonKey
* Output: updated node, node
* Return: DELETE_SUCCESS, or
* DELETE_INVALID_KEY_SEARCH_VALUE,
* DELETE_INVALID_NON_KEY_SEARCH_VALUE
* Description: The routine searches the current index and removes all data
* objects which are consistent with the search input values,
* key and non-key. The routine makes use of the recursive
* routine deleteEntry() to perform the actual search and
* removal of data objects in the index. The deleteEntry()
* routine will also remove empty nodes from the index all the
* way up to the root node. After the return from
* deleteEntry(), two checks need to be made. The first checks
* to see if the current root node level is not a LEAF and the
* list of entries for the root node is empty, i.e., NULL.
* This case indicates that the input search values completely
* removed every data object in the index and thus all nodes
* except the root node. For this case, the level for the root
* is reset to the LEAF level and the updated root node is
* returned. The second case checks to see if the root node
* has only one entry in its list. The R-Tree is required to
* replace any root node with only one child with the child
* node, unless the root is a LEAF node.
* Calls: deleteEntry()
* errorMessage()
* validIndexKey()
* validAttributes()
* System: free()
* Author: M.L.Rivas
*
* Revision History:
*
* Date Name Revision
* ------- --------------- ------------------------------
* 27May99 Matthew Rivas Created
*
* Copyright 1999, Atlantic Aerospace Electronics Corp.
*/
#include <assert.h> /* for assert() */
#include <stdlib.h> /* for free() and NULL definitions */
#include "dataManagement.h" /* for primitive type definitions */
#include "errorMessage.h" /* for errorMessage() definition */
#include "dataObject.h" /* for DataAttribute definition */
#include "index.h" /* for IndexNode and IndexEntry definitions */
#include "indexKey.h" /* for IndexKey definition */
#include "delete.h" /* for delete() return codes */
/*
* Function prototypes
*/
extern Boolean validIndexKey( IndexKey *key );
extern Boolean validAttributes( DataAttribute *attributes );
extern void deleteEntry( IndexNode *node, IndexKey *searchKey,
DataAttribute *searchNonKey, Boolean *adjustmentFlag );
Int delete( IndexNode **root, /* root node of index */
IndexKey *searchKey, /* index key search values */
DataAttribute *searchNonKey ) /* non-key search values */
{ /* beginning of delete() */
Boolean adjustmentFlag; /* place-holder for deleteEntry routine */
static Char name[] = "delete";
assert( root );
assert( *root );
assert( searchKey );
assert( LEAF >= 0 );
/*
* Check validity of search values
*/
if ( validIndexKey( searchKey ) == FALSE ) {
errorMessage( "invalid index key search values", REPLACE );
errorMessage( name, PREPEND );
return ( DELETE_INVALID_KEY_SEARCH_VALUE );
} /* end validity check of key values */
else if ( validAttributes( searchNonKey ) == FALSE ) {
errorMessage( "invalid non-key search values", REPLACE );
errorMessage( name, PREPEND );
return ( DELETE_INVALID_NON_KEY_SEARCH_VALUE );
} /* end validity check of non-key values */
/*
* Call deleteEntry routine for root node which will recursively process
* the entire index. Note that the adjustment flag is passed to
* deleteEntry but its not needed for the root node since adjustments would
* be made to the parent which the root node does not have.
*/
deleteEntry( *root, searchKey, searchNonKey, &adjustmentFlag );
/*
* Check case where level of the root node is not LEAF and there are no
* entries residing on root node, i.e., entries == NULL. This indicates
* that the input search values completely removed all of the data objects
* referenced by the index, which will also remove all index nodes and
* entries in the index except for the root node. Because there are no
* more objects in the index, simply set the current level of the root node
* to be the LEAF level and continue.
*/
if ( (*root)->level > LEAF && (*root)->entries == NULL ) {
(*root)->level = LEAF;
}
/*
* If there is at least one entry on the current root node (root->entries
* != NULL), but there is only one entry ((root->entries)->next == NULL),
* then replace the root node with the only child unless the root node is a
* LEAF node. This behavior is required by the R-Tree definition. The old
* root node is deleted, but the entries is first set to EMPTY/NULL. This
* prevents the deleteIndexNode() routine from removing the child entry
* which has become the new root.
*/
while ( (*root)->level != LEAF && /* current root not LEAF */
(*root)->entries != NULL && /* at least one child entry */
((*root)->entries)->next == NULL ) { /* only one child entry */
IndexNode *temp; /* placeholder for old root to delete */
temp = (*root); /* save old root for removal */
*root = ((*root)->entries)->child.node; /* replace root with child */
/* which is referenced by */
/* entries */
free( temp->entries ); /* delete old entry which */
/* referenced old root's */
/* child which is now the */
/* new root. */
temp->entries = NULL; /* Need to set the value to */
/* NULL which will prevent */
/* the next step from */
/* deleting the entire index */
deleteIndexNode( temp ); /* delete old root node */
} /* end of loop for checking number of entries <= 1 */
return ( DELETE_SUCCESS );
} /* end delete() */