1
/* Copyright (C) 2000-2002, 2004-200 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16
/* remove current record in heap-database */
18
#include "heap_priv.h"
20
int heap_delete(HP_INFO *info, const unsigned char *record)
23
HP_SHARE *share=info->getShare();
24
HP_KEYDEF *keydef, *end, *p_lastinx;
28
if (info->opt_flag & READ_CHECK_USED)
29
return(errno); /* Record changed */
32
if ( --(share->records) < share->blength >> 1) share->blength>>=1;
33
pos=info->current_ptr;
35
p_lastinx = share->keydef + info->lastinx;
36
for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
39
if (hp_delete_key(info, keydef, record, pos, keydef == p_lastinx))
43
info->update=HA_STATE_DELETED;
44
hp_free_chunks(&share->recordspace, pos);
45
info->current_hash_ptr=0;
49
if (++(share->records) == share->blength)
50
share->blength+= share->blength;
56
Remove one key from hash-table
61
keyinfo key definition of key that we want to delete
62
record row data to be deleted
63
recpos Pointer to heap record in memory
64
flag Is set if we want's to correct info->current_ptr
71
int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
72
const unsigned char *record, unsigned char *recpos, int flag)
74
uint32_t blength,pos2,pos_hashnr,lastpos_hashnr;
75
HASH_INFO *lastpos,*gpos,*pos,*pos3,*empty,*last_ptr;
76
HP_SHARE *share=info->getShare();
78
blength=share->blength;
79
if (share->records+1 == blength)
82
/* find the very last HASH_INFO pointer in the index */
83
/* note that records has already been decremented */
84
lastpos=hp_find_hash(&keyinfo->block,share->records);
87
/* Search after record with key */
88
pos= hp_find_hash(&keyinfo->block,
89
hp_mask(hp_rec_hashnr(keyinfo, record), blength,
93
while (pos->ptr_to_rec != recpos)
95
if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 0))
96
last_ptr=pos; /* Previous same key */
98
if (!(pos=pos->next_key))
100
return(errno=HA_ERR_CRASHED); /* This shouldn't happend */
104
/* Remove link to record */
108
/* Save for heap_rnext/heap_rprev */
109
info->current_hash_ptr=last_ptr;
110
info->current_ptr = last_ptr ? last_ptr->ptr_to_rec : 0;
114
/* gpos says we have previous HASH_INFO, change previous to point to next, this way unlinking "empty" */
115
gpos->next_key=pos->next_key;
117
else if (pos->next_key)
119
/* no previous gpos, this pos is the first in the list and it has pointer to "next" */
120
/* move next HASH_INFO data to our pos, to free up space at the next position */
121
/* remember next pos as "empty", nobody refers to "empty" at this point */
123
pos->ptr_to_rec=empty->ptr_to_rec;
124
pos->next_key=empty->next_key;
128
/* this was the only HASH_INFO at this position */
129
keyinfo->hash_buckets--;
132
if (empty == lastpos) /* deleted last hash key */
135
/* Move the last key (lastpos) */
136
lastpos_hashnr = hp_rec_hashnr(keyinfo, lastpos->ptr_to_rec);
137
/* pos is where lastpos should be */
138
pos=hp_find_hash(&keyinfo->block, hp_mask(lastpos_hashnr, share->blength,
140
if (pos == empty) /* Move to empty position. */
145
pos_hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
146
/* pos3 is where the pos should be */
147
pos3= hp_find_hash(&keyinfo->block,
148
hp_mask(pos_hashnr, share->blength, share->records));
150
{ /* pos is on wrong posit */
151
empty[0]=pos[0]; /* Save it here */
152
pos[0]=lastpos[0]; /* This shold be here */
153
hp_movelink(pos, pos3, empty); /* Fix link to pos */
156
pos2= hp_mask(lastpos_hashnr, blength, share->records + 1);
157
if (pos2 == hp_mask(pos_hashnr, blength, share->records + 1))
158
{ /* Identical key-positions */
159
if (pos2 != share->records)
162
hp_movelink(lastpos, pos, empty);
165
pos3= pos; /* Link pos->next after lastpos */
169
pos3= 0; /* Different positions merge */
170
keyinfo->hash_buckets--;
174
hp_movelink(pos3, empty, pos->next_key);