~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_delete.c

  • Committer: Monty Taylor
  • Date: 2008-10-16 06:32:59 UTC
  • mfrom: (518 drizzle)
  • mto: (511.1.5 codestyle)
  • mto: This revision was merged to the branch mainline in revision 521.
  • Revision ID: monty@inaugust.com-20081016063259-fwbqogq7lnezct0l
Merged with trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
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 */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
/* Remove a row from a MyISAM table */
17
17
 
18
 
#include "myisam_priv.h"
19
 
#include <drizzled/internal/m_string.h>
 
18
#include "myisamdef.h"
20
19
#include <drizzled/util/test.h>
21
20
 
22
 
using namespace drizzled;
23
 
 
24
21
static int d_search(MI_INFO *info,MI_KEYDEF *keyinfo,uint32_t comp_flag,
25
 
                    unsigned char *key,uint32_t key_length,internal::my_off_t page,unsigned char *anc_buff);
 
22
                    unsigned char *key,uint32_t key_length,my_off_t page,unsigned char *anc_buff);
26
23
static int del(MI_INFO *info,MI_KEYDEF *keyinfo,unsigned char *key,unsigned char *anc_buff,
27
 
               internal::my_off_t leaf_page,unsigned char *leaf_buff,unsigned char *keypos,
28
 
               internal::my_off_t next_block,unsigned char *ret_key);
 
24
               my_off_t leaf_page,unsigned char *leaf_buff,unsigned char *keypos,
 
25
               my_off_t next_block,unsigned char *ret_key);
29
26
static int underflow(MI_INFO *info,MI_KEYDEF *keyinfo,unsigned char *anc_buff,
30
 
                     internal::my_off_t leaf_page,unsigned char *leaf_buff,unsigned char *keypos);
 
27
                     my_off_t leaf_page,unsigned char *leaf_buff,unsigned char *keypos);
31
28
static uint32_t remove_key(MI_KEYDEF *keyinfo,uint32_t nod_flag,unsigned char *keypos,
32
29
                       unsigned char *lastkey,unsigned char *page_end,
33
 
                       internal::my_off_t *next_block);
 
30
                       my_off_t *next_block);
34
31
static int _mi_ck_real_delete(register MI_INFO *info,MI_KEYDEF *keyinfo,
35
 
                              unsigned char *key, uint32_t key_length, internal::my_off_t *root);
 
32
                              unsigned char *key, uint32_t key_length, my_off_t *root);
36
33
 
37
34
 
38
35
int mi_delete(MI_INFO *info,const unsigned char *record)
47
44
        /* Test if record is in datafile */
48
45
  if (!(info->update & HA_STATE_AKTIV))
49
46
  {
50
 
    return(errno=HA_ERR_KEY_NOT_FOUND); /* No database read */
 
47
    return(my_errno=HA_ERR_KEY_NOT_FOUND);      /* No database read */
51
48
  }
52
49
  if (share->options & HA_OPTION_READ_ONLY_DATA)
53
50
  {
54
 
    return(errno=EACCES);
 
51
    return(my_errno=EACCES);
55
52
  }
56
53
  if (_mi_readinfo(info,F_WRLCK,1))
57
 
    return(errno);
 
54
    return(my_errno);
58
55
  if (info->s->calc_checksum)
59
56
    info->checksum=(*info->s->calc_checksum)(info,record);
60
57
  if ((*share->compare_record)(info,record))
90
87
 
91
88
  mi_sizestore(lastpos,info->lastpos);
92
89
  _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
 
90
  if (info->invalidator != 0)
 
91
  {
 
92
    (*info->invalidator)(info->filename);
 
93
    info->invalidator=0;
 
94
  }
93
95
  return(0);
94
96
 
95
97
err:
96
 
  save_errno=errno;
 
98
  save_errno=my_errno;
97
99
  mi_sizestore(lastpos,info->lastpos);
98
100
  if (save_errno != HA_ERR_RECORD_CHANGED)
99
101
  {
102
104
  }
103
105
  _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
104
106
  info->update|=HA_STATE_WRITTEN;       /* Buffer changed */
105
 
  errno=save_errno;
 
107
  my_errno=save_errno;
106
108
  if (save_errno == HA_ERR_KEY_NOT_FOUND)
107
109
  {
108
110
    mi_print_error(info->s, HA_ERR_CRASHED);
109
 
    errno=HA_ERR_CRASHED;
 
111
    my_errno=HA_ERR_CRASHED;
110
112
  }
111
113
 
112
 
  return(errno);
 
114
  return(my_errno);
113
115
} /* mi_delete */
114
116
 
115
117
 
124
126
 
125
127
 
126
128
static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo,
127
 
                              unsigned char *key, uint32_t key_length, internal::my_off_t *root)
 
129
                              unsigned char *key, uint32_t key_length, my_off_t *root)
128
130
{
129
131
  int error;
130
132
  uint32_t nod_flag;
131
 
  internal::my_off_t old_root;
 
133
  my_off_t old_root;
132
134
  unsigned char *root_buff;
133
135
 
134
136
  if ((old_root=*root) == HA_OFFSET_ERROR)
135
137
  {
136
138
    mi_print_error(info->s, HA_ERR_CRASHED);
137
 
    return(errno=HA_ERR_CRASHED);
 
139
    return(my_errno=HA_ERR_CRASHED);
138
140
  }
139
 
  if (!(root_buff= (unsigned char*) malloc(keyinfo->block_length+
 
141
  if (!(root_buff= (unsigned char*) my_alloca((uint) keyinfo->block_length+
140
142
                                      MI_MAX_KEY_BUFF*2)))
141
143
  {
142
 
    return(errno=ENOMEM);
 
144
    return(my_errno=ENOMEM);
143
145
  }
144
146
  if (!_mi_fetch_keypage(info,keyinfo,old_root,DFLT_INIT_HITS,root_buff,0))
145
147
  {
170
172
    }
171
173
  }
172
174
err:
173
 
  free(root_buff);
 
175
  my_afree((unsigned char*) root_buff);
174
176
  return(error);
175
177
} /* _mi_ck_real_delete */
176
178
 
185
187
 
186
188
static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
187
189
                    uint32_t comp_flag, unsigned char *key, uint32_t key_length,
188
 
                    internal::my_off_t page, unsigned char *anc_buff)
 
190
                    my_off_t page, unsigned char *anc_buff)
189
191
{
190
192
  int flag,ret_value,save_flag;
191
193
  uint32_t length,nod_flag,search_key_length;
192
194
  bool last_key;
193
195
  unsigned char *leaf_buff,*keypos;
194
 
  internal::my_off_t leaf_page= 0, next_block;
 
196
  my_off_t leaf_page= 0, next_block;
195
197
  unsigned char lastkey[MI_MAX_KEY_BUFF];
196
198
 
197
199
  search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY;
207
209
  if (nod_flag)
208
210
  {
209
211
    leaf_page=_mi_kpos(nod_flag,keypos);
210
 
    if (!(leaf_buff= (unsigned char*) malloc(keyinfo->block_length+
 
212
    if (!(leaf_buff= (unsigned char*) my_alloca((uint) keyinfo->block_length+
211
213
                                        MI_MAX_KEY_BUFF*2)))
212
214
    {
213
 
      errno=ENOMEM;
 
215
      my_errno=ENOMEM;
214
216
      return(-1);
215
217
    }
216
218
    if (!_mi_fetch_keypage(info,keyinfo,leaf_page,DFLT_INIT_HITS,leaf_buff,0))
222
224
    if (!nod_flag)
223
225
    {
224
226
      mi_print_error(info->s, HA_ERR_CRASHED);
225
 
      errno=HA_ERR_CRASHED;             /* This should newer happend */
 
227
      my_errno=HA_ERR_CRASHED;          /* This should newer happend */
226
228
      goto err;
227
229
    }
228
230
    save_flag=0;
266
268
        goto err;
267
269
      }
268
270
      ret_value=_mi_insert(info,keyinfo,key,anc_buff,keypos,lastkey,
269
 
                           (unsigned char*) 0,(unsigned char*) 0,(internal::my_off_t) 0,(bool) 0);
 
271
                           (unsigned char*) 0,(unsigned char*) 0,(my_off_t) 0,(bool) 0);
270
272
    }
271
273
  }
272
274
  if (ret_value == 0 && mi_getint(anc_buff) > keyinfo->block_length)
276
278
  }
277
279
  if (save_flag && ret_value != 1)
278
280
    ret_value|=_mi_write_keypage(info,keyinfo,page,DFLT_INIT_HITS,anc_buff);
279
 
  free(leaf_buff);
 
281
  my_afree((unsigned char*) leaf_buff);
280
282
  return(ret_value);
281
283
 
282
284
err:
283
 
  free(leaf_buff);
 
285
  my_afree((unsigned char*) leaf_buff);
284
286
  return (-1);
285
287
} /* d_search */
286
288
 
288
290
        /* Remove a key that has a page-reference */
289
291
 
290
292
static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, unsigned char *key,
291
 
               unsigned char *anc_buff, internal::my_off_t leaf_page, unsigned char *leaf_buff,
 
293
               unsigned char *anc_buff, my_off_t leaf_page, unsigned char *leaf_buff,
292
294
               unsigned char *keypos,           /* Pos to where deleted key was */
293
 
               internal::my_off_t next_block,
 
295
               my_off_t next_block,
294
296
               unsigned char *ret_key)          /* key before keypos in anc_buff */
295
297
{
296
298
  int ret_value,length;
297
299
  uint32_t a_length,nod_flag,tmp;
298
 
  internal::my_off_t next_page;
 
300
  my_off_t next_page;
299
301
  unsigned char keybuff[MI_MAX_KEY_BUFF],*endpos,*next_buff,*key_start, *prev_key;
300
302
  MYISAM_SHARE *share=info->s;
301
303
  MI_KEY_PARAM s_temp;
308
310
  if ((nod_flag=mi_test_if_nod(leaf_buff)))
309
311
  {
310
312
    next_page= _mi_kpos(nod_flag,endpos);
311
 
    if (!(next_buff= (unsigned char*) malloc(keyinfo->block_length+
 
313
    if (!(next_buff= (unsigned char*) my_alloca((uint) keyinfo->block_length+
312
314
                                        MI_MAX_KEY_BUFF*2)))
313
315
      return(-1);
314
316
    if (!_mi_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,next_buff,0))
334
336
                                &tmp))
335
337
            goto err;
336
338
          ret_value=_mi_insert(info,keyinfo,key,leaf_buff,endpos,keybuff,
337
 
                               (unsigned char*) 0,(unsigned char*) 0,(internal::my_off_t) 0,0);
 
339
                               (unsigned char*) 0,(unsigned char*) 0,(my_off_t) 0,0);
338
340
        }
339
341
      }
340
342
      if (_mi_write_keypage(info,keyinfo,leaf_page,DFLT_INIT_HITS,leaf_buff))
341
343
        goto err;
342
344
    }
343
 
    free(next_buff);
 
345
    my_afree((unsigned char*) next_buff);
344
346
    return(ret_value);
345
347
  }
346
348
 
364
366
                              prev_key, prev_key,
365
367
                              keybuff,&s_temp);
366
368
  if (length > 0)
367
 
    internal::bmove_upp((unsigned char*) endpos+length,(unsigned char*) endpos,(uint) (endpos-keypos));
 
369
    bmove_upp((unsigned char*) endpos+length,(unsigned char*) endpos,(uint) (endpos-keypos));
368
370
  else
369
 
    memmove(keypos,keypos-length, (int) (endpos-keypos)+length);
 
371
    memcpy(keypos,keypos-length, (int) (endpos-keypos)+length);
370
372
  (*keyinfo->store_key)(keyinfo,keypos,&s_temp);
371
373
  /* Save pointer to next leaf */
372
374
  if (!(*keyinfo->get_key)(keyinfo,share->base.key_reflength,&keypos,ret_key))
386
388
 
387
389
static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
388
390
                     unsigned char *anc_buff,
389
 
                     internal::my_off_t leaf_page,/* Ancestor page and underflow page */
 
391
                     my_off_t leaf_page,/* Ancestor page and underflow page */
390
392
                     unsigned char *leaf_buff,
391
393
                     unsigned char *keypos)     /* Position to pos after key */
392
394
{
393
395
  int t_length;
394
396
  uint32_t length,anc_length,buff_length,leaf_length,p_length,s_length,nod_flag,
395
397
       key_reflength,key_length;
396
 
  internal::my_off_t next_page;
 
398
  my_off_t next_page;
397
399
  unsigned char anc_key[MI_MAX_KEY_BUFF],leaf_key[MI_MAX_KEY_BUFF],
398
400
        *buff,*endpos,*next_keypos,*anc_pos,*half_pos,*temp_pos,*prev_key,
399
401
        *after_key;
434
436
    buff_length=mi_getint(buff);
435
437
 
436
438
    /* find keys to make a big key-page */
437
 
    memmove(next_keypos - key_reflength, buff + 2, key_reflength);
 
439
    memcpy(next_keypos - key_reflength, buff + 2, key_reflength);
438
440
    if (!_mi_get_last_key(info,keyinfo,anc_buff,anc_key,next_keypos,&length)
439
441
        || !_mi_get_last_key(info,keyinfo,leaf_buff,leaf_key,
440
442
                             leaf_buff+leaf_length,&length))
448
450
    length=buff_length-p_length;
449
451
    endpos=buff+length+leaf_length+t_length;
450
452
    /* buff will always be larger than before !*/
451
 
    internal::bmove_upp((unsigned char*) endpos, (unsigned char*) buff+buff_length,length);
 
453
    bmove_upp((unsigned char*) endpos, (unsigned char*) buff+buff_length,length);
452
454
    memcpy(buff, leaf_buff, leaf_length);
453
455
    (*keyinfo->store_key)(keyinfo,buff+leaf_length,&s_temp);
454
456
    buff_length=(uint) (endpos-buff);
457
459
    /* remove key from anc_buff */
458
460
 
459
461
    if (!(s_length=remove_key(keyinfo,key_reflength,keypos,anc_key,
460
 
                              anc_buff+anc_length,(internal::my_off_t *) 0)))
 
462
                              anc_buff+anc_length,(my_off_t *) 0)))
461
463
      goto err;
462
464
 
463
465
    anc_length-=s_length;
493
495
                                    prev_key, prev_key,
494
496
                                    leaf_key, &s_temp);
495
497
      if (t_length >= 0)
496
 
        internal::bmove_upp((unsigned char*) endpos+t_length,(unsigned char*) endpos,
 
498
        bmove_upp((unsigned char*) endpos+t_length,(unsigned char*) endpos,
497
499
                  (uint) (endpos-keypos));
498
500
      else
499
 
        memmove(keypos,keypos-t_length,(uint) (endpos-keypos)+t_length);
 
501
        memcpy(keypos,keypos-t_length,(uint) (endpos-keypos)+t_length);
500
502
      (*keyinfo->store_key)(keyinfo,keypos,&s_temp);
501
503
      mi_putint(anc_buff,(anc_length+=t_length),key_reflength);
502
504
 
503
505
        /* Store key first in new page */
504
506
      if (nod_flag)
505
 
        memmove(buff + 2, half_pos - nod_flag, nod_flag);
 
507
        memcpy(buff + 2, half_pos - nod_flag, nod_flag);
506
508
      if (!(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key))
507
509
        goto err;
508
510
      t_length=(int) (*keyinfo->pack_key)(keyinfo, nod_flag, (unsigned char*) 0,
510
512
                                          leaf_key, &s_temp);
511
513
      /* t_length will always be > 0 for a new page !*/
512
514
      length=(uint) ((buff+mi_getint(buff))-half_pos);
513
 
      memmove(buff + p_length + t_length, half_pos, length);
 
515
      memcpy(buff + p_length + t_length, half_pos, length);
514
516
      (*keyinfo->store_key)(keyinfo,buff+p_length,&s_temp);
515
517
      mi_putint(buff,length+t_length+p_length,nod_flag);
516
518
 
533
535
  endpos=buff+buff_length;
534
536
 
535
537
  /* find keys to make a big key-page */
536
 
  memmove(next_keypos - key_reflength, leaf_buff+2, key_reflength);
 
538
  memcpy(next_keypos - key_reflength, leaf_buff+2, key_reflength);
537
539
  next_keypos=keypos;
538
540
  if (!(*keyinfo->get_key)(keyinfo,key_reflength,&next_keypos,
539
541
                           anc_key))
549
551
                                prev_key, prev_key,
550
552
                                anc_key, &s_temp);
551
553
  if (t_length >= 0)
552
 
    memmove(endpos+t_length,leaf_buff+p_length, leaf_length-p_length);
 
554
    memcpy(endpos+t_length,leaf_buff+p_length, leaf_length-p_length);
553
555
  else                                          /* We gained space */
554
 
    memmove(endpos, leaf_buff+((int) p_length-t_length),
555
 
            leaf_length - p_length + t_length);
 
556
    memcpy(endpos, leaf_buff+((int) p_length-t_length),
 
557
           leaf_length - p_length + t_length);
556
558
 
557
559
  (*keyinfo->store_key)(keyinfo,endpos,&s_temp);
558
560
  buff_length=buff_length+leaf_length-p_length+t_length;
560
562
 
561
563
  /* remove key from anc_buff */
562
564
  if (!(s_length= remove_key(keyinfo,key_reflength,keypos,anc_key,
563
 
                             anc_buff+anc_length,(internal::my_off_t *) 0)))
 
565
                             anc_buff+anc_length,(my_off_t *) 0)))
564
566
    goto err;
565
567
 
566
568
  anc_length-=s_length;
592
594
                                  anc_pos, anc_pos,
593
595
                                  leaf_key,&s_temp);
594
596
    if (t_length > 0)
595
 
      internal::bmove_upp((unsigned char*) temp_pos+t_length,(unsigned char*) temp_pos,
 
597
      bmove_upp((unsigned char*) temp_pos+t_length,(unsigned char*) temp_pos,
596
598
                (uint) (temp_pos-keypos));
597
599
    else
598
 
      memmove(keypos,keypos-t_length,(uint) (temp_pos-keypos)+t_length);
 
600
      memcpy(keypos,keypos-t_length,(uint) (temp_pos-keypos)+t_length);
599
601
    (*keyinfo->store_key)(keyinfo,keypos,&s_temp);
600
602
    mi_putint(anc_buff,(anc_length+=t_length),key_reflength);
601
603
 
602
604
    /* Store first key on new page */
603
605
    if (nod_flag)
604
 
      memmove(leaf_buff+2, half_pos - nod_flag, nod_flag);
 
606
      memcpy(leaf_buff+2, half_pos - nod_flag, nod_flag);
605
607
    if (!(length=(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key)))
606
608
      goto err;
607
609
    t_length=(*keyinfo->pack_key)(keyinfo,nod_flag, (unsigned char*) 0,
608
610
                                  (unsigned char*) 0, (unsigned char*) 0, leaf_key, &s_temp);
609
611
    length=(uint) ((buff+buff_length)-half_pos);
610
 
    memmove(leaf_buff + p_length + t_length, half_pos, length);
 
612
    memcpy(leaf_buff + p_length + t_length, half_pos, length);
611
613
    (*keyinfo->store_key)(keyinfo,leaf_buff+p_length,&s_temp);
612
614
    mi_putint(leaf_buff,length+t_length+p_length,nod_flag);
613
615
    if (_mi_write_keypage(info,keyinfo,leaf_page,DFLT_INIT_HITS,leaf_buff))
634
636
                       unsigned char *keypos,   /* Where key starts */
635
637
                       unsigned char *lastkey,  /* key to be removed */
636
638
                       unsigned char *page_end, /* End of page */
637
 
                       internal::my_off_t *next_block)  /* ptr to next block */
 
639
                       my_off_t *next_block)    /* ptr to next block */
638
640
{
639
641
  int s_length;
640
642
  unsigned char *start;
668
670
        if (next_length > prev_length)
669
671
        {
670
672
          /* We have to copy data from the current key to the next key */
671
 
          internal::bmove_upp(keypos, (lastkey+next_length),
 
673
          bmove_upp(keypos, (lastkey+next_length),
672
674
                    (next_length-prev_length));
673
675
          keypos-=(next_length-prev_length)+prev_pack_length;
674
676
          store_key_length(keypos,prev_length);
715
717
          if (next_length >= prev_length)
716
718
          {             /* Key after is based on deleted key */
717
719
            uint32_t pack_length,tmp;
718
 
            internal::bmove_upp(keypos, (lastkey+next_length),
719
 
                                tmp=(next_length-prev_length));
 
720
            bmove_upp(keypos, (lastkey+next_length),
 
721
                      tmp=(next_length-prev_length));
720
722
            rest_length+=tmp;
721
723
            pack_length= prev_length ? get_pack_length(rest_length): 0;
722
724
            keypos-=tmp+pack_length+prev_pack_length;
749
751
  }
750
752
end:
751
753
  assert(page_end-start >= s_length);
752
 
  memmove(start, start + s_length, page_end-start-s_length);
 
754
  memcpy(start, start + s_length, page_end-start-s_length);
753
755
  return s_length;
754
756
} /* remove_key */