Drizzled Public API Documentation

hp_delete.cc
00001 /* Copyright (C) 2000-2002, 2004-2006 MySQL AB
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software
00014    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00015 
00016 /* remove current record in heap-database */
00017 
00018 #include "heap_priv.h"
00019 #include <drizzled/error_t.h>
00020 #include <drizzled/internal/my_sys.h>
00021 
00022 int heap_delete(HP_INFO *info, const unsigned char *record)
00023 {
00024   unsigned char *pos;
00025   HP_SHARE *share=info->getShare();
00026   HP_KEYDEF *keydef, *end, *p_lastinx;
00027 
00028   test_active(info);
00029 
00030   if (info->opt_flag & READ_CHECK_USED)
00031     return(errno);   /* Record changed */
00032   share->changed=1;
00033 
00034   if ( --(share->records) < share->blength >> 1) share->blength>>=1;
00035   pos=info->current_ptr;
00036 
00037   p_lastinx = share->keydef + info->lastinx;
00038   for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
00039        keydef++)
00040   {
00041     if (hp_delete_key(info, keydef, record, pos, keydef == p_lastinx))
00042       goto err;
00043   }
00044 
00045   info->update=HA_STATE_DELETED;
00046   hp_free_chunks(&share->recordspace, pos);
00047   info->current_hash_ptr=0;
00048 
00049   return(0);
00050 err:
00051   if (++(share->records) == share->blength)
00052     share->blength+= share->blength;
00053   return(errno);
00054 }
00055 
00056 
00057 /*
00058   Remove one key from hash-table
00059 
00060   SYNPOSIS
00061     hp_delete_key()
00062     info    Hash handler
00063     keyinfo   key definition of key that we want to delete
00064     record    row data to be deleted
00065     recpos    Pointer to heap record in memory
00066     flag    Is set if we want's to correct info->current_ptr
00067 
00068   RETURN
00069     0      Ok
00070     other  Error code
00071 */
00072 
00073 int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
00074       const unsigned char *record, unsigned char *recpos, int flag)
00075 {
00076   uint32_t blength,pos2,pos_hashnr,lastpos_hashnr;
00077   HASH_INFO *lastpos,*gpos,*pos,*pos3,*empty,*last_ptr;
00078   HP_SHARE *share=info->getShare();
00079 
00080   blength=share->blength;
00081   if (share->records+1 == blength)
00082     blength+= blength;
00083 
00084   /* find the very last HASH_INFO pointer in the index */
00085   /* note that records has already been decremented */
00086   lastpos=hp_find_hash(&keyinfo->block,share->records);
00087   last_ptr=0;
00088 
00089   /* Search after record with key */
00090   pos= hp_find_hash(&keyinfo->block,
00091         hp_mask(hp_rec_hashnr(keyinfo, record), blength,
00092           share->records + 1));
00093   gpos = pos3 = 0;
00094 
00095   while (pos->ptr_to_rec != recpos)
00096   {
00097     if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 0))
00098       last_ptr=pos;       /* Previous same key */
00099     gpos=pos;
00100     if (!(pos=pos->next_key))
00101     {
00102       return(errno= drizzled::HA_ERR_CRASHED);  /* This shouldn't happend */
00103     }
00104   }
00105 
00106   /* Remove link to record */
00107 
00108   if (flag)
00109   {
00110     /* Save for heap_rnext/heap_rprev */
00111     info->current_hash_ptr=last_ptr;
00112     info->current_ptr = last_ptr ? last_ptr->ptr_to_rec : 0;
00113   }
00114   empty=pos;
00115   if (gpos) {
00116     /* gpos says we have previous HASH_INFO, change previous to point to next, this way unlinking "empty" */
00117     gpos->next_key=pos->next_key;
00118   }
00119   else if (pos->next_key)
00120   {
00121     /* no previous gpos, this pos is the first in the list and it has pointer to "next" */
00122     /* move next HASH_INFO data to our pos, to free up space at the next position */
00123     /* remember next pos as "empty", nobody refers to "empty" at this point */
00124     empty=pos->next_key;
00125     pos->ptr_to_rec=empty->ptr_to_rec;
00126     pos->next_key=empty->next_key;
00127   }
00128   else
00129   {
00130     /* this was the only HASH_INFO at this position */
00131     keyinfo->hash_buckets--;
00132   }
00133 
00134   if (empty == lastpos)     /* deleted last hash key */
00135     return (0);
00136 
00137   /* Move the last key (lastpos) */
00138   lastpos_hashnr = hp_rec_hashnr(keyinfo, lastpos->ptr_to_rec);
00139   /* pos is where lastpos should be */
00140   pos=hp_find_hash(&keyinfo->block, hp_mask(lastpos_hashnr, share->blength,
00141               share->records));
00142   if (pos == empty)     /* Move to empty position. */
00143   {
00144     empty[0]=lastpos[0];
00145     return(0);
00146   }
00147   pos_hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
00148   /* pos3 is where the pos should be */
00149   pos3= hp_find_hash(&keyinfo->block,
00150          hp_mask(pos_hashnr, share->blength, share->records));
00151   if (pos != pos3)
00152   {         /* pos is on wrong posit */
00153     empty[0]=pos[0];      /* Save it here */
00154     pos[0]=lastpos[0];      /* This shold be here */
00155     hp_movelink(pos, pos3, empty);  /* Fix link to pos */
00156     return(0);
00157   }
00158   pos2= hp_mask(lastpos_hashnr, blength, share->records + 1);
00159   if (pos2 == hp_mask(pos_hashnr, blength, share->records + 1))
00160   {         /* Identical key-positions */
00161     if (pos2 != share->records)
00162     {
00163       empty[0]=lastpos[0];
00164       hp_movelink(lastpos, pos, empty);
00165       return(0);
00166     }
00167     pos3= pos;        /* Link pos->next after lastpos */
00168   }
00169   else
00170   {
00171     pos3= 0;        /* Different positions merge */
00172     keyinfo->hash_buckets--;
00173   }
00174 
00175   empty[0]=lastpos[0];
00176   hp_movelink(pos3, empty, pos->next_key);
00177   pos->next_key=empty;
00178   return(0);
00179 }