~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
/* Remove a row from a MyISAM table */
17
1130.3.28 by Monty Taylor
Moved heapdef.h and myisamdef.h to *_priv.h for easier filtering for include guard check.
18
#include "myisam_priv.h"
612.2.13 by Monty Taylor
Work on removing global.h from headers that should be installed.
19
#include <mystrings/m_string.h>
492.1.7 by Monty Taylor
Moved test() to its own file.
20
#include <drizzled/util/test.h>
1 by brian
clean slate
21
482 by Brian Aker
Remove uint.
22
static int d_search(MI_INFO *info,MI_KEYDEF *keyinfo,uint32_t comp_flag,
23
                    unsigned char *key,uint32_t key_length,my_off_t page,unsigned char *anc_buff);
481 by Brian Aker
Remove all of uchar.
24
static int del(MI_INFO *info,MI_KEYDEF *keyinfo,unsigned char *key,unsigned char *anc_buff,
25
	       my_off_t leaf_page,unsigned char *leaf_buff,unsigned char *keypos,
26
	       my_off_t next_block,unsigned char *ret_key);
27
static int underflow(MI_INFO *info,MI_KEYDEF *keyinfo,unsigned char *anc_buff,
28
		     my_off_t leaf_page,unsigned char *leaf_buff,unsigned char *keypos);
482 by Brian Aker
Remove uint.
29
static uint32_t remove_key(MI_KEYDEF *keyinfo,uint32_t nod_flag,unsigned char *keypos,
481 by Brian Aker
Remove all of uchar.
30
		       unsigned char *lastkey,unsigned char *page_end,
1 by brian
clean slate
31
		       my_off_t *next_block);
32
static int _mi_ck_real_delete(register MI_INFO *info,MI_KEYDEF *keyinfo,
482 by Brian Aker
Remove uint.
33
			      unsigned char *key, uint32_t key_length, my_off_t *root);
481 by Brian Aker
Remove all of uchar.
34
35
36
int mi_delete(MI_INFO *info,const unsigned char *record)
1 by brian
clean slate
37
{
482 by Brian Aker
Remove uint.
38
  uint32_t i;
481 by Brian Aker
Remove all of uchar.
39
  unsigned char *old_key;
1 by brian
clean slate
40
  int save_errno;
41
  char lastpos[8];
42
43
  MYISAM_SHARE *share=info->s;
44
45
	/* Test if record is in datafile */
46
  if (!(info->update & HA_STATE_AKTIV))
47
  {
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
48
    return(my_errno=HA_ERR_KEY_NOT_FOUND);	/* No database read */
1 by brian
clean slate
49
  }
50
  if (share->options & HA_OPTION_READ_ONLY_DATA)
51
  {
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
52
    return(my_errno=EACCES);
1 by brian
clean slate
53
  }
54
  if (_mi_readinfo(info,F_WRLCK,1))
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
55
    return(my_errno);
1 by brian
clean slate
56
  if (info->s->calc_checksum)
57
    info->checksum=(*info->s->calc_checksum)(info,record);
58
  if ((*share->compare_record)(info,record))
59
    goto err;				/* Error on read-check */
60
61
  if (_mi_mark_file_changed(info))
62
    goto err;
63
64
	/* Remove all keys from the .ISAM file */
65
66
  old_key=info->lastkey2;
67
  for (i=0 ; i < share->base.keys ; i++ )
68
  {
69
    if (mi_is_key_active(info->s->state.key_map, i))
70
    {
71
      info->s->keyinfo[i].version++;
72
      {
73
        if (info->s->keyinfo[i].ck_delete(info,i,old_key,
74
                _mi_make_key(info,i,old_key,record,info->lastpos)))
75
          goto err;
76
      }
77
      /* The above changed info->lastkey2. Inform mi_rnext_same(). */
78
      info->update&= ~HA_STATE_RNEXT_SAME;
79
    }
80
  }
81
82
  if ((*share->delete_record)(info))
83
    goto err;				/* Remove record from database */
84
  info->state->checksum-=info->checksum;
85
86
  info->update= HA_STATE_CHANGED+HA_STATE_DELETED+HA_STATE_ROW_CHANGED;
87
  info->state->records--;
88
89
  mi_sizestore(lastpos,info->lastpos);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
90
  _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
91
  return(0);
1 by brian
clean slate
92
93
err:
94
  save_errno=my_errno;
95
  mi_sizestore(lastpos,info->lastpos);
96
  if (save_errno != HA_ERR_RECORD_CHANGED)
97
  {
98
    mi_print_error(info->s, HA_ERR_CRASHED);
99
    mi_mark_crashed(info);		/* mark table crashed */
100
  }
398.1.10 by Monty Taylor
Actually removed VOID() this time.
101
  _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
1 by brian
clean slate
102
  info->update|=HA_STATE_WRITTEN;	/* Buffer changed */
103
  my_errno=save_errno;
104
  if (save_errno == HA_ERR_KEY_NOT_FOUND)
105
  {
106
    mi_print_error(info->s, HA_ERR_CRASHED);
107
    my_errno=HA_ERR_CRASHED;
108
  }
109
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
110
  return(my_errno);
1 by brian
clean slate
111
} /* mi_delete */
112
113
114
	/* Remove a key from the btree index */
115
482 by Brian Aker
Remove uint.
116
int _mi_ck_delete(register MI_INFO *info, uint32_t keynr, unsigned char *key,
117
		  uint32_t key_length)
1 by brian
clean slate
118
{
119
  return _mi_ck_real_delete(info, info->s->keyinfo+keynr, key, key_length,
120
                            &info->s->state.key_root[keynr]);
121
} /* _mi_ck_delete */
122
123
124
static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo,
482 by Brian Aker
Remove uint.
125
			      unsigned char *key, uint32_t key_length, my_off_t *root)
1 by brian
clean slate
126
{
127
  int error;
482 by Brian Aker
Remove uint.
128
  uint32_t nod_flag;
1 by brian
clean slate
129
  my_off_t old_root;
481 by Brian Aker
Remove all of uchar.
130
  unsigned char *root_buff;
1 by brian
clean slate
131
132
  if ((old_root=*root) == HA_OFFSET_ERROR)
133
  {
134
    mi_print_error(info->s, HA_ERR_CRASHED);
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
135
    return(my_errno=HA_ERR_CRASHED);
1 by brian
clean slate
136
  }
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
137
  if (!(root_buff= (unsigned char*) malloc(keyinfo->block_length+
1 by brian
clean slate
138
				      MI_MAX_KEY_BUFF*2)))
139
  {
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
140
    return(my_errno=ENOMEM);
1 by brian
clean slate
141
  }
142
  if (!_mi_fetch_keypage(info,keyinfo,old_root,DFLT_INIT_HITS,root_buff,0))
143
  {
144
    error= -1;
145
    goto err;
146
  }
76 by Brian Aker
Next pass on fulltext.
147
  if ((error=d_search(info,keyinfo, (SEARCH_SAME), key,key_length,old_root,root_buff)) > 0)
1 by brian
clean slate
148
  {
149
    if (error == 2)
150
    {
151
      error=_mi_enlarge_root(info,keyinfo,key,root);
152
    }
153
    else /* error == 1 */
154
    {
155
      if (mi_getint(root_buff) <= (nod_flag=mi_test_if_nod(root_buff))+3)
156
      {
157
	error=0;
158
	if (nod_flag)
159
	  *root=_mi_kpos(nod_flag,root_buff+2+nod_flag);
160
	else
161
	  *root=HA_OFFSET_ERROR;
162
	if (_mi_dispose(info,keyinfo,old_root,DFLT_INIT_HITS))
163
	  error= -1;
164
      }
165
      else
166
	error=_mi_write_keypage(info,keyinfo,old_root,
167
                                DFLT_INIT_HITS,root_buff);
168
    }
169
  }
170
err:
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
171
  free(root_buff);
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
172
  return(error);
1 by brian
clean slate
173
} /* _mi_ck_real_delete */
174
175
176
	/*
177
	** Remove key below key root
178
	** Return values:
179
	** 1 if there are less buffers;  In this case anc_buff is not saved
180
	** 2 if there are more buffers
181
	** -1 on errors
182
	*/
183
184
static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
482 by Brian Aker
Remove uint.
185
                    uint32_t comp_flag, unsigned char *key, uint32_t key_length,
481 by Brian Aker
Remove all of uchar.
186
                    my_off_t page, unsigned char *anc_buff)
1 by brian
clean slate
187
{
188
  int flag,ret_value,save_flag;
482 by Brian Aker
Remove uint.
189
  uint32_t length,nod_flag,search_key_length;
281 by Brian Aker
Converted myisam away from my_bool
190
  bool last_key;
481 by Brian Aker
Remove all of uchar.
191
  unsigned char *leaf_buff,*keypos;
1 by brian
clean slate
192
  my_off_t leaf_page= 0, next_block;
481 by Brian Aker
Remove all of uchar.
193
  unsigned char lastkey[MI_MAX_KEY_BUFF];
1 by brian
clean slate
194
195
  search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY;
196
  flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key, search_key_length,
197
                              comp_flag, &keypos, lastkey, &last_key);
198
  if (flag == MI_FOUND_WRONG_KEY)
199
  {
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
200
    return(-1);
1 by brian
clean slate
201
  }
202
  nod_flag=mi_test_if_nod(anc_buff);
203
204
  leaf_buff= 0;
205
  if (nod_flag)
206
  {
207
    leaf_page=_mi_kpos(nod_flag,keypos);
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
208
    if (!(leaf_buff= (unsigned char*) malloc(keyinfo->block_length+
1 by brian
clean slate
209
					MI_MAX_KEY_BUFF*2)))
210
    {
211
      my_errno=ENOMEM;
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
212
      return(-1);
1 by brian
clean slate
213
    }
214
    if (!_mi_fetch_keypage(info,keyinfo,leaf_page,DFLT_INIT_HITS,leaf_buff,0))
215
      goto err;
216
  }
217
218
  if (flag != 0)
219
  {
220
    if (!nod_flag)
221
    {
222
      mi_print_error(info->s, HA_ERR_CRASHED);
223
      my_errno=HA_ERR_CRASHED;		/* This should newer happend */
224
      goto err;
225
    }
226
    save_flag=0;
227
    ret_value=d_search(info,keyinfo,comp_flag,key,key_length,
228
                       leaf_page,leaf_buff);
229
  }
230
  else
231
  {						/* Found key */
482 by Brian Aker
Remove uint.
232
    uint32_t tmp;
1 by brian
clean slate
233
    length=mi_getint(anc_buff);
234
    if (!(tmp= remove_key(keyinfo,nod_flag,keypos,lastkey,anc_buff+length,
235
                          &next_block)))
236
      goto err;
237
238
    length-= tmp;
239
240
    mi_putint(anc_buff,length,nod_flag);
241
    if (!nod_flag)
242
    {						/* On leaf page */
243
      if (_mi_write_keypage(info,keyinfo,page,DFLT_INIT_HITS,anc_buff))
244
      {
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
245
	return(-1);
1 by brian
clean slate
246
      }
247
      /* Page will be update later if we return 1 */
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
248
      return(test(length <= (info->quick_mode ? MI_MIN_KEYBLOCK_LENGTH :
1 by brian
clean slate
249
				  (uint) keyinfo->underflow_block_length)));
250
    }
251
    save_flag=1;
252
    ret_value=del(info,keyinfo,key,anc_buff,leaf_page,leaf_buff,keypos,
253
		  next_block,lastkey);
254
  }
255
  if (ret_value >0)
256
  {
257
    save_flag=1;
258
    if (ret_value == 1)
259
      ret_value= underflow(info,keyinfo,anc_buff,leaf_page,leaf_buff,keypos);
260
    else
261
    {				/* This happens only with packed keys */
262
      if (!_mi_get_last_key(info,keyinfo,anc_buff,lastkey,keypos,&length))
263
      {
264
	goto err;
265
      }
266
      ret_value=_mi_insert(info,keyinfo,key,anc_buff,keypos,lastkey,
481 by Brian Aker
Remove all of uchar.
267
			   (unsigned char*) 0,(unsigned char*) 0,(my_off_t) 0,(bool) 0);
1 by brian
clean slate
268
    }
269
  }
270
  if (ret_value == 0 && mi_getint(anc_buff) > keyinfo->block_length)
271
  {
272
    save_flag=1;
273
    ret_value=_mi_split_page(info,keyinfo,key,anc_buff,lastkey,0) | 2;
274
  }
275
  if (save_flag && ret_value != 1)
276
    ret_value|=_mi_write_keypage(info,keyinfo,page,DFLT_INIT_HITS,anc_buff);
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
277
  free(leaf_buff);
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
278
  return(ret_value);
1 by brian
clean slate
279
280
err:
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
281
  free(leaf_buff);
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
282
  return (-1);
1 by brian
clean slate
283
} /* d_search */
284
285
286
	/* Remove a key that has a page-reference */
287
481 by Brian Aker
Remove all of uchar.
288
static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, unsigned char *key,
289
	       unsigned char *anc_buff, my_off_t leaf_page, unsigned char *leaf_buff,
290
	       unsigned char *keypos,		/* Pos to where deleted key was */
1 by brian
clean slate
291
	       my_off_t next_block,
481 by Brian Aker
Remove all of uchar.
292
	       unsigned char *ret_key)		/* key before keypos in anc_buff */
1 by brian
clean slate
293
{
294
  int ret_value,length;
482 by Brian Aker
Remove uint.
295
  uint32_t a_length,nod_flag,tmp;
1 by brian
clean slate
296
  my_off_t next_page;
481 by Brian Aker
Remove all of uchar.
297
  unsigned char keybuff[MI_MAX_KEY_BUFF],*endpos,*next_buff,*key_start, *prev_key;
1 by brian
clean slate
298
  MYISAM_SHARE *share=info->s;
299
  MI_KEY_PARAM s_temp;
300
301
  endpos=leaf_buff+mi_getint(leaf_buff);
302
  if (!(key_start=_mi_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos,
303
				   &tmp)))
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
304
    return(-1);
1 by brian
clean slate
305
306
  if ((nod_flag=mi_test_if_nod(leaf_buff)))
307
  {
308
    next_page= _mi_kpos(nod_flag,endpos);
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
309
    if (!(next_buff= (unsigned char*) malloc(keyinfo->block_length+
1 by brian
clean slate
310
					MI_MAX_KEY_BUFF*2)))
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
311
      return(-1);
1 by brian
clean slate
312
    if (!_mi_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,next_buff,0))
313
      ret_value= -1;
314
    else
315
    {
316
      if ((ret_value=del(info,keyinfo,key,anc_buff,next_page,next_buff,
317
			 keypos,next_block,ret_key)) >0)
318
      {
319
	endpos=leaf_buff+mi_getint(leaf_buff);
320
	if (ret_value == 1)
321
	{
322
	  ret_value=underflow(info,keyinfo,leaf_buff,next_page,
323
			      next_buff,endpos);
324
	  if (ret_value == 0 && mi_getint(leaf_buff) > keyinfo->block_length)
325
	  {
326
	    ret_value=_mi_split_page(info,keyinfo,key,leaf_buff,ret_key,0) | 2;
327
	  }
328
	}
329
	else
330
	{
331
	  if (!_mi_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos,
332
				&tmp))
333
	    goto err;
334
	  ret_value=_mi_insert(info,keyinfo,key,leaf_buff,endpos,keybuff,
481 by Brian Aker
Remove all of uchar.
335
			       (unsigned char*) 0,(unsigned char*) 0,(my_off_t) 0,0);
1 by brian
clean slate
336
	}
337
      }
338
      if (_mi_write_keypage(info,keyinfo,leaf_page,DFLT_INIT_HITS,leaf_buff))
339
	goto err;
340
    }
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
341
    free(next_buff);
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
342
    return(ret_value);
1 by brian
clean slate
343
  }
344
345
	/* Remove last key from leaf page */
346
347
  mi_putint(leaf_buff,key_start-leaf_buff,nod_flag);
348
  if (_mi_write_keypage(info,keyinfo,leaf_page,DFLT_INIT_HITS,leaf_buff))
349
    goto err;
350
351
	/* Place last key in ancestor page on deleted key position */
352
353
  a_length=mi_getint(anc_buff);
354
  endpos=anc_buff+a_length;
355
  if (keypos != anc_buff+2+share->base.key_reflength &&
356
      !_mi_get_last_key(info,keyinfo,anc_buff,ret_key,keypos,&tmp))
357
    goto err;
358
  prev_key=(keypos == anc_buff+2+share->base.key_reflength ?
359
	    0 : ret_key);
360
  length=(*keyinfo->pack_key)(keyinfo,share->base.key_reflength,
481 by Brian Aker
Remove all of uchar.
361
			      keypos == endpos ? (unsigned char*) 0 : keypos,
1 by brian
clean slate
362
			      prev_key, prev_key,
363
			      keybuff,&s_temp);
364
  if (length > 0)
481 by Brian Aker
Remove all of uchar.
365
    bmove_upp((unsigned char*) endpos+length,(unsigned char*) endpos,(uint) (endpos-keypos));
1 by brian
clean slate
366
  else
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
367
    memmove(keypos,keypos-length, (int) (endpos-keypos)+length);
1 by brian
clean slate
368
  (*keyinfo->store_key)(keyinfo,keypos,&s_temp);
369
  /* Save pointer to next leaf */
370
  if (!(*keyinfo->get_key)(keyinfo,share->base.key_reflength,&keypos,ret_key))
371
    goto err;
372
  _mi_kpointer(info,keypos - share->base.key_reflength,next_block);
373
  mi_putint(anc_buff,a_length+length,share->base.key_reflength);
374
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
375
  return( mi_getint(leaf_buff) <=
1 by brian
clean slate
376
	       (info->quick_mode ? MI_MIN_KEYBLOCK_LENGTH :
377
		(uint) keyinfo->underflow_block_length));
378
err:
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
379
  return(-1);
1 by brian
clean slate
380
} /* del */
381
382
383
	/* Balances adjacent pages if underflow occours */
384
385
static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
481 by Brian Aker
Remove all of uchar.
386
		     unsigned char *anc_buff,
1 by brian
clean slate
387
		     my_off_t leaf_page,/* Ancestor page and underflow page */
481 by Brian Aker
Remove all of uchar.
388
		     unsigned char *leaf_buff,
389
		     unsigned char *keypos)	/* Position to pos after key */
1 by brian
clean slate
390
{
391
  int t_length;
482 by Brian Aker
Remove uint.
392
  uint32_t length,anc_length,buff_length,leaf_length,p_length,s_length,nod_flag,
1 by brian
clean slate
393
       key_reflength,key_length;
394
  my_off_t next_page;
481 by Brian Aker
Remove all of uchar.
395
  unsigned char anc_key[MI_MAX_KEY_BUFF],leaf_key[MI_MAX_KEY_BUFF],
1 by brian
clean slate
396
        *buff,*endpos,*next_keypos,*anc_pos,*half_pos,*temp_pos,*prev_key,
397
        *after_key;
398
  MI_KEY_PARAM s_temp;
399
  MYISAM_SHARE *share=info->s;
400
401
  buff=info->buff;
402
  info->buff_used=1;
403
  next_keypos=keypos;
404
  nod_flag=mi_test_if_nod(leaf_buff);
405
  p_length=nod_flag+2;
406
  anc_length=mi_getint(anc_buff);
407
  leaf_length=mi_getint(leaf_buff);
408
  key_reflength=share->base.key_reflength;
409
  if (info->s->keyinfo+info->lastinx == keyinfo)
410
    info->page_changed=1;
411
412
  if ((keypos < anc_buff+anc_length && (info->state->records & 1)) ||
413
      keypos == anc_buff+2+key_reflength)
414
  {					/* Use page right of anc-page */
415
    if (keyinfo->flag & HA_BINARY_PACK_KEY)
416
    {
417
      if (!(next_keypos=_mi_get_key(info, keyinfo,
418
				    anc_buff, buff, keypos, &length)))
419
	goto err;
420
    }
421
    else
422
    {
423
      /* Got to end of found key */
424
      buff[0]=buff[1]=0;	/* Avoid length error check if packed key */
425
      if (!(*keyinfo->get_key)(keyinfo,key_reflength,&next_keypos,
426
			       buff))
427
      goto err;
428
    }
429
    next_page= _mi_kpos(key_reflength,next_keypos);
430
    if (!_mi_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,buff,0))
431
      goto err;
432
    buff_length=mi_getint(buff);
433
434
    /* find keys to make a big key-page */
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
435
    memmove(next_keypos - key_reflength, buff + 2, key_reflength);
1 by brian
clean slate
436
    if (!_mi_get_last_key(info,keyinfo,anc_buff,anc_key,next_keypos,&length)
437
	|| !_mi_get_last_key(info,keyinfo,leaf_buff,leaf_key,
438
			     leaf_buff+leaf_length,&length))
439
      goto err;
440
441
    /* merge pages and put parting key from anc_buff between */
481 by Brian Aker
Remove all of uchar.
442
    prev_key=(leaf_length == p_length ? (unsigned char*) 0 : leaf_key);
1 by brian
clean slate
443
    t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,buff+p_length,
444
				  prev_key, prev_key,
445
				  anc_key, &s_temp);
446
    length=buff_length-p_length;
447
    endpos=buff+length+leaf_length+t_length;
448
    /* buff will always be larger than before !*/
481 by Brian Aker
Remove all of uchar.
449
    bmove_upp((unsigned char*) endpos, (unsigned char*) buff+buff_length,length);
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
450
    memcpy(buff, leaf_buff, leaf_length);
1 by brian
clean slate
451
    (*keyinfo->store_key)(keyinfo,buff+leaf_length,&s_temp);
452
    buff_length=(uint) (endpos-buff);
453
    mi_putint(buff,buff_length,nod_flag);
454
455
    /* remove key from anc_buff */
456
457
    if (!(s_length=remove_key(keyinfo,key_reflength,keypos,anc_key,
458
                              anc_buff+anc_length,(my_off_t *) 0)))
459
      goto err;
460
461
    anc_length-=s_length;
462
    mi_putint(anc_buff,anc_length,key_reflength);
463
464
    if (buff_length <= keyinfo->block_length)
465
    {						/* Keys in one page */
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
466
      memcpy(leaf_buff, buff, buff_length);
1 by brian
clean slate
467
      if (_mi_dispose(info,keyinfo,next_page,DFLT_INIT_HITS))
468
       goto err;
469
    }
470
    else
471
    {						/* Page is full */
472
      endpos=anc_buff+anc_length;
473
      if (keypos != anc_buff+2+key_reflength &&
474
	  !_mi_get_last_key(info,keyinfo,anc_buff,anc_key,keypos,&length))
475
	goto err;
476
      if (!(half_pos=_mi_find_half_pos(nod_flag, keyinfo, buff, leaf_key,
477
				       &key_length, &after_key)))
478
	goto err;
479
      length=(uint) (half_pos-buff);
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
480
      memcpy(leaf_buff, buff, length);
1 by brian
clean slate
481
      mi_putint(leaf_buff,length,nod_flag);
482
483
      /* Correct new keypointer to leaf_page */
484
      half_pos=after_key;
485
      _mi_kpointer(info,leaf_key+key_length,next_page);
486
      /* Save key in anc_buff */
481 by Brian Aker
Remove all of uchar.
487
      prev_key=(keypos == anc_buff+2+key_reflength ? (unsigned char*) 0 : anc_key),
1 by brian
clean slate
488
      t_length=(*keyinfo->pack_key)(keyinfo,key_reflength,
481 by Brian Aker
Remove all of uchar.
489
				    (keypos == endpos ? (unsigned char*) 0 :
1 by brian
clean slate
490
				     keypos),
491
				    prev_key, prev_key,
492
				    leaf_key, &s_temp);
493
      if (t_length >= 0)
481 by Brian Aker
Remove all of uchar.
494
	bmove_upp((unsigned char*) endpos+t_length,(unsigned char*) endpos,
1 by brian
clean slate
495
		  (uint) (endpos-keypos));
496
      else
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
497
	memmove(keypos,keypos-t_length,(uint) (endpos-keypos)+t_length);
1 by brian
clean slate
498
      (*keyinfo->store_key)(keyinfo,keypos,&s_temp);
499
      mi_putint(anc_buff,(anc_length+=t_length),key_reflength);
500
501
	/* Store key first in new page */
502
      if (nod_flag)
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
503
	memmove(buff + 2, half_pos - nod_flag, nod_flag);
1 by brian
clean slate
504
      if (!(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key))
505
	goto err;
481 by Brian Aker
Remove all of uchar.
506
      t_length=(int) (*keyinfo->pack_key)(keyinfo, nod_flag, (unsigned char*) 0,
507
					  (unsigned char*) 0, (unsigned char *) 0,
1 by brian
clean slate
508
					  leaf_key, &s_temp);
509
      /* t_length will always be > 0 for a new page !*/
510
      length=(uint) ((buff+mi_getint(buff))-half_pos);
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
511
      memmove(buff + p_length + t_length, half_pos, length);
1 by brian
clean slate
512
      (*keyinfo->store_key)(keyinfo,buff+p_length,&s_temp);
513
      mi_putint(buff,length+t_length+p_length,nod_flag);
514
515
      if (_mi_write_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,buff))
516
	goto err;
517
    }
518
    if (_mi_write_keypage(info,keyinfo,leaf_page,DFLT_INIT_HITS,leaf_buff))
519
      goto err;
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
520
    return(anc_length <= ((info->quick_mode ? MI_MIN_BLOCK_LENGTH :
1 by brian
clean slate
521
				(uint) keyinfo->underflow_block_length)));
522
  }
523
524
  keypos=_mi_get_last_key(info,keyinfo,anc_buff,anc_key,keypos,&length);
525
  if (!keypos)
526
    goto err;
527
  next_page= _mi_kpos(key_reflength,keypos);
528
  if (!_mi_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,buff,0))
529
      goto err;
530
  buff_length=mi_getint(buff);
531
  endpos=buff+buff_length;
532
533
  /* find keys to make a big key-page */
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
534
  memmove(next_keypos - key_reflength, leaf_buff+2, key_reflength);
1 by brian
clean slate
535
  next_keypos=keypos;
536
  if (!(*keyinfo->get_key)(keyinfo,key_reflength,&next_keypos,
537
			   anc_key))
538
    goto err;
539
  if (!_mi_get_last_key(info,keyinfo,buff,leaf_key,endpos,&length))
540
    goto err;
541
542
  /* merge pages and put parting key from anc_buff between */
481 by Brian Aker
Remove all of uchar.
543
  prev_key=(leaf_length == p_length ? (unsigned char*) 0 : leaf_key);
1 by brian
clean slate
544
  t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
545
				(leaf_length == p_length ?
481 by Brian Aker
Remove all of uchar.
546
                                 (unsigned char*) 0 : leaf_buff+p_length),
1 by brian
clean slate
547
				prev_key, prev_key,
548
				anc_key, &s_temp);
549
  if (t_length >= 0)
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
550
    memmove(endpos+t_length,leaf_buff+p_length, leaf_length-p_length);
1 by brian
clean slate
551
  else						/* We gained space */
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
552
    memmove(endpos, leaf_buff+((int) p_length-t_length),
553
            leaf_length - p_length + t_length);
1 by brian
clean slate
554
555
  (*keyinfo->store_key)(keyinfo,endpos,&s_temp);
556
  buff_length=buff_length+leaf_length-p_length+t_length;
557
  mi_putint(buff,buff_length,nod_flag);
558
559
  /* remove key from anc_buff */
560
  if (!(s_length= remove_key(keyinfo,key_reflength,keypos,anc_key,
561
                             anc_buff+anc_length,(my_off_t *) 0)))
562
    goto err;
563
564
  anc_length-=s_length;
565
  mi_putint(anc_buff,anc_length,key_reflength);
566
567
  if (buff_length <= keyinfo->block_length)
568
  {						/* Keys in one page */
569
    if (_mi_dispose(info,keyinfo,leaf_page,DFLT_INIT_HITS))
570
      goto err;
571
  }
572
  else
573
  {						/* Page is full */
574
    if (keypos == anc_buff+2+key_reflength)
575
      anc_pos=0;				/* First key */
576
    else if (!_mi_get_last_key(info,keyinfo,anc_buff,anc_pos=anc_key,keypos,
577
			       &length))
578
      goto err;
579
    endpos=_mi_find_half_pos(nod_flag,keyinfo,buff,leaf_key,
580
			     &key_length, &half_pos);
581
    if (!endpos)
582
      goto err;
583
    _mi_kpointer(info,leaf_key+key_length,leaf_page);
584
    /* Save key in anc_buff */
585
586
    temp_pos=anc_buff+anc_length;
587
    t_length=(*keyinfo->pack_key)(keyinfo,key_reflength,
481 by Brian Aker
Remove all of uchar.
588
				  keypos == temp_pos ? (unsigned char*) 0
1 by brian
clean slate
589
				  : keypos,
590
				  anc_pos, anc_pos,
591
				  leaf_key,&s_temp);
592
    if (t_length > 0)
481 by Brian Aker
Remove all of uchar.
593
      bmove_upp((unsigned char*) temp_pos+t_length,(unsigned char*) temp_pos,
1 by brian
clean slate
594
		(uint) (temp_pos-keypos));
595
    else
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
596
      memmove(keypos,keypos-t_length,(uint) (temp_pos-keypos)+t_length);
1 by brian
clean slate
597
    (*keyinfo->store_key)(keyinfo,keypos,&s_temp);
598
    mi_putint(anc_buff,(anc_length+=t_length),key_reflength);
599
600
    /* Store first key on new page */
601
    if (nod_flag)
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
602
      memmove(leaf_buff+2, half_pos - nod_flag, nod_flag);
1 by brian
clean slate
603
    if (!(length=(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key)))
604
      goto err;
481 by Brian Aker
Remove all of uchar.
605
    t_length=(*keyinfo->pack_key)(keyinfo,nod_flag, (unsigned char*) 0,
606
				  (unsigned char*) 0, (unsigned char*) 0, leaf_key, &s_temp);
1 by brian
clean slate
607
    length=(uint) ((buff+buff_length)-half_pos);
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
608
    memmove(leaf_buff + p_length + t_length, half_pos, length);
1 by brian
clean slate
609
    (*keyinfo->store_key)(keyinfo,leaf_buff+p_length,&s_temp);
610
    mi_putint(leaf_buff,length+t_length+p_length,nod_flag);
611
    if (_mi_write_keypage(info,keyinfo,leaf_page,DFLT_INIT_HITS,leaf_buff))
612
      goto err;
613
    mi_putint(buff,endpos-buff,nod_flag);
614
  }
615
  if (_mi_write_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,buff))
616
    goto err;
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
617
  return(anc_length <= (uint) keyinfo->block_length/2);
1 by brian
clean slate
618
619
err:
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
620
  return(-1);
1 by brian
clean slate
621
} /* underflow */
622
623
624
	/*
625
	  remove a key from packed buffert
626
	  The current code doesn't handle the case that the next key may be
627
	  packed better against the previous key if there is a case difference
628
	  returns how many chars was removed or 0 on error
629
	*/
630
482 by Brian Aker
Remove uint.
631
static uint32_t remove_key(MI_KEYDEF *keyinfo, uint32_t nod_flag,
481 by Brian Aker
Remove all of uchar.
632
		       unsigned char *keypos,	/* Where key starts */
633
		       unsigned char *lastkey,	/* key to be removed */
634
		       unsigned char *page_end, /* End of page */
1 by brian
clean slate
635
		       my_off_t *next_block)	/* ptr to next block */
636
{
637
  int s_length;
481 by Brian Aker
Remove all of uchar.
638
  unsigned char *start;
1 by brian
clean slate
639
640
  start=keypos;
641
  if (!(keyinfo->flag &
642
	(HA_PACK_KEY | HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY |
643
	 HA_BINARY_PACK_KEY)))
644
  {
645
    s_length=(int) (keyinfo->keylength+nod_flag);
646
    if (next_block && nod_flag)
647
      *next_block= _mi_kpos(nod_flag,keypos+s_length);
648
  }
649
  else
650
  {					 /* Let keypos point at next key */
651
    /* Calculate length of key */
652
    if (!(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey))
51.1.95 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
653
      return(0);				/* Error */
1 by brian
clean slate
654
655
    if (next_block && nod_flag)
656
      *next_block= _mi_kpos(nod_flag,keypos);
657
    s_length=(int) (keypos-start);
658
    if (keypos != page_end)
659
    {
660
      if (keyinfo->flag & HA_BINARY_PACK_KEY)
661
      {
481 by Brian Aker
Remove all of uchar.
662
	unsigned char *old_key=start;
482 by Brian Aker
Remove uint.
663
	uint32_t next_length,prev_length,prev_pack_length;
1 by brian
clean slate
664
	get_key_length(next_length,keypos);
665
	get_key_pack_length(prev_length,prev_pack_length,old_key);
666
	if (next_length > prev_length)
667
	{
668
	  /* We have to copy data from the current key to the next key */
669
	  bmove_upp(keypos, (lastkey+next_length),
670
		    (next_length-prev_length));
671
	  keypos-=(next_length-prev_length)+prev_pack_length;
672
	  store_key_length(keypos,prev_length);
673
	  s_length=(int) (keypos-start);
674
	}
675
      }
676
      else
677
      {
678
	/* Check if a variable length first key part */
679
	if ((keyinfo->seg->flag & HA_PACK_KEY) && *keypos & 128)
680
	{
681
	  /* Next key is packed against the current one */
482 by Brian Aker
Remove uint.
682
	  uint32_t next_length,prev_length,prev_pack_length,lastkey_length,
1 by brian
clean slate
683
	    rest_length;
684
	  if (keyinfo->seg[0].length >= 127)
685
	  {
686
	    if (!(prev_length=mi_uint2korr(start) & 32767))
687
	      goto end;
688
	    next_length=mi_uint2korr(keypos) & 32767;
689
	    keypos+=2;
690
	    prev_pack_length=2;
691
	  }
692
	  else
693
	  {
694
	    if (!(prev_length= *start & 127))
695
	      goto end;				/* Same key as previous*/
696
	    next_length= *keypos & 127;
697
	    keypos++;
698
	    prev_pack_length=1;
699
	  }
700
	  if (!(*start & 128))
701
	    prev_length=0;			/* prev key not packed */
702
	  if (keyinfo->seg[0].flag & HA_NULL_PART)
703
	    lastkey++;				/* Skip null marker */
704
	  get_key_length(lastkey_length,lastkey);
705
	  if (!next_length)			/* Same key after */
706
	  {
707
	    next_length=lastkey_length;
708
	    rest_length=0;
709
	  }
710
	  else
711
	    get_key_length(rest_length,keypos);
712
713
	  if (next_length >= prev_length)
714
	  {		/* Key after is based on deleted key */
482 by Brian Aker
Remove uint.
715
	    uint32_t pack_length,tmp;
1 by brian
clean slate
716
	    bmove_upp(keypos, (lastkey+next_length),
717
		      tmp=(next_length-prev_length));
718
	    rest_length+=tmp;
719
	    pack_length= prev_length ? get_pack_length(rest_length): 0;
720
	    keypos-=tmp+pack_length+prev_pack_length;
721
	    s_length=(int) (keypos-start);
722
	    if (prev_length)			/* Pack against prev key */
723
	    {
724
	      *keypos++= start[0];
725
	      if (prev_pack_length == 2)
726
		*keypos++= start[1];
727
	      store_key_length(keypos,rest_length);
728
	    }
729
	    else
730
	    {
731
	      /* Next key is not packed anymore */
732
	      if (keyinfo->seg[0].flag & HA_NULL_PART)
733
	      {
734
		rest_length++;			/* Mark not null */
735
	      }
736
	      if (prev_pack_length == 2)
737
	      {
738
		mi_int2store(keypos,rest_length);
739
	      }
740
	      else
741
		*keypos= rest_length;
742
	    }
743
	  }
744
	}
745
      }
746
    }
747
  }
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
748
end:
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
749
  assert(page_end-start >= s_length);
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
750
  memmove(start, start + s_length, page_end-start-s_length);
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
751
  return s_length;
1 by brian
clean slate
752
} /* remove_key */