mi_delete.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:28k
源码类别:

MySQL数据库

开发平台:

Visual C++

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