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

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. /* Tar bort ett record fr}n en isam-databas */
  14. #include "isamdef.h"
  15. #ifdef __WIN__
  16. #include <errno.h>
  17. #endif
  18. #include <assert.h>
  19. static int d_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,ulong page,
  20.     uchar *anc_buff);
  21. static int del(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,uchar *anc_buff,
  22.        ulong leaf_page,uchar *leaf_buff,uchar *keypos,
  23.        ulong next_block,uchar *ret_key);
  24. static int underflow(N_INFO *info,N_KEYDEF *keyinfo,uchar *anc_buff,
  25.      ulong leaf_page, uchar *leaf_buff,uchar *keypos);
  26. static uint remove_key(N_KEYDEF *keyinfo,uint nod_flag,uchar *keypos,
  27.        uchar *lastkey,uchar *page_end);
  28. int nisam_delete(N_INFO *info,const byte *record)
  29. {
  30.   uint i;
  31.   uchar *old_key;
  32.   int save_errno;
  33.   uint32 lastpos;
  34.   ISAM_SHARE *share=info->s;
  35.   DBUG_ENTER("nisam_delete");
  36. /* Test if record is in datafile */
  37.   if (!(info->update & HA_STATE_AKTIV))
  38.   {
  39.     my_errno=HA_ERR_KEY_NOT_FOUND; /* No database read */
  40.     DBUG_RETURN(-1);
  41.   }
  42.   if (share->base.options & HA_OPTION_READ_ONLY_DATA)
  43.   {
  44.     my_errno=EACCES;
  45.     DBUG_RETURN(-1);
  46.   }
  47. #ifndef NO_LOCKING
  48.   if (_nisam_readinfo(info,F_WRLCK,1)) DBUG_RETURN(-1);
  49. #endif
  50.   if ((*share->compare_record)(info,record))
  51.     goto err; /* Fel vid kontroll-l{sning */
  52. /* Remove all keys from the .ISAM file */
  53.   old_key=info->lastkey+share->base.max_key_length;
  54.   for (i=0 ; i < share->state.keys ; i++ )
  55.   {
  56.     VOID(_nisam_make_key(info,i,old_key,record,info->lastpos));
  57.     if (_nisam_ck_delete(info,i,old_key)) goto err;
  58.   }
  59.   if ((*share->delete_record)(info))
  60.     goto err; /* Remove record from database */
  61.   info->update= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_DELETED;
  62.   share->state.records--;
  63.   lastpos= (uint32) info->lastpos;
  64.   nisam_log_command(LOG_DELETE,info,(byte*) &lastpos,sizeof(lastpos),0);
  65.   VOID(_nisam_writeinfo(info,1));
  66.   allow_break(); /* Allow SIGHUP & SIGINT */
  67.   DBUG_RETURN(0);
  68. err:
  69.   save_errno=my_errno;
  70.   lastpos= (uint32) info->lastpos;
  71.   nisam_log_command(LOG_DELETE,info,(byte*) &lastpos, sizeof(lastpos),0);
  72.   VOID(_nisam_writeinfo(info,1));
  73.   info->update|=HA_STATE_WRITTEN; /* Buffer changed */
  74.   allow_break(); /* Allow SIGHUP & SIGINT */
  75.   my_errno=save_errno;
  76.   if (save_errno == HA_ERR_KEY_NOT_FOUND)
  77.     my_errno=HA_ERR_CRASHED;
  78.   DBUG_RETURN(-1);
  79. } /* nisam_delete */
  80. /* Tar bort en nyckel till isam-nyckelfilen */
  81. int _nisam_ck_delete(register N_INFO *info, uint keynr, uchar *key)
  82. {
  83.   int error;
  84.   uint nod_flag;
  85.   ulong old_root;
  86.   uchar *root_buff;
  87.   N_KEYDEF *keyinfo;
  88.   DBUG_ENTER("_nisam_ck_delete");
  89.   if ((old_root=info->s->state.key_root[keynr]) == NI_POS_ERROR)
  90.   {
  91.     my_errno=HA_ERR_CRASHED;
  92.     DBUG_RETURN(-1);
  93.   }
  94.   keyinfo=info->s->keyinfo+keynr;
  95.   if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+
  96.       N_MAX_KEY_BUFF*2)))
  97.     DBUG_RETURN(-1);
  98.   if (!_nisam_fetch_keypage(info,keyinfo,old_root,root_buff,0))
  99.   {
  100.     error= -1;
  101.     goto err;
  102.   }
  103.   if ((error=d_search(info,keyinfo,key,old_root,root_buff)) >0)
  104.   {
  105.     if (error == 2)
  106.     {
  107.       DBUG_PRINT("test",("Enlarging of root when deleting"));
  108.       error=_nisam_enlarge_root(info,keynr,key);
  109.     }
  110.     else
  111.     {
  112.       error=0;
  113.       if (getint(root_buff) <= (nod_flag=test_if_nod(root_buff))+3)
  114.       {
  115. if (nod_flag)
  116.   info->s->state.key_root[keynr]=_nisam_kpos(nod_flag,
  117.        root_buff+2+nod_flag);
  118. else
  119.   info->s->state.key_root[keynr]= NI_POS_ERROR;
  120. if (_nisam_dispose(info,keyinfo,old_root))
  121.   error= -1;
  122.       }
  123.     }
  124.   }
  125. err:
  126.   my_afree((gptr) root_buff);
  127.   DBUG_RETURN(error);
  128. } /* _nisam_ck_delete */
  129. /* Tar bort en nyckel under root */
  130. /* Returnerar 1 om nuvarande buffert minskade */
  131. /* Returnerar 2 om nuvarande buffert |kar */
  132. static int d_search(register N_INFO *info, register N_KEYDEF *keyinfo, uchar *key, ulong page, uchar *anc_buff)
  133. {
  134.   int flag,ret_value,save_flag;
  135.   uint length,nod_flag;
  136.   uchar *leaf_buff,*keypos,*next_keypos;
  137.   ulong leaf_page,next_block;
  138.   uchar lastkey[N_MAX_KEY_BUFF];
  139.   DBUG_ENTER("d_search");
  140.   DBUG_DUMP("page",(byte*) anc_buff,getint(anc_buff));
  141.   flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key,0,SEARCH_SAME,&keypos,
  142.       lastkey);
  143.   nod_flag=test_if_nod(anc_buff);
  144.   leaf_buff=0;
  145.   LINT_INIT(leaf_page);
  146.   if (nod_flag)
  147.   {
  148.     leaf_page=_nisam_kpos(nod_flag,keypos);
  149.     if (!(leaf_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+
  150. N_MAX_KEY_BUFF*2)))
  151.     {
  152.       my_errno=ENOMEM;
  153.       DBUG_RETURN(-1);
  154.     }
  155.     if (!_nisam_fetch_keypage(info,keyinfo,leaf_page,leaf_buff,0))
  156.       goto err;
  157.   }
  158.   if (flag != 0)
  159.   {
  160.     if (!nod_flag)
  161.     {
  162.       my_errno=HA_ERR_CRASHED; /* This should newer happend */
  163.       goto err;
  164.     }
  165.     save_flag=0;
  166.     ret_value=d_search(info,keyinfo,key,leaf_page,leaf_buff);
  167.   }
  168.   else
  169.   { /* Found key */
  170.     next_keypos=keypos; /* Find where next block is */
  171.     VOID((*keyinfo->get_key)(keyinfo,nod_flag,&next_keypos,lastkey));
  172.     next_block=_nisam_kpos(nod_flag,next_keypos);
  173.     length=getint(anc_buff);
  174.     length-= remove_key(keyinfo,nod_flag,keypos,lastkey,anc_buff+length);
  175.     putint(anc_buff,length,nod_flag);
  176.     if (!nod_flag)
  177.     { /* On leaf page */
  178.       if (_nisam_write_keypage(info,keyinfo,page,anc_buff))
  179. DBUG_RETURN(-1);
  180.       DBUG_RETURN(length <= (uint) keyinfo->base.block_length/2);
  181.     }
  182.     save_flag=1;
  183.     ret_value=del(info,keyinfo,key,anc_buff,leaf_page,leaf_buff,keypos,
  184.   next_block,lastkey);
  185.   }
  186.   if (ret_value >0)
  187.   {
  188.     save_flag=1;
  189.     if (ret_value == 1)
  190.       ret_value= underflow(info,keyinfo,anc_buff,leaf_page,leaf_buff,keypos);
  191.     else
  192.     { /* This happens only with packed keys */
  193.       DBUG_PRINT("test",("Enlarging of key when deleting"));
  194.       VOID(_nisam_get_last_key(info,keyinfo,anc_buff,lastkey,keypos));
  195.       ret_value=_nisam_insert(info,keyinfo,key,anc_buff,keypos,lastkey,
  196.    (uchar*) 0,(uchar*) 0,0L);
  197.     }
  198.   }
  199.   if (ret_value == 0 && getint(anc_buff) > keyinfo->base.block_length)
  200.   {
  201.     save_flag=1;
  202.     ret_value=_nisam_splitt_page(info,keyinfo,key,anc_buff,lastkey) | 2;
  203.   }
  204.   if (save_flag)
  205.     ret_value|=_nisam_write_keypage(info,keyinfo,page,anc_buff);
  206.   else
  207.   {
  208.     DBUG_DUMP("page",(byte*) anc_buff,getint(anc_buff));
  209.   }
  210.   my_afree((byte*) leaf_buff);
  211.   DBUG_RETURN(ret_value);
  212. err:
  213.   my_afree((byte*) leaf_buff);
  214.   DBUG_PRINT("exit",("Error: %d",my_errno));
  215.   DBUG_RETURN (-1);
  216. } /* d_search */
  217. /* Remove a key that has a page-reference */
  218. static int del(register N_INFO *info, register N_KEYDEF *keyinfo, uchar *key,
  219.        uchar *anc_buff, ulong leaf_page, uchar *leaf_buff,
  220.        uchar *keypos, /* Pos to where deleted key was */
  221.        ulong next_block,
  222.        uchar *ret_key) /* key before keypos in anc_buff */
  223. {
  224.   int ret_value,length;
  225.   uint a_length,nod_flag;
  226.   ulong next_page;
  227.   uchar keybuff[N_MAX_KEY_BUFF],*endpos,*next_buff,*key_start;
  228.   ISAM_SHARE *share=info->s;
  229.   S_PARAM s_temp;
  230.   DBUG_ENTER("del");
  231.   DBUG_PRINT("enter",("leaf_page: %ld   keypos: %lx",leaf_page,keypos));
  232.   DBUG_DUMP("leaf_buff",(byte*) leaf_buff,getint(leaf_buff));
  233.   endpos=leaf_buff+getint(leaf_buff);
  234.   key_start=_nisam_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos);
  235.   if ((nod_flag=test_if_nod(leaf_buff)))
  236.   {
  237.     next_page= _nisam_kpos(nod_flag,endpos);
  238.     if (!(next_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+
  239. N_MAX_KEY_BUFF)))
  240.       DBUG_RETURN(-1);
  241.     if (!_nisam_fetch_keypage(info,keyinfo,next_page,next_buff,0))
  242.       ret_value= -1;
  243.     else
  244.     {
  245.       DBUG_DUMP("next_page",(byte*) next_buff,getint(next_buff));
  246.       if ((ret_value=del(info,keyinfo,key,anc_buff,next_page,next_buff,
  247.  keypos,next_block,ret_key)) >0)
  248.       {
  249. endpos=leaf_buff+getint(leaf_buff);
  250. if (ret_value == 1)
  251. {
  252.   ret_value=underflow(info,keyinfo,leaf_buff,next_page,
  253.       next_buff,endpos);
  254.   if (ret_value == 0 && getint(leaf_buff) > keyinfo->base.block_length)
  255.   {
  256.     ret_value=_nisam_splitt_page(info,keyinfo,key,leaf_buff,ret_key) | 2;
  257.   }
  258. }
  259. else
  260. {
  261.   DBUG_PRINT("test",("Inserting of key when deleting"));
  262.   VOID(_nisam_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos));
  263.   ret_value=_nisam_insert(info,keyinfo,key,leaf_buff,endpos,keybuff,
  264.        (uchar*) 0,(uchar*) 0,0L);
  265. }
  266.       }
  267.       if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff))
  268. goto err;
  269.     }
  270.     my_afree((byte*) next_buff);
  271.     DBUG_RETURN(ret_value);
  272.   }
  273. /* Remove last key from leaf page */
  274.   putint(leaf_buff,key_start-leaf_buff,nod_flag);
  275.   if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff))
  276.     goto err;
  277. /* Place last key in ancestor page on deleted key position */
  278.   a_length=getint(anc_buff);
  279.   endpos=anc_buff+a_length;
  280.   VOID(_nisam_get_last_key(info,keyinfo,anc_buff,ret_key,keypos));
  281.   length=_nisam_get_pack_key_length(keyinfo,share->base.key_reflength,
  282.  keypos == endpos ? (uchar*) 0 : keypos,
  283.  ret_key,keybuff,&s_temp);
  284.   if (length > 0)
  285.     bmove_upp((byte*) endpos+length,(byte*) endpos,(uint) (endpos-keypos));
  286.   else
  287.     bmove(keypos,keypos-length, (int) (endpos-keypos)+length);
  288.   _nisam_store_key(keyinfo,keypos,&s_temp);
  289. /* Save pointer to next leaf */
  290.   VOID((*keyinfo->get_key)(keyinfo,share->base.key_reflength,&keypos,ret_key));
  291.   _nisam_kpointer(info,keypos - share->base.key_reflength,next_block);
  292.   putint(anc_buff,a_length+length,share->base.key_reflength);
  293.   DBUG_RETURN( getint(leaf_buff) <= (uint) keyinfo->base.block_length/2 );
  294. err:
  295.   DBUG_RETURN(-1);
  296. } /* del */
  297. /* Balances adjacent pages if underflow occours */
  298. static int underflow(register N_INFO *info, register N_KEYDEF *keyinfo,
  299.      uchar *anc_buff,
  300.      ulong leaf_page, /* Ancestor page and underflow page */
  301.      uchar *leaf_buff,
  302.      uchar *keypos) /* Position to pos after key */
  303. {
  304.   int t_length;
  305.   uint length,anc_length,buff_length,leaf_length,p_length,s_length,nod_flag;
  306.   ulong next_page;
  307.   uchar anc_key[N_MAX_KEY_BUFF],leaf_key[N_MAX_KEY_BUFF],
  308. *buff,*endpos,*next_keypos,*half_pos,*temp_pos;
  309.   S_PARAM s_temp;
  310.   ISAM_SHARE *share=info->s;
  311.   DBUG_ENTER("underflow");
  312.   DBUG_PRINT("enter",("leaf_page: %ld   keypos: %lx",leaf_page,keypos));
  313.   DBUG_DUMP("anc_buff",(byte*) anc_buff,getint(anc_buff));
  314.   DBUG_DUMP("leaf_buff",(byte*) leaf_buff,getint(leaf_buff));
  315.   buff=info->buff;
  316.   next_keypos=keypos;
  317.   nod_flag=test_if_nod(leaf_buff);
  318.   p_length=2+nod_flag;
  319.   anc_length=getint(anc_buff);
  320.   leaf_length=getint(leaf_buff);
  321.   info->page_changed=1;
  322.   if ((keypos < anc_buff+anc_length && (share->rnd++ & 1)) ||
  323.       keypos == anc_buff+2+share->base.key_reflength)
  324.   { /* Use page right of anc-page */
  325.     DBUG_PRINT("test",("use right page"));
  326.     VOID((*keyinfo->get_key)(keyinfo,share->base.key_reflength,&next_keypos,
  327.      buff));
  328.     next_page= _nisam_kpos(share->base.key_reflength,next_keypos);
  329.     if (!_nisam_fetch_keypage(info,keyinfo,next_page,buff,0))
  330.       goto err;
  331.     buff_length=getint(buff);
  332.     DBUG_DUMP("next",(byte*) buff,buff_length);
  333.     /* find keys to make a big key-page */
  334.     bmove((byte*) next_keypos-share->base.key_reflength,(byte*) buff+2,
  335.   share->base.key_reflength);
  336.     VOID(_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,next_keypos));
  337.     VOID(_nisam_get_last_key(info,keyinfo,leaf_buff,leaf_key,
  338.   leaf_buff+leaf_length));
  339.     /* merge pages and put parting key from anc_buff between */
  340.     t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag,buff+p_length,
  341.    (leaf_length == nod_flag+2 ?
  342.     (uchar*) 0 : leaf_key),
  343.    anc_key,&s_temp);
  344.     length=buff_length-p_length;
  345.     endpos=buff+length+leaf_length+t_length;
  346.     bmove_upp((byte*) endpos, (byte*) buff+buff_length,length);
  347.     memcpy((byte*) buff, (byte*) leaf_buff,(size_t) leaf_length);
  348.     _nisam_store_key(keyinfo,buff+leaf_length,&s_temp);
  349.     buff_length=(uint) (endpos-buff);
  350.     putint(buff,buff_length,nod_flag);
  351.     /* remove key from anc_buff */
  352.     s_length=remove_key(keyinfo,share->base.key_reflength,keypos,anc_key,
  353. anc_buff+anc_length);
  354.     putint(anc_buff,(anc_length-=s_length),share->base.key_reflength);
  355.     if (buff_length <= keyinfo->base.block_length)
  356.     { /* Keys in one page */
  357.       memcpy((byte*) leaf_buff,(byte*) buff,(size_t) buff_length);
  358.       if (_nisam_dispose(info,keyinfo,next_page))
  359.        goto err;
  360.     }
  361.     else
  362.     { /* Page is full */
  363.       VOID(_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,keypos));
  364.       half_pos=_nisam_find_half_pos(info,keyinfo,buff,leaf_key);
  365.       length=(uint) (half_pos-buff);
  366.       memcpy((byte*) leaf_buff,(byte*) buff,(size_t) length);
  367.       putint(leaf_buff,length,nod_flag);
  368.       endpos=anc_buff+anc_length;
  369.       /* Correct new keypointer to leaf_page */
  370.       length=(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key);
  371.       _nisam_kpointer(info,leaf_key+length,next_page);
  372.       /* Save key in anc_buff */
  373.       t_length=(int) _nisam_get_pack_key_length(keyinfo,
  374. share->base.key_reflength,
  375. keypos == endpos ?
  376. (uchar*) 0 : keypos,
  377. anc_key,leaf_key,&s_temp);
  378.       if (t_length >= 0)
  379. bmove_upp((byte*) endpos+t_length,(byte*) endpos,
  380.   (uint) (endpos-keypos));
  381.       else
  382. bmove(keypos,keypos-t_length,(uint) (endpos-keypos)+t_length);
  383.       _nisam_store_key(keyinfo,keypos,&s_temp);
  384.       putint(anc_buff,(anc_length+=t_length),share->base.key_reflength);
  385. /* Store new page */
  386.       if (nod_flag)
  387. bmove((byte*) buff+2,(byte*) half_pos-nod_flag,(size_t) nod_flag);
  388.       VOID((*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key));
  389.       t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag,(uchar*) 0,
  390.      (uchar*) 0, leaf_key,&s_temp);
  391.       s_temp.n_length= *half_pos; /* For _nisam_store_key */
  392.       length=(uint) ((buff+getint(buff))-half_pos);
  393.       bmove((byte*) buff+p_length+t_length,(byte*) half_pos,(size_t) length);
  394.       _nisam_store_key(keyinfo,buff+p_length,&s_temp);
  395.       putint(buff,length+t_length+p_length,nod_flag);
  396.       if (_nisam_write_keypage(info,keyinfo,next_page,buff))
  397. goto err;
  398.     }
  399.     if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff))
  400.       goto err;
  401.     DBUG_RETURN(anc_length <= (uint) keyinfo->base.block_length/2);
  402.   }
  403.   DBUG_PRINT("test",("use left page"));
  404.   keypos=_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,keypos);
  405.   next_page= _nisam_kpos(share->base.key_reflength,keypos);
  406.   if (!_nisam_fetch_keypage(info,keyinfo,next_page,buff,0))
  407.       goto err;
  408.   buff_length=getint(buff);
  409.   endpos=buff+buff_length;
  410.   DBUG_DUMP("prev",(byte*) buff,buff_length);
  411.   /* find keys to make a big key-page */
  412.   bmove((byte*) next_keypos - share->base.key_reflength,(byte*) leaf_buff+2,
  413. share->base.key_reflength);
  414.   next_keypos=keypos;
  415.   VOID((*keyinfo->get_key)(keyinfo,share->base.key_reflength,&next_keypos,
  416.    anc_key));
  417.   VOID(_nisam_get_last_key(info,keyinfo,buff,leaf_key,endpos));
  418.   /* merge pages and put parting key from anc_buff between */
  419.   t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag,
  420.     leaf_buff+p_length,
  421.     (leaf_length == nod_flag+2 ?
  422.      (uchar*) 0 : leaf_key),
  423.     anc_key,&s_temp);
  424.   if (t_length >= 0)
  425.     bmove((byte*) endpos+t_length,(byte*) leaf_buff+p_length,
  426.     (size_t) (leaf_length-p_length));
  427.   else /* We gained space */
  428.     bmove((byte*) endpos,(byte*) leaf_buff+((int) p_length-t_length),
  429.     (size_t) (leaf_length-p_length+t_length));
  430.   _nisam_store_key(keyinfo,endpos,&s_temp);
  431.   buff_length=buff_length+leaf_length-p_length+t_length;
  432.   putint(buff,buff_length,nod_flag);
  433.   /* remove key from anc_buff */
  434.   s_length=remove_key(keyinfo,share->base.key_reflength,keypos,anc_key,
  435.       anc_buff+anc_length);
  436.   putint(anc_buff,(anc_length-=s_length),share->base.key_reflength);
  437.   if (buff_length <= keyinfo->base.block_length)
  438.   { /* Keys in one page */
  439.     if (_nisam_dispose(info,keyinfo,leaf_page))
  440.       goto err;
  441.   }
  442.   else
  443.   { /* Page is full */
  444.     VOID(_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,keypos));
  445.     endpos=half_pos=_nisam_find_half_pos(info,keyinfo,buff,leaf_key);
  446.     /* Correct new keypointer to leaf_page */
  447.     length=(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key);
  448.     _nisam_kpointer(info,leaf_key+length,leaf_page);
  449.     /* Save key in anc_buff */
  450.     DBUG_DUMP("anc_buff",(byte*) anc_buff,anc_length);
  451.     DBUG_DUMP("key",(byte*) leaf_key,16);
  452.     temp_pos=anc_buff+anc_length;
  453.     t_length=(int) _nisam_get_pack_key_length(keyinfo,
  454.       share->base.key_reflength,
  455.       keypos == temp_pos ? (uchar*) 0
  456.       : keypos,
  457.       anc_key,leaf_key,&s_temp);
  458.     if (t_length > 0)
  459.       bmove_upp((byte*) temp_pos+t_length,(byte*) temp_pos,
  460. (uint) (temp_pos-keypos));
  461.     else
  462.       bmove(keypos,keypos-t_length,(uint) (temp_pos-keypos)+t_length);
  463.     _nisam_store_key(keyinfo,keypos,&s_temp);
  464.     putint(anc_buff,(anc_length+=t_length),share->base.key_reflength);
  465.     /* Store new page */
  466.     if (nod_flag)
  467.       bmove((byte*) leaf_buff+2,(byte*) half_pos-nod_flag,(size_t) nod_flag);
  468.     VOID((*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key));
  469.     t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag, (uchar*) 0,
  470.    (uchar*) 0, leaf_key, &s_temp);
  471.     s_temp.n_length= *half_pos; /* For _nisam_store_key */
  472.     length=(uint) ((buff+buff_length)-half_pos);
  473.     bmove((byte*) leaf_buff+p_length+t_length,(byte*) half_pos,
  474.     (size_t) length);
  475.     _nisam_store_key(keyinfo,leaf_buff+p_length,&s_temp);
  476.     putint(leaf_buff,length+t_length+p_length,nod_flag);
  477.     putint(buff,endpos-buff,nod_flag);
  478.     if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff))
  479. goto err;
  480.   }
  481.   if (_nisam_write_keypage(info,keyinfo,next_page,buff))
  482.     goto err;
  483.   DBUG_RETURN(anc_length <= (uint) keyinfo->base.block_length/2);
  484. err:
  485.   DBUG_RETURN(-1);
  486. } /* underflow */
  487. /* remove a key from packed buffert */
  488. /* returns how many chars was removed */
  489. static uint remove_key(N_KEYDEF *keyinfo, uint nod_flag,
  490.        uchar *keypos, /* Where key starts */
  491.        uchar *lastkey, /* key to be removed */
  492.        uchar *page_end) /* End of page */
  493. {
  494.   int r_length,s_length,first,diff_flag;
  495.   uchar *start;
  496.   DBUG_ENTER("remove_key");
  497.   DBUG_PRINT("enter",("keypos: %lx  page_end: %lx",keypos,page_end));
  498.   start=keypos;
  499.   if (!(keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED)))
  500.     s_length=(int) (keyinfo->base.keylength+nod_flag);
  501.   else
  502.   {  /* Let keypos point at next key */
  503.     VOID((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey));
  504.     s_length=(uint) (keypos-start);
  505.     if (keyinfo->base.flag & HA_PACK_KEY)
  506.     {
  507.       diff_flag= (keyinfo->seg[0].base.flag & HA_SPACE_PACK);
  508.       first= *start;
  509.       if (keypos != page_end && *keypos & 128 && first != 128)
  510.       { /* Referens length */
  511. if ((r_length= *keypos++ & 127) == 0)
  512. { /* Same key after */
  513.   if (first & 128)
  514.     start++; /* Skip ref length */
  515.   if (diff_flag)
  516.     start+= *start+1; /* Skip key length */
  517.   else
  518.     start+=keyinfo->seg[0].base.length- (first & 127);
  519.   s_length=(uint)(keypos-start); /* Remove pntrs and next-key-flag */
  520. }
  521. else if (! (first & 128))
  522. { /* Deleted key was not compressed */
  523.   if (diff_flag)
  524.   {
  525.     *start= (uchar) (r_length+ *keypos);
  526.     start+=r_length+1; /* Let ref-part remain */
  527.     s_length=(uint) (keypos-start)+1; /* Skip everything between */
  528.   }
  529.   else
  530.   {
  531.     start+=r_length+1; /* Let ref-part remain */
  532.     s_length=(uint) (keypos-start); /* Skip everything between */
  533.   }
  534. }
  535. else if ((first & 127) < r_length)
  536. { /* mid-part of key is used */
  537.   r_length-=(first & 127);
  538.   start++; /* Ref remains the same */
  539.   if (diff_flag)
  540.     *start++= (uchar) (*keypos++ + r_length);
  541.   start+= r_length;
  542.   s_length=(uint) (keypos-start); /* Skip everything between */
  543. }
  544.       }
  545.     }
  546.   }
  547.   bmove((byte*) start,(byte*) start+s_length,
  548. (uint) (page_end-start-s_length));
  549.   DBUG_RETURN((uint) s_length);
  550. } /* remove_key */