hp_hash.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. /* The hash functions used for saveing keys */
  14. #include "heapdef.h"
  15. #include <m_ctype.h>
  16. /*
  17.   Find out how many rows there is in the given range
  18.   SYNOPSIS
  19.     hp_rb_records_in_range()
  20.     info HEAP handler
  21.     inx Index to use
  22.     min_key Min key. Is = 0 if no min range
  23.     max_key Max key. Is = 0 if no max range
  24.   NOTES
  25.     min_key.flag can have one of the following values:
  26.       HA_READ_KEY_EXACT Include the key in the range
  27.       HA_READ_AFTER_KEY Don't include key in range
  28.     max_key.flag can have one of the following values:  
  29.       HA_READ_BEFORE_KEY Don't include key in range
  30.       HA_READ_AFTER_KEY Include all 'end_key' values in the range
  31.   RETURN
  32.    HA_POS_ERROR Something is wrong with the index tree.
  33.    0 There is no matching keys in the given range
  34.    number > 0 There is approximately 'number' matching rows in
  35. the range.
  36. */
  37. ha_rows hp_rb_records_in_range(HP_INFO *info, int inx,  key_range *min_key,
  38.                                key_range *max_key)
  39. {
  40.   ha_rows start_pos, end_pos;
  41.   HP_KEYDEF *keyinfo= info->s->keydef + inx;
  42.   TREE *rb_tree = &keyinfo->rb_tree;
  43.   heap_rb_param custom_arg;
  44.   DBUG_ENTER("hp_rb_records_in_range");
  45.   info->lastinx= inx;
  46.   custom_arg.keyseg= keyinfo->seg;
  47.   custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
  48.   if (min_key)
  49.   {
  50.     custom_arg.key_length= hp_rb_pack_key(keyinfo, (uchar*) info->recbuf,
  51.   (uchar*) min_key->key,
  52.   min_key->length);
  53.     start_pos= tree_record_pos(rb_tree, info->recbuf, min_key->flag,
  54.        &custom_arg);
  55.   }
  56.   else
  57.   {
  58.     start_pos= 0;
  59.   }
  60.   
  61.   if (max_key)
  62.   {
  63.     custom_arg.key_length= hp_rb_pack_key(keyinfo, (uchar*) info->recbuf,
  64.   (uchar*) max_key->key,
  65.                                           max_key->length);
  66.     end_pos= tree_record_pos(rb_tree, info->recbuf, max_key->flag,
  67.      &custom_arg);
  68.   }
  69.   else
  70.   {
  71.     end_pos= rb_tree->elements_in_tree + (ha_rows)1;
  72.   }
  73.   DBUG_PRINT("info",("start_pos: %lu  end_pos: %lu", (ulong) start_pos,
  74.      (ulong) end_pos));
  75.   if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
  76.     DBUG_RETURN(HA_POS_ERROR);
  77.   DBUG_RETURN(end_pos < start_pos ? (ha_rows) 0 :
  78.       (end_pos == start_pos ? (ha_rows) 1 : end_pos - start_pos));
  79. }
  80. /* Search after a record based on a key */
  81. /* Sets info->current_ptr to found record */
  82. /* next_flag:  Search=0, next=1, prev =2, same =3 */
  83. byte *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
  84.                 uint nextflag)
  85. {
  86.   reg1 HASH_INFO *pos,*prev_ptr;
  87.   int flag;
  88.   uint old_nextflag;
  89.   HP_SHARE *share=info->s;
  90.   DBUG_ENTER("hp_search");
  91.   old_nextflag=nextflag;
  92.   flag=1;
  93.   prev_ptr=0;
  94.   if (share->records)
  95.   {
  96.     pos=hp_find_hash(&keyinfo->block, hp_mask(hp_hashnr(keyinfo, key),
  97.       share->blength, share->records));
  98.     do
  99.     {
  100.       if (!hp_key_cmp(keyinfo, pos->ptr_to_rec, key))
  101.       {
  102. switch (nextflag) {
  103. case 0: /* Search after key */
  104.   DBUG_PRINT("exit",("found key at %d",pos->ptr_to_rec));
  105.   info->current_hash_ptr=pos;
  106.   DBUG_RETURN(info->current_ptr= pos->ptr_to_rec);
  107. case 1: /* Search next */
  108.   if (pos->ptr_to_rec == info->current_ptr)
  109.     nextflag=0;
  110.   break;
  111. case 2: /* Search previous */
  112.   if (pos->ptr_to_rec == info->current_ptr)
  113.   {
  114.     my_errno=HA_ERR_KEY_NOT_FOUND; /* If gpos == 0 */
  115.     info->current_hash_ptr=prev_ptr;
  116.     DBUG_RETURN(info->current_ptr=prev_ptr ? prev_ptr->ptr_to_rec : 0);
  117.   }
  118.   prev_ptr=pos; /* Prev. record found */
  119.   break;
  120. case 3: /* Search same */
  121.   if (pos->ptr_to_rec == info->current_ptr)
  122.   {
  123.     info->current_hash_ptr=pos;
  124.     DBUG_RETURN(info->current_ptr);
  125.   }
  126. }
  127.       }
  128.       if (flag)
  129.       {
  130. flag=0; /* Reset flag */
  131. if (hp_find_hash(&keyinfo->block,
  132.  hp_mask(hp_rec_hashnr(keyinfo, pos->ptr_to_rec),
  133.   share->blength, share->records)) != pos)
  134.   break; /* Wrong link */
  135.       }
  136.     }
  137.     while ((pos=pos->next_key));
  138.   }
  139.   my_errno=HA_ERR_KEY_NOT_FOUND;
  140.   if (nextflag == 2 && ! info->current_ptr)
  141.   {
  142.     /* Do a previous from end */
  143.     info->current_hash_ptr=prev_ptr;
  144.     DBUG_RETURN(info->current_ptr=prev_ptr ? prev_ptr->ptr_to_rec : 0);
  145.   }
  146.   if (old_nextflag && nextflag)
  147.     my_errno=HA_ERR_RECORD_CHANGED; /* Didn't find old record */
  148.   DBUG_PRINT("exit",("Error: %d",my_errno));
  149.   info->current_hash_ptr=0;  
  150.   DBUG_RETURN((info->current_ptr= 0));
  151. }
  152. /*
  153.   Search next after last read;  Assumes that the table hasn't changed
  154.   since last read !
  155. */
  156. byte *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
  157.       HASH_INFO *pos)
  158. {
  159.   DBUG_ENTER("hp_search_next");
  160.   while ((pos= pos->next_key))
  161.   {
  162.     if (! hp_key_cmp(keyinfo, pos->ptr_to_rec, key))
  163.     {
  164.       info->current_hash_ptr=pos;
  165.       DBUG_RETURN (info->current_ptr= pos->ptr_to_rec);
  166.     }
  167.   }
  168.   my_errno=HA_ERR_KEY_NOT_FOUND;
  169.   DBUG_PRINT("exit",("Error: %d",my_errno));
  170.   info->current_hash_ptr=0;
  171.   DBUG_RETURN ((info->current_ptr= 0));
  172. }
  173. /*
  174.   Calculate position number for hash value.
  175.   SYNOPSIS
  176.     hp_mask()
  177.       hashnr     Hash value
  178.       buffmax    Value such that
  179.                  2^(n-1) < maxlength <= 2^n = buffmax
  180.       maxlength  
  181.   
  182.   RETURN
  183.     Array index, in [0..maxlength)
  184. */
  185. ulong hp_mask(ulong hashnr, ulong buffmax, ulong maxlength)
  186. {
  187.   if ((hashnr & (buffmax-1)) < maxlength) return (hashnr & (buffmax-1));
  188.   return (hashnr & ((buffmax >> 1) -1));
  189. }
  190. /*
  191.   Change
  192.     next_link -> ... -> X -> pos
  193.   to
  194.     next_link -> ... -> X -> newlink
  195. */
  196. void hp_movelink(HASH_INFO *pos, HASH_INFO *next_link, HASH_INFO *newlink)
  197. {
  198.   HASH_INFO *old_link;
  199.   do
  200.   {
  201.     old_link=next_link;
  202.   }
  203.   while ((next_link=next_link->next_key) != pos);
  204.   old_link->next_key=newlink;
  205.   return;
  206. }
  207. #ifndef NEW_HASH_FUNCTION
  208. /* Calc hashvalue for a key */
  209. ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
  210. {
  211.   /*register*/ 
  212.   ulong nr=1, nr2=4;
  213.   HA_KEYSEG *seg,*endseg;
  214.   for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
  215.   {
  216.     uchar *pos=(uchar*) key;
  217.     key+=seg->length;
  218.     if (seg->null_bit)
  219.     {
  220.       key++; /* Skip null byte */
  221.       if (*pos) /* Found null */
  222.       {
  223. nr^= (nr << 1) | 1;
  224. continue;
  225.       }
  226.       pos++;
  227.     }
  228.     if (seg->type == HA_KEYTYPE_TEXT)
  229.     {
  230.        CHARSET_INFO *cs= seg->charset;
  231.        uint char_length= (uint) ((uchar*) key - pos);
  232.        if (cs->mbmaxlen > 1)
  233.        {
  234.          uint length= char_length;
  235.          char_length= my_charpos(cs, pos, pos + length, length/cs->mbmaxlen);
  236.          set_if_smaller(char_length, length);   /* QQ: ok to remove? */
  237.        }
  238.        cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
  239.     }
  240.     else
  241.     {
  242.       for (; pos < (uchar*) key ; pos++)
  243.       {
  244. nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) *pos)) + (nr << 8);
  245. nr2+=3;
  246.       }
  247.     }
  248.   }
  249.   return((ulong) nr);
  250. }
  251. /* Calc hashvalue for a key in a record */
  252. ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
  253. {
  254.   /*register*/
  255.   ulong nr=1, nr2=4;
  256.   HA_KEYSEG *seg,*endseg;
  257.   for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
  258.   {
  259.     uchar *pos=(uchar*) rec+seg->start,*end=pos+seg->length;
  260.     if (seg->null_bit)
  261.     {
  262.       if (rec[seg->null_pos] & seg->null_bit)
  263.       {
  264. nr^= (nr << 1) | 1;
  265. continue;
  266.       }
  267.     }
  268.     if (seg->type == HA_KEYTYPE_TEXT)
  269.     {
  270.       CHARSET_INFO *cs= seg->charset;
  271.       uint char_length= seg->length;
  272.       if (cs->mbmaxlen > 1)
  273.       {
  274.         char_length= my_charpos(cs, pos, pos + char_length,
  275.                                 char_length / cs->mbmaxlen);
  276.         set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
  277.       }
  278.       cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
  279.     }
  280.     else
  281.     {
  282.       for (; pos < end ; pos++)
  283.       {
  284. nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) *pos))+ (nr << 8);
  285. nr2+=3;
  286.       }
  287.     }
  288.   }
  289.   return((ulong) nr);
  290. }
  291. #else
  292. /*
  293.  * Fowler/Noll/Vo hash
  294.  *
  295.  * The basis of the hash algorithm was taken from an idea sent by email to the
  296.  * IEEE Posix P1003.2 mailing list from Phong Vo (kpv@research.att.com) and
  297.  * Glenn Fowler (gsf@research.att.com).  Landon Curt Noll (chongo@toad.com)
  298.  * later improved on their algorithm.
  299.  *
  300.  * The magic is in the interesting relationship between the special prime
  301.  * 16777619 (2^24 + 403) and 2^32 and 2^8.
  302.  *
  303.  * This hash produces the fewest collisions of any function that we've seen so
  304.  * far, and works well on both numbers and strings.
  305.  */
  306. ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
  307. {
  308.   register ulong nr=0;
  309.   HA_KEYSEG *seg,*endseg;
  310.   for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
  311.   {
  312.     uchar *pos=(uchar*) key;
  313.     key+=seg->length;
  314.     if (seg->null_bit)
  315.     {
  316.       key++;
  317.       if (*pos)
  318.       {
  319. nr^= (nr << 1) | 1;
  320. continue;
  321.       }
  322.       pos++;
  323.     }
  324.     if (seg->type == HA_KEYTYPE_TEXT)
  325.     {
  326.       seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
  327.     }
  328.     else
  329.     {
  330.       for ( ; pos < (uchar*) key ; pos++)
  331.       {
  332. nr *=16777619; 
  333. nr ^=(uint) *pos;
  334.       }
  335.     }
  336.   }
  337.   return((ulong) nr);
  338. }
  339. /* Calc hashvalue for a key in a record */
  340. ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
  341. {
  342.   register ulong nr=0;
  343.   HA_KEYSEG *seg,*endseg;
  344.   for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
  345.   {
  346.     uchar *pos=(uchar*) rec+seg->start,*end=pos+seg->length;
  347.     if (seg->null_bit)
  348.     {
  349.       if (rec[seg->null_pos] & seg->null_bit)
  350.       {
  351. nr^= (nr << 1) | 1;
  352. continue;
  353.       }
  354.     }
  355.     if (seg->type == HA_KEYTYPE_TEXT)
  356.     {
  357.       seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
  358.     }
  359.     else
  360.     {
  361.       for ( ; pos < end ; pos++)
  362.       {
  363. nr *=16777619; 
  364. nr ^=(uint) *pos;
  365.       }
  366.     }
  367.   }
  368.   return((ulong) nr);
  369. }
  370. #endif
  371. /* Compare keys for two records. Returns 0 if they are identical */
  372. int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
  373. {
  374.   HA_KEYSEG *seg,*endseg;
  375.   for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
  376.   {
  377.     if (seg->null_bit)
  378.     {
  379.       if ((rec1[seg->null_pos] & seg->null_bit) !=
  380.   (rec2[seg->null_pos] & seg->null_bit))
  381. return 1;
  382.       if (rec1[seg->null_pos] & seg->null_bit)
  383. continue;
  384.     }
  385.     if (seg->type == HA_KEYTYPE_TEXT)
  386.     {
  387.       CHARSET_INFO *cs= seg->charset;
  388.       uint char_length1;
  389.       uint char_length2;
  390.       uchar *pos1= (uchar*)rec1 + seg->start;
  391.       uchar *pos2= (uchar*)rec2 + seg->start;
  392.       if (cs->mbmaxlen > 1)
  393.       {
  394.         uint char_length= seg->length / cs->mbmaxlen;
  395.         char_length1= my_charpos(cs, pos1, pos1 + seg->length, char_length);
  396.         set_if_smaller(char_length1, seg->length); /* QQ: ok to remove? */
  397.         char_length2= my_charpos(cs, pos2, pos2 + seg->length, char_length);
  398.         set_if_smaller(char_length2, seg->length); /* QQ: ok to remove? */
  399.       }
  400.       else
  401.       {
  402.         char_length1= char_length2= seg->length;
  403.       }
  404.       if (seg->charset->coll->strnncollsp(seg->charset,
  405.          pos1,char_length1,
  406.   pos2,char_length2))
  407. return 1;
  408.     }
  409.     else
  410.     {
  411.       if (bcmp(rec1+seg->start,rec2+seg->start,seg->length))
  412. return 1;
  413.     }
  414.   }
  415.   return 0;
  416. }
  417. /* Compare a key in a record to a whole key */
  418. int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
  419. {
  420.   HA_KEYSEG *seg,*endseg;
  421.   for (seg=keydef->seg,endseg=seg+keydef->keysegs ;
  422.        seg < endseg ;
  423.        key+= (seg++)->length)
  424.   {
  425.     if (seg->null_bit)
  426.     {
  427.       int found_null=test(rec[seg->null_pos] & seg->null_bit);
  428.       if (found_null != (int) *key++)
  429. return 1;
  430.       if (found_null)
  431. continue;
  432.     }
  433.     if (seg->type == HA_KEYTYPE_TEXT)
  434.     {
  435.       CHARSET_INFO *cs= seg->charset;
  436.       uint char_length_key;
  437.       uint char_length_rec;
  438.       uchar *pos= (uchar*) rec + seg->start;
  439.       if (cs->mbmaxlen > 1)
  440.       {
  441.         uint char_length= seg->length / cs->mbmaxlen;
  442.         char_length_key= my_charpos(cs, key, key + seg->length, char_length);
  443.         set_if_smaller(char_length_key, seg->length);
  444.         char_length_rec= my_charpos(cs, pos, pos + seg->length, char_length);
  445.         set_if_smaller(char_length_rec, seg->length);
  446.       }
  447.       else
  448.       {
  449.         char_length_key= seg->length;
  450.         char_length_rec= seg->length;
  451.       }
  452.       
  453.       if (seg->charset->coll->strnncollsp(seg->charset,
  454.   (uchar*) pos, char_length_rec,
  455.   (uchar*) key, char_length_key))
  456. return 1;
  457.     }
  458.     else
  459.     {
  460.       if (bcmp(rec+seg->start,key,seg->length))
  461. return 1;
  462.     }
  463.   }
  464.   return 0;
  465. }
  466. /* Copy a key from a record to a keybuffer */
  467. void hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
  468. {
  469.   HA_KEYSEG *seg,*endseg;
  470.   for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
  471.   {
  472.     CHARSET_INFO *cs= seg->charset;
  473.     uint char_length= seg->length;
  474.     uchar *pos= (uchar*) rec + seg->start;
  475.     if (seg->null_bit)
  476.       *key++= test(rec[seg->null_pos] & seg->null_bit);
  477.     if (cs->mbmaxlen > 1)
  478.     {
  479.       char_length= my_charpos(cs, pos, pos + seg->length,
  480.                               char_length / cs->mbmaxlen);
  481.       set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
  482.     }
  483.     memcpy(key,rec+seg->start,(size_t) char_length);
  484.     key+= char_length;
  485.   }
  486. }
  487. uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key, 
  488.     const byte *rec, byte *recpos)
  489. {
  490.   byte *start_key= key;
  491.   HA_KEYSEG *seg, *endseg;
  492.   for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
  493.   {
  494.     uint char_length;
  495.     if (seg->null_bit)
  496.     {
  497.       if (!(*key++= 1 - test(rec[seg->null_pos] & seg->null_bit)))
  498.         continue;
  499.     }
  500.     if (seg->flag & HA_SWAP_KEY)
  501.     {
  502.       uint length= seg->length;
  503.       byte *pos= (byte*) rec + seg->start;
  504.       
  505. #ifdef HAVE_ISNAN
  506.       if (seg->type == HA_KEYTYPE_FLOAT)
  507.       {
  508. float nr;
  509. float4get(nr, pos);
  510. if (isnan(nr))
  511. {
  512.   /* Replace NAN with zero */
  513.     bzero(key, length);
  514.   key+= length;
  515.   continue;
  516. }
  517.       }
  518.       else if (seg->type == HA_KEYTYPE_DOUBLE)
  519.       {
  520. double nr;
  521. float8get(nr, pos);
  522. if (isnan(nr))
  523. {
  524.     bzero(key, length);
  525.   key+= length;
  526.   continue;
  527. }
  528.       }
  529. #endif
  530.       pos+= length;
  531.       while (length--)
  532.       {
  533. *key++= *--pos;
  534.       }
  535.       continue;
  536.     }
  537.     char_length= seg->length;
  538.     if (seg->charset->mbmaxlen > 1)
  539.     {
  540.       char_length= my_charpos(seg->charset, 
  541.                               rec + seg->start, rec + seg->start + char_length,
  542.                               char_length / seg->charset->mbmaxlen);
  543.       set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
  544.       if (char_length < seg->length)
  545.         seg->charset->cset->fill(seg->charset, (char*) key + char_length, 
  546.                                  seg->length - char_length, ' ');
  547.     }
  548.     memcpy(key, rec + seg->start, (size_t) char_length);
  549.     key+= seg->length;
  550.   }
  551.   memcpy(key, &recpos, sizeof(byte*));
  552.   return key - start_key;
  553. }
  554. uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
  555.                     uint k_len)
  556. {
  557.   HA_KEYSEG *seg, *endseg;
  558.   uchar *start_key= key;
  559.   
  560.   for (seg= keydef->seg, endseg= seg + keydef->keysegs;
  561.        seg < endseg && (int) k_len > 0; old+= seg->length, seg++)
  562.   {
  563.     uint char_length;
  564.     if (seg->null_bit)
  565.     {
  566.       k_len--;
  567.       if (!(*key++= (char) 1 - *old++))
  568.       {
  569.         k_len-= seg->length;
  570.         continue;
  571.       }
  572.     }
  573.     if (seg->flag & HA_SWAP_KEY)
  574.     {
  575.       uint length= seg->length;
  576.       byte *pos= (byte*) old + length;
  577.       
  578.       k_len-= length;
  579.       while (length--)
  580.       {
  581. *key++= *--pos;
  582.       }
  583.       continue;
  584.     }
  585.     char_length= seg->length;
  586.     if (seg->charset->mbmaxlen > 1)
  587.     {
  588.       char_length= my_charpos(seg->charset, old, old+char_length,
  589.                               char_length / seg->charset->mbmaxlen);
  590.       set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
  591.       if (char_length < seg->length)
  592.         seg->charset->cset->fill(seg->charset, (char*) key + char_length, 
  593.                                  seg->length - char_length, ' ');
  594.     }
  595.     memcpy(key, old, (size_t) char_length);
  596.     key+= seg->length;
  597.     k_len-= seg->length;
  598.   }
  599.   return key - start_key;
  600. }
  601. uint hp_rb_key_length(HP_KEYDEF *keydef, 
  602.       const byte *key __attribute__((unused)))
  603. {
  604.   return keydef->length;
  605. }
  606. uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key)
  607. {
  608.   const byte *start_key= key;
  609.   HA_KEYSEG *seg, *endseg;
  610.   
  611.   for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
  612.   {
  613.     if (seg->null_bit && !*key++)
  614.       continue;
  615.     key+= seg->length;
  616.   }
  617.   return key - start_key;
  618. }
  619.                   
  620. /*
  621.   Test if any of the key parts are NULL.
  622.   Return:
  623.     1 if any of the key parts was NULL
  624.     0 otherwise
  625. */
  626. my_bool hp_if_null_in_key(HP_KEYDEF *keydef, const byte *record)
  627. {
  628.   HA_KEYSEG *seg,*endseg;
  629.   for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
  630.   {
  631.     if (seg->null_bit && (record[seg->null_pos] & seg->null_bit))
  632.       return 1;
  633.   }
  634.   return 0;
  635. }
  636. /*
  637.   Update auto_increment info
  638.   SYNOPSIS
  639.     update_auto_increment()
  640.     info MyISAM handler
  641.     record Row to update
  642.   IMPLEMENTATION
  643.     Only replace the auto_increment value if it is higher than the previous
  644.     one. For signed columns we don't update the auto increment value if it's
  645.     less than zero.
  646. */
  647. void heap_update_auto_increment(HP_INFO *info, const byte *record)
  648. {
  649.   ulonglong value= 0; /* Store unsigned values here */
  650.   longlong s_value= 0; /* Store signed values here */
  651.   HA_KEYSEG *keyseg= info->s->keydef[info->s->auto_key - 1].seg;
  652.   const uchar *key=  (uchar*) record + keyseg->start;
  653.   switch (info->s->auto_key_type) {
  654.   case HA_KEYTYPE_INT8:
  655.     s_value= (longlong) *(char*)key;
  656.     break;
  657.   case HA_KEYTYPE_BINARY:
  658.     value=(ulonglong)  *(uchar*) key;
  659.     break;
  660.   case HA_KEYTYPE_SHORT_INT:
  661.     s_value= (longlong) sint2korr(key);
  662.     break;
  663.   case HA_KEYTYPE_USHORT_INT:
  664.     value=(ulonglong) uint2korr(key);
  665.     break;
  666.   case HA_KEYTYPE_LONG_INT:
  667.     s_value= (longlong) sint4korr(key);
  668.     break;
  669.   case HA_KEYTYPE_ULONG_INT:
  670.     value=(ulonglong) uint4korr(key);
  671.     break;
  672.   case HA_KEYTYPE_INT24:
  673.     s_value= (longlong) sint3korr(key);
  674.     break;
  675.   case HA_KEYTYPE_UINT24:
  676.     value=(ulonglong) uint3korr(key);
  677.     break;
  678.   case HA_KEYTYPE_FLOAT:                        /* This shouldn't be used */
  679.   {
  680.     float f_1;
  681.     float4get(f_1,key);
  682.     /* Ignore negative values */
  683.     value = (f_1 < (float) 0.0) ? 0 : (ulonglong) f_1;
  684.     break;
  685.   }
  686.   case HA_KEYTYPE_DOUBLE:                       /* This shouldn't be used */
  687.   {
  688.     double f_1;
  689.     float8get(f_1,key);
  690.     /* Ignore negative values */
  691.     value = (f_1 < 0.0) ? 0 : (ulonglong) f_1;
  692.     break;
  693.   }
  694.   case HA_KEYTYPE_LONGLONG:
  695.     s_value= sint8korr(key);
  696.     break;
  697.   case HA_KEYTYPE_ULONGLONG:
  698.     value= uint8korr(key);
  699.     break;
  700.   default:
  701.     DBUG_ASSERT(0);
  702.     value=0;                                    /* Error */
  703.     break;
  704.   }
  705.   /*
  706.     The following code works becasue if s_value < 0 then value is 0
  707.     and if s_value == 0 then value will contain either s_value or the
  708.     correct value.
  709.   */
  710.   set_if_bigger(info->s->auto_increment,
  711.                 (s_value > 0) ? (ulonglong) s_value : value);
  712. }