~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/memory/hp_delete.cc

  • Committer: Brian Aker
  • Date: 2010-09-22 22:29:55 UTC
  • mto: (1787.3.1 drizzle)
  • mto: This revision was merged to the branch mainline in revision 1789.
  • Revision ID: brian@tangent.org-20100922222955-cg1bddv4b72jwe31
Fix enum at being an intefer (which is what PG did, and it saves on
alignment issues).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2002, 2004-200 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
 
 
20
 
int heap_delete(HP_INFO *info, const unsigned char *record)
21
 
{
22
 
  unsigned char *pos;
23
 
  HP_SHARE *share=info->getShare();
24
 
  HP_KEYDEF *keydef, *end, *p_lastinx;
25
 
 
26
 
  test_active(info);
27
 
 
28
 
  if (info->opt_flag & READ_CHECK_USED)
29
 
    return(errno);                      /* Record changed */
30
 
  share->changed=1;
31
 
 
32
 
  if ( --(share->records) < share->blength >> 1) share->blength>>=1;
33
 
  pos=info->current_ptr;
34
 
 
35
 
  p_lastinx = share->keydef + info->lastinx;
36
 
  for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
37
 
       keydef++)
38
 
  {
39
 
    if (hp_delete_key(info, keydef, record, pos, keydef == p_lastinx))
40
 
      goto err;
41
 
  }
42
 
 
43
 
  info->update=HA_STATE_DELETED;
44
 
  hp_free_chunks(&share->recordspace, pos);
45
 
  info->current_hash_ptr=0;
46
 
 
47
 
  return(0);
48
 
err:
49
 
  if (++(share->records) == share->blength)
50
 
    share->blength+= share->blength;
51
 
  return(errno);
52
 
}
53
 
 
54
 
 
55
 
/*
56
 
  Remove one key from hash-table
57
 
 
58
 
  SYNPOSIS
59
 
    hp_delete_key()
60
 
    info                Hash handler
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
65
 
 
66
 
  RETURN
67
 
    0      Ok
68
 
    other  Error code
69
 
*/
70
 
 
71
 
int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
72
 
                  const unsigned char *record, unsigned char *recpos, int flag)
73
 
{
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();
77
 
 
78
 
  blength=share->blength;
79
 
  if (share->records+1 == blength)
80
 
    blength+= blength;
81
 
 
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);
85
 
  last_ptr=0;
86
 
 
87
 
  /* Search after record with key */
88
 
  pos= hp_find_hash(&keyinfo->block,
89
 
                    hp_mask(hp_rec_hashnr(keyinfo, record), blength,
90
 
                            share->records + 1));
91
 
  gpos = pos3 = 0;
92
 
 
93
 
  while (pos->ptr_to_rec != recpos)
94
 
  {
95
 
    if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 0))
96
 
      last_ptr=pos;                             /* Previous same key */
97
 
    gpos=pos;
98
 
    if (!(pos=pos->next_key))
99
 
    {
100
 
      return(errno=HA_ERR_CRASHED);     /* This shouldn't happend */
101
 
    }
102
 
  }
103
 
 
104
 
  /* Remove link to record */
105
 
 
106
 
  if (flag)
107
 
  {
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;
111
 
  }
112
 
  empty=pos;
113
 
  if (gpos) {
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;
116
 
  }
117
 
  else if (pos->next_key)
118
 
  {
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 */
122
 
    empty=pos->next_key;
123
 
    pos->ptr_to_rec=empty->ptr_to_rec;
124
 
    pos->next_key=empty->next_key;
125
 
  }
126
 
  else
127
 
  {
128
 
    /* this was the only HASH_INFO at this position */
129
 
    keyinfo->hash_buckets--;
130
 
  }
131
 
 
132
 
  if (empty == lastpos)                 /* deleted last hash key */
133
 
    return (0);
134
 
 
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,
139
 
                                            share->records));
140
 
  if (pos == empty)                     /* Move to empty position. */
141
 
  {
142
 
    empty[0]=lastpos[0];
143
 
    return(0);
144
 
  }
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));
149
 
  if (pos != pos3)
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 */
154
 
    return(0);
155
 
  }
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)
160
 
    {
161
 
      empty[0]=lastpos[0];
162
 
      hp_movelink(lastpos, pos, empty);
163
 
      return(0);
164
 
    }
165
 
    pos3= pos;                          /* Link pos->next after lastpos */
166
 
  }
167
 
  else
168
 
  {
169
 
    pos3= 0;                            /* Different positions merge */
170
 
    keyinfo->hash_buckets--;
171
 
  }
172
 
 
173
 
  empty[0]=lastpos[0];
174
 
  hp_movelink(pos3, empty, pos->next_key);
175
 
  pos->next_key=empty;
176
 
  return(0);
177
 
}