Drizzled Public API Documentation

hp_delete.cc
1 /* Copyright (C) 2000-2002, 2004-2006 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 St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 /* remove current record in heap-database */
17 
18 #include "heap_priv.h"
19 #include <drizzled/error_t.h>
20 #include <drizzled/internal/my_sys.h>
21 
22 int heap_delete(HP_INFO *info, const unsigned char *record)
23 {
24  unsigned char *pos;
25  HP_SHARE *share=info->getShare();
26  HP_KEYDEF *keydef, *end, *p_lastinx;
27 
28  test_active(info);
29 
30  if (info->opt_flag & READ_CHECK_USED)
31  return(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 (hp_delete_key(info, keydef, record, pos, keydef == p_lastinx))
42  goto err;
43  }
44 
45  info->update=HA_STATE_DELETED;
46  hp_free_chunks(&share->recordspace, pos);
47  info->current_hash_ptr=0;
48 
49  return(0);
50 err:
51  if (++(share->records) == share->blength)
52  share->blength+= share->blength;
53  return(errno);
54 }
55 
56 
57 /*
58  Remove one key from hash-table
59 
60  SYNPOSIS
61  hp_delete_key()
62  info Hash handler
63  keyinfo key definition of key that we want to delete
64  record row data to be deleted
65  recpos Pointer to heap record in memory
66  flag Is set if we want's to correct info->current_ptr
67 
68  RETURN
69  0 Ok
70  other Error code
71 */
72 
73 int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
74  const unsigned char *record, unsigned char *recpos, int flag)
75 {
76  uint32_t blength,pos2,pos_hashnr,lastpos_hashnr;
77  HASH_INFO *lastpos,*gpos,*pos,*pos3,*empty,*last_ptr;
78  HP_SHARE *share=info->getShare();
79 
80  blength=share->blength;
81  if (share->records+1 == blength)
82  blength+= blength;
83 
84  /* find the very last HASH_INFO pointer in the index */
85  /* note that records has already been decremented */
86  lastpos=hp_find_hash(&keyinfo->block,share->records);
87  last_ptr=0;
88 
89  /* Search after record with key */
90  pos= hp_find_hash(&keyinfo->block,
91  hp_mask(hp_rec_hashnr(keyinfo, record), blength,
92  share->records + 1));
93  gpos = pos3 = 0;
94 
95  while (pos->ptr_to_rec != recpos)
96  {
97  if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 0))
98  last_ptr=pos; /* Previous same key */
99  gpos=pos;
100  if (!(pos=pos->next_key))
101  {
102  return(errno= drizzled::HA_ERR_CRASHED); /* This shouldn't happend */
103  }
104  }
105 
106  /* Remove link to record */
107 
108  if (flag)
109  {
110  /* Save for heap_rnext/heap_rprev */
111  info->current_hash_ptr=last_ptr;
112  info->current_ptr = last_ptr ? last_ptr->ptr_to_rec : 0;
113  }
114  empty=pos;
115  if (gpos) {
116  /* gpos says we have previous HASH_INFO, change previous to point to next, this way unlinking "empty" */
117  gpos->next_key=pos->next_key;
118  }
119  else if (pos->next_key)
120  {
121  /* no previous gpos, this pos is the first in the list and it has pointer to "next" */
122  /* move next HASH_INFO data to our pos, to free up space at the next position */
123  /* remember next pos as "empty", nobody refers to "empty" at this point */
124  empty=pos->next_key;
125  pos->ptr_to_rec=empty->ptr_to_rec;
126  pos->next_key=empty->next_key;
127  }
128  else
129  {
130  /* this was the only HASH_INFO at this position */
131  keyinfo->hash_buckets--;
132  }
133 
134  if (empty == lastpos) /* deleted last hash key */
135  return (0);
136 
137  /* Move the last key (lastpos) */
138  lastpos_hashnr = hp_rec_hashnr(keyinfo, lastpos->ptr_to_rec);
139  /* pos is where lastpos should be */
140  pos=hp_find_hash(&keyinfo->block, hp_mask(lastpos_hashnr, share->blength,
141  share->records));
142  if (pos == empty) /* Move to empty position. */
143  {
144  empty[0]=lastpos[0];
145  return(0);
146  }
147  pos_hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
148  /* pos3 is where the pos should be */
149  pos3= hp_find_hash(&keyinfo->block,
150  hp_mask(pos_hashnr, share->blength, share->records));
151  if (pos != pos3)
152  { /* pos is on wrong posit */
153  empty[0]=pos[0]; /* Save it here */
154  pos[0]=lastpos[0]; /* This shold be here */
155  hp_movelink(pos, pos3, empty); /* Fix link to pos */
156  return(0);
157  }
158  pos2= hp_mask(lastpos_hashnr, blength, share->records + 1);
159  if (pos2 == hp_mask(pos_hashnr, blength, share->records + 1))
160  { /* Identical key-positions */
161  if (pos2 != share->records)
162  {
163  empty[0]=lastpos[0];
164  hp_movelink(lastpos, pos, empty);
165  return(0);
166  }
167  pos3= pos; /* Link pos->next after lastpos */
168  }
169  else
170  {
171  pos3= 0; /* Different positions merge */
172  keyinfo->hash_buckets--;
173  }
174 
175  empty[0]=lastpos[0];
176  hp_movelink(pos3, empty, pos->next_key);
177  pos->next_key=empty;
178  return(0);
179 }