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 
00020 int heap_delete(HP_INFO *info, const unsigned char *record)
00021 {
00022   unsigned char *pos;
00023   HP_SHARE *share=info->getShare();
00024   HP_KEYDEF *keydef, *end, *p_lastinx;
00025 
00026   test_active(info);
00027 
00028   if (info->opt_flag & READ_CHECK_USED)
00029     return(errno);   /* Record changed */
00030   share->changed=1;
00031 
00032   if ( --(share->records) < share->blength >> 1) share->blength>>=1;
00033   pos=info->current_ptr;
00034 
00035   p_lastinx = share->keydef + info->lastinx;
00036   for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
00037        keydef++)
00038   {
00039     if (hp_delete_key(info, keydef, record, pos, keydef == p_lastinx))
00040       goto err;
00041   }
00042 
00043   info->update=HA_STATE_DELETED;
00044   hp_free_chunks(&share->recordspace, pos);
00045   info->current_hash_ptr=0;
00046 
00047   return(0);
00048 err:
00049   if (++(share->records) == share->blength)
00050     share->blength+= share->blength;
00051   return(errno);
00052 }
00053 
00054 
00055 /*
00056   Remove one key from hash-table
00057 
00058   SYNPOSIS
00059     hp_delete_key()
00060     info    Hash handler
00061     keyinfo   key definition of key that we want to delete
00062     record    row data to be deleted
00063     recpos    Pointer to heap record in memory
00064     flag    Is set if we want's to correct info->current_ptr
00065 
00066   RETURN
00067     0      Ok
00068     other  Error code
00069 */
00070 
00071 int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
00072       const unsigned char *record, unsigned char *recpos, int flag)
00073 {
00074   uint32_t blength,pos2,pos_hashnr,lastpos_hashnr;
00075   HASH_INFO *lastpos,*gpos,*pos,*pos3,*empty,*last_ptr;
00076   HP_SHARE *share=info->getShare();
00077 
00078   blength=share->blength;
00079   if (share->records+1 == blength)
00080     blength+= blength;
00081 
00082   /* find the very last HASH_INFO pointer in the index */
00083   /* note that records has already been decremented */
00084   lastpos=hp_find_hash(&keyinfo->block,share->records);
00085   last_ptr=0;
00086 
00087   /* Search after record with key */
00088   pos= hp_find_hash(&keyinfo->block,
00089         hp_mask(hp_rec_hashnr(keyinfo, record), blength,
00090           share->records + 1));
00091   gpos = pos3 = 0;
00092 
00093   while (pos->ptr_to_rec != recpos)
00094   {
00095     if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 0))
00096       last_ptr=pos;       /* Previous same key */
00097     gpos=pos;
00098     if (!(pos=pos->next_key))
00099     {
00100       return(errno= drizzled::HA_ERR_CRASHED);  /* This shouldn't happend */
00101     }
00102   }
00103 
00104   /* Remove link to record */
00105 
00106   if (flag)
00107   {
00108     /* Save for heap_rnext/heap_rprev */
00109     info->current_hash_ptr=last_ptr;
00110     info->current_ptr = last_ptr ? last_ptr->ptr_to_rec : 0;
00111   }
00112   empty=pos;
00113   if (gpos) {
00114     /* gpos says we have previous HASH_INFO, change previous to point to next, this way unlinking "empty" */
00115     gpos->next_key=pos->next_key;
00116   }
00117   else if (pos->next_key)
00118   {
00119     /* no previous gpos, this pos is the first in the list and it has pointer to "next" */
00120     /* move next HASH_INFO data to our pos, to free up space at the next position */
00121     /* remember next pos as "empty", nobody refers to "empty" at this point */
00122     empty=pos->next_key;
00123     pos->ptr_to_rec=empty->ptr_to_rec;
00124     pos->next_key=empty->next_key;
00125   }
00126   else
00127   {
00128     /* this was the only HASH_INFO at this position */
00129     keyinfo->hash_buckets--;
00130   }
00131 
00132   if (empty == lastpos)     /* deleted last hash key */
00133     return (0);
00134 
00135   /* Move the last key (lastpos) */
00136   lastpos_hashnr = hp_rec_hashnr(keyinfo, lastpos->ptr_to_rec);
00137   /* pos is where lastpos should be */
00138   pos=hp_find_hash(&keyinfo->block, hp_mask(lastpos_hashnr, share->blength,
00139               share->records));
00140   if (pos == empty)     /* Move to empty position. */
00141   {
00142     empty[0]=lastpos[0];
00143     return(0);
00144   }
00145   pos_hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
00146   /* pos3 is where the pos should be */
00147   pos3= hp_find_hash(&keyinfo->block,
00148          hp_mask(pos_hashnr, share->blength, share->records));
00149   if (pos != pos3)
00150   {         /* pos is on wrong posit */
00151     empty[0]=pos[0];      /* Save it here */
00152     pos[0]=lastpos[0];      /* This shold be here */
00153     hp_movelink(pos, pos3, empty);  /* Fix link to pos */
00154     return(0);
00155   }
00156   pos2= hp_mask(lastpos_hashnr, blength, share->records + 1);
00157   if (pos2 == hp_mask(pos_hashnr, blength, share->records + 1))
00158   {         /* Identical key-positions */
00159     if (pos2 != share->records)
00160     {
00161       empty[0]=lastpos[0];
00162       hp_movelink(lastpos, pos, empty);
00163       return(0);
00164     }
00165     pos3= pos;        /* Link pos->next after lastpos */
00166   }
00167   else
00168   {
00169     pos3= 0;        /* Different positions merge */
00170     keyinfo->hash_buckets--;
00171   }
00172 
00173   empty[0]=lastpos[0];
00174   hp_movelink(pos3, empty, pos->next_key);
00175   pos->next_key=empty;
00176   return(0);
00177 }