home *** CD-ROM | disk | FTP | other *** search
- /*
- * IDELETE.C - delete a record
- *
- * Copyright (c) 1987, Jim Mischel
- */
-
- #include "inxdefs.h"
-
- /*
- * idelete() - remove the current record from the data stream. The data
- * record is not actually removed from the file and the index record is not
- * removed from the index file. The index pointers are adjusted so that
- * they skip over the index for this record.
- * Returns 0 if successful, error status otherwise. If the key at 'source'
- * is not the same as the key in the current data record, I_INVKEY is
- * returned and no action is taken. Since the only integrity check
- * made is a simple key comparison, if duplicate keys are permitted, it
- * is possible to delete the wrong record.
- */
- int idelete(void *d, void *src)
- {
- register df_rec *db_control = (df_rec *)d;
- char *source = (char *)src;
- register inx_rec *irec;
- inx_rec save_inx_rec;
- long save_inx_ptr;
-
- /* see if record has already been deleted */
- if (db_control->df_flags & DF_DELETE)
- return(ierror(I_INVKEY));
-
- /* see if keys are equal */
- if ((*db_control->df_cmp)((source+db_control->df_key_offset),
- db_control->df_key_ptr))
- return(ierror(I_INVKEY)); /* error: keys not equal */
-
- /*
- * There are 3 cases to worry about:
- * 1. The node is a leaf
- * 2. The node has only 1 son
- * 3. The node has 2 sons
- */
-
- /* setup a pointer to the current index record */
- irec = &db_control->df_inx_buff;
- memcpy(&save_inx_rec,irec,sizeof(inx_rec)); /* copy current index rec */
- save_inx_ptr = db_control->df_inx_ptr; /* save current index pointer */
-
- if ((irec->if_flags & RTHRD) && (irec->if_flags & LTHRD)) {
-
- /*
- * the node has no descendents (leaf)
- */
- if (iread_inx(db_control,irec->if_parent)) /* get parent node */
- return(ierrno);
-
- if (irec->if_left_node == save_inx_ptr) { /* node is a left son */
- irec->if_left_node = save_inx_rec.if_left_node;
- irec->if_flags |= ((save_inx_rec.if_flags & BTHRD) | LTHRD);
- }
- else { /* node is a right son */
- irec->if_right_node = save_inx_rec.if_right_node;
- irec->if_flags |= ((save_inx_rec.if_flags & ETHRD) | RTHRD);
- }
- if (iwrite_inx(db_control,irec,db_control->df_inx_ptr))
- return(ierrno);
- }
- else if ((irec->if_flags & LTHRD) || (irec->if_flags & RTHRD)) {
-
- /*
- * the node has only one son
- */
- long node_ptr;
- int son;
-
- if (irec->if_flags & RTHRD)
- node_ptr = irec->if_left_node;
- else
- node_ptr = irec->if_right_node;
-
- /* adjust parent node */
- if (iread_inx(db_control,irec->if_parent))
- return(ierrno);
-
- if (irec->if_left_node == save_inx_ptr) { /* left son */
- son = -1;
- irec->if_left_node = node_ptr;
- }
- else { /* right son */
- son = 1;
- irec->if_right_node = node_ptr;
- }
-
- if (iwrite_inx(db_control,irec,db_control->df_inx_ptr))
- return(ierrno);
-
- /* adjust only son */
- if (iread_inx(db_control,node_ptr))
- return(ierrno);
- if (irec->if_right_node == save_inx_ptr)
- irec->if_right_node = save_inx_rec.if_parent;
- else if (irec->if_left_node == save_inx_ptr)
- irec->if_left_node = save_inx_rec.if_parent;
- irec->if_parent = save_inx_rec.if_parent;
- if (iwrite_inx(db_control,irec,db_control->df_inx_ptr))
- return(ierrno);
-
- /* adjust inorder successor/predecessor */
- if (son == -1) {
- if (iget_prev(db_control,&save_inx_rec))
- return(ierrno);
- irec->if_right_node = save_inx_ptr;
- }
- else {
- if (iget_next(db_control,&save_inx_rec))
- return(ierrno);
- irec->if_left_node = save_inx_ptr;
- }
- if (iwrite_inx(db_control,irec,db_control->df_inx_ptr))
- return(ierrno);
- }
- else {
- /*
- * the node has two sons
- */
- inx_rec save_parent,
- save_prev;
- long save_prev_ptr;
-
- if (iread_inx(db_control,irec->if_parent)) /* get parent node */
- return(ierrno);
- memcpy(&save_parent,irec,sizeof(inx_rec)); /* and save it */
-
- /*
- * the deleted node will be replaced by its inorder predecessor
- */
-
- if (iget_prev(db_control,&save_inx_rec))
- return(ierrno);
- memcpy(&save_prev,irec,sizeof(inx_rec)); /* and save it */
- save_prev_ptr = db_control->df_inx_ptr;
-
- /*
- * adjust the parent node to point to the replacement
- */
- if (save_parent.if_right_node == save_inx_ptr) /* right son */
- save_parent.if_right_node = save_prev_ptr;
- else /* left son */
- save_parent.if_left_node = save_prev_ptr;
- if (iwrite_inx(db_control,&save_parent,save_inx_rec.if_parent))
- return(ierrno);
-
- /* update predecessor's parent */
- if (iread_inx(db_control,save_prev.if_parent))
- return(ierrno);
- if (save_prev.if_flags & LTHRD)
- irec->if_flags |= RTHRD;
- else
- irec->if_right_node = save_prev.if_left_node;
- if (iwrite_inx(db_control,irec,db_control->df_inx_ptr))
- return(ierrno);
-
- /* update predecessor's left son (if it exists) */
- if (!(save_prev.if_flags & LTHRD)) {
- if (iread_inx(db_control,save_prev.if_left_node))
- return(ierrno);
- irec->if_parent = save_prev.if_parent;
- if (iwrite_inx(db_control,irec,db_control->df_inx_ptr))
- return(ierrno);
- }
-
- /* now update the replacement node */
- save_prev.if_parent = save_inx_rec.if_parent;
- save_prev.if_right_node = save_inx_rec.if_right_node;
- if (save_inx_rec.if_left_node != save_prev_ptr) {
- save_prev.if_left_node = save_inx_rec.if_left_node;
- save_prev.if_flags = 0;
- }
- else {
- save_prev.if_flags &= ~(RTHRD | ETHRD);
- }
- if (iwrite_inx(db_control,&save_prev,save_prev_ptr))
- return(ierrno);
-
- /* get inorder successor and update its left thread pointer */
- if (iget_next(db_control,&save_inx_rec))
- return(ierrno);
- irec->if_left_node = save_prev_ptr;
- if (iwrite_inx(db_control,irec,db_control->df_inx_ptr))
- return(ierrno);
- }
- db_control->df_flags |= DF_DELETE; /* flag record as deleted */
- return(0);
- } /* idelete */