mi_delete.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:25k
源码类别:

MySQL数据库

开发平台:

Visual C++

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