MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
hp_delete.c
1 /* Copyright (C) 2000-2002, 2004-2007 MySQL AB
2 
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.
6 
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.
11 
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 Street, Fifth Floor, Boston, MA 02110-1301, USA */
15 
16 /* remove current record in heap-database */
17 
18 #include "heapdef.h"
19 
20 int heap_delete(HP_INFO *info, const uchar *record)
21 {
22  uchar *pos;
23  HP_SHARE *share=info->s;
24  HP_KEYDEF *keydef, *end, *p_lastinx;
25  DBUG_ENTER("heap_delete");
26  DBUG_PRINT("enter",("info: 0x%lx record: 0x%lx", (long) info, (long) record));
27 
28  test_active(info);
29 
30  if (info->opt_flag & READ_CHECK_USED && hp_rectest(info,record))
31  DBUG_RETURN(my_errno); /* Record changed */
32  share->changed=1;
33 
34  if ( --(share->records) < share->blength >> 1) share->blength>>=1;
35  pos=info->current_ptr;
36 
37  p_lastinx = share->keydef + info->lastinx;
38  for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
39  keydef++)
40  {
41  if ((*keydef->delete_key)(info, keydef, record, pos, keydef == p_lastinx))
42  goto err;
43  }
44 
45  info->update=HA_STATE_DELETED;
46  *((uchar**) pos)=share->del_link;
47  share->del_link=pos;
48  pos[share->reclength]=0; /* Record deleted */
49  share->deleted++;
50  info->current_hash_ptr=0;
51 #if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)
52  DBUG_EXECUTE("check_heap",heap_check_heap(info, 0););
53 #endif
54 
55  DBUG_RETURN(0);
56 err:
57  if (++(share->records) == share->blength)
58  share->blength+= share->blength;
59  DBUG_RETURN(my_errno);
60 }
61 
62 
63 /*
64  Remove one key from rb-tree
65 */
66 
67 int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
68  const uchar *record, uchar *recpos, int flag)
69 {
70  heap_rb_param custom_arg;
71  uint old_allocated;
72  int res;
73 
74  if (flag)
75  info->last_pos= NULL; /* For heap_rnext/heap_rprev */
76 
77  custom_arg.keyseg= keyinfo->seg;
78  custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
79  custom_arg.search_flag= SEARCH_SAME;
80  old_allocated= keyinfo->rb_tree.allocated;
81  res= tree_delete(&keyinfo->rb_tree, info->recbuf, custom_arg.key_length,
82  &custom_arg);
83  info->s->index_length-= (old_allocated - keyinfo->rb_tree.allocated);
84  return res;
85 }
86 
87 
88 /*
89  Remove one key from hash-table
90 
91  SYNPOSIS
92  hp_delete_key()
93  info Hash handler
94  keyinfo key definition of key that we want to delete
95  record row data to be deleted
96  recpos Pointer to heap record in memory
97  flag Is set if we want's to correct info->current_ptr
98 
99  RETURN
100  0 Ok
101  other Error code
102 */
103 
104 int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
105  const uchar *record, uchar *recpos, int flag)
106 {
107  ulong blength, pos2, pos_hashnr, lastpos_hashnr, key_pos;
108  HASH_INFO *lastpos,*gpos,*pos,*pos3,*empty,*last_ptr;
109  HP_SHARE *share=info->s;
110  DBUG_ENTER("hp_delete_key");
111 
112  blength=share->blength;
113  if (share->records+1 == blength)
114  blength+= blength;
115  lastpos=hp_find_hash(&keyinfo->block,share->records);
116  last_ptr=0;
117 
118  /* Search after record with key */
119  key_pos= hp_mask(hp_rec_hashnr(keyinfo, record), blength, share->records + 1);
120  pos= hp_find_hash(&keyinfo->block, key_pos);
121 
122  gpos = pos3 = 0;
123 
124  while (pos->ptr_to_rec != recpos)
125  {
126  if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 0))
127  last_ptr=pos; /* Previous same key */
128  gpos=pos;
129  if (!(pos=pos->next_key))
130  {
131  DBUG_RETURN(my_errno=HA_ERR_CRASHED); /* This shouldn't happend */
132  }
133  }
134 
135  /* Remove link to record */
136 
137  if (flag)
138  {
139  /* Save for heap_rnext/heap_rprev */
140  info->current_hash_ptr=last_ptr;
141  info->current_ptr = last_ptr ? last_ptr->ptr_to_rec : 0;
142  DBUG_PRINT("info",("Corrected current_ptr to point at: 0x%lx",
143  (long) info->current_ptr));
144  }
145  empty=pos;
146  if (gpos)
147  gpos->next_key=pos->next_key; /* unlink current ptr */
148  else if (pos->next_key)
149  {
150  empty=pos->next_key;
151  pos->ptr_to_rec=empty->ptr_to_rec;
152  pos->next_key=empty->next_key;
153  }
154  else
155  keyinfo->hash_buckets--;
156 
157  if (empty == lastpos) /* deleted last hash key */
158  DBUG_RETURN (0);
159 
160  /* Move the last key (lastpos) */
161  lastpos_hashnr = hp_rec_hashnr(keyinfo, lastpos->ptr_to_rec);
162  /* pos is where lastpos should be */
163  pos=hp_find_hash(&keyinfo->block, hp_mask(lastpos_hashnr, share->blength,
164  share->records));
165  if (pos == empty) /* Move to empty position. */
166  {
167  empty[0]=lastpos[0];
168  DBUG_RETURN(0);
169  }
170  pos_hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
171  /* pos3 is where the pos should be */
172  pos3= hp_find_hash(&keyinfo->block,
173  hp_mask(pos_hashnr, share->blength, share->records));
174  if (pos != pos3)
175  { /* pos is on wrong posit */
176  empty[0]=pos[0]; /* Save it here */
177  pos[0]=lastpos[0]; /* This shold be here */
178  hp_movelink(pos, pos3, empty); /* Fix link to pos */
179  DBUG_RETURN(0);
180  }
181  pos2= hp_mask(lastpos_hashnr, blength, share->records + 1);
182  if (pos2 == hp_mask(pos_hashnr, blength, share->records + 1))
183  { /* Identical key-positions */
184  if (pos2 != share->records)
185  {
186  empty[0]=lastpos[0];
187  hp_movelink(lastpos, pos, empty);
188  DBUG_RETURN(0);
189  }
190  pos3= pos; /* Link pos->next after lastpos */
191  /*
192  One of elements from the bucket we're scanning is moved to the
193  beginning of the list. Reset search since this element may not have
194  been processed yet.
195  */
196  if (flag && pos2 == key_pos)
197  {
198  info->current_ptr= 0;
199  info->current_hash_ptr= 0;
200  }
201  }
202  else
203  {
204  pos3= 0; /* Different positions merge */
205  keyinfo->hash_buckets--;
206  }
207 
208  empty[0]=lastpos[0];
209  hp_movelink(pos3, empty, pos->next_key);
210  pos->next_key=empty;
211  DBUG_RETURN(0);
212 }