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

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