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

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. /* Functions to handle keys */
  14. #include "myisamdef.h"
  15. #include "m_ctype.h"
  16. #include "sp_defs.h"
  17. #ifdef HAVE_IEEEFP_H
  18. #include <ieeefp.h>
  19. #endif
  20. #define CHECK_KEYS                              /* Enable safety checks */
  21. #define FIX_LENGTH(cs, pos, length, char_length)                            
  22.             do {                                                            
  23.               if (length > char_length)                                     
  24.                 char_length= my_charpos(cs, pos, pos+length, char_length);  
  25.               set_if_smaller(char_length,length);                           
  26.             } while(0)
  27. static int _mi_put_key_in_record(MI_INFO *info,uint keynr,byte *record);
  28. /*
  29. ** Make a intern key from a record
  30. ** Ret: Length of key
  31. */
  32. uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
  33.   const byte *record, my_off_t filepos)
  34. {
  35.   byte *pos,*end;
  36.   uchar *start;
  37.   reg1 HA_KEYSEG *keyseg;
  38.   my_bool is_ft= info->s->keyinfo[keynr].flag & HA_FULLTEXT;
  39.   DBUG_ENTER("_mi_make_key");
  40.   if (info->s->keyinfo[keynr].flag & HA_SPATIAL)
  41.   {
  42.     /*
  43.       TODO: nulls processing
  44.     */
  45. #ifdef HAVE_SPATIAL
  46.     return sp_make_key(info,keynr,key,record,filepos);
  47. #else
  48.     DBUG_ASSERT(0); /* mi_open should check that this never happens*/
  49. #endif
  50.   }
  51.   start=key;
  52.   for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++)
  53.   {
  54.     enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
  55.     uint length=keyseg->length;
  56.     uint char_length;
  57.     CHARSET_INFO *cs=keyseg->charset;
  58.     if (keyseg->null_bit)
  59.     {
  60.       if (record[keyseg->null_pos] & keyseg->null_bit)
  61.       {
  62. *key++= 0; /* NULL in key */
  63. continue;
  64.       }
  65.       *key++=1; /* Not NULL */
  66.     }
  67.     char_length= ((!is_ft && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen :
  68.                   length);
  69.     pos= (byte*) record+keyseg->start;
  70.     if (keyseg->flag & HA_SPACE_PACK)
  71.     {
  72.       end= pos + length;
  73.       if (type != HA_KEYTYPE_NUM)
  74.       {
  75. while (end > pos && end[-1] == ' ')
  76.   end--;
  77.       }
  78.       else
  79.       {
  80. while (pos < end && pos[0] == ' ')
  81.   pos++;
  82.       }
  83.       length=(uint) (end-pos);
  84.       FIX_LENGTH(cs, pos, length, char_length);
  85.       store_key_length_inc(key,char_length);
  86.       memcpy((byte*) key,(byte*) pos,(size_t) char_length);
  87.       key+=char_length;
  88.       continue;
  89.     }
  90.     if (keyseg->flag & HA_VAR_LENGTH)
  91.     {
  92.       uint tmp_length=uint2korr(pos);
  93.       pos+=2; /* Skip VARCHAR length */
  94.       set_if_smaller(length,tmp_length);
  95.       FIX_LENGTH(cs, pos, length, char_length);
  96.       store_key_length_inc(key,char_length);
  97.       memcpy((byte*) key,(byte*) pos,(size_t) char_length);
  98.       key+= char_length;
  99.       continue;
  100.     }
  101.     else if (keyseg->flag & HA_BLOB_PART)
  102.     {
  103.       uint tmp_length=_mi_calc_blob_length(keyseg->bit_start,pos);
  104.       memcpy_fixed((byte*) &pos,pos+keyseg->bit_start,sizeof(char*));
  105.       set_if_smaller(length,tmp_length);
  106.       FIX_LENGTH(cs, pos, length, char_length);
  107.       store_key_length_inc(key,char_length);
  108.       memcpy((byte*) key,(byte*) pos,(size_t) char_length);
  109.       key+= char_length;
  110.       continue;
  111.     }
  112.     else if (keyseg->flag & HA_SWAP_KEY)
  113.     { /* Numerical column */
  114. #ifdef HAVE_ISNAN
  115.       if (type == HA_KEYTYPE_FLOAT)
  116.       {
  117. float nr;
  118. float4get(nr,pos);
  119. if (isnan(nr))
  120. {
  121.   /* Replace NAN with zero */
  122.   bzero(key,length);
  123.   key+=length;
  124.   continue;
  125. }
  126.       }
  127.       else if (type == HA_KEYTYPE_DOUBLE)
  128.       {
  129. double nr;
  130. float8get(nr,pos);
  131. if (isnan(nr))
  132. {
  133.   bzero(key,length);
  134.   key+=length;
  135.   continue;
  136. }
  137.       }
  138. #endif
  139.       pos+=length;
  140.       while (length--)
  141.       {
  142. *key++ = *--pos;
  143.       }
  144.       continue;
  145.     }
  146.     FIX_LENGTH(cs, pos, length, char_length);
  147.     memcpy((byte*) key, pos, char_length);
  148.     if (length > char_length)
  149.       cs->cset->fill(cs, key+char_length, length-char_length, ' ');
  150.     key+= length;
  151.   }
  152.   _mi_dpointer(info,key,filepos);
  153.   DBUG_PRINT("exit",("keynr: %d",keynr));
  154.   DBUG_DUMP("key",(byte*) start,(uint) (key-start)+keyseg->length);
  155.   DBUG_EXECUTE("key",
  156.        _mi_print_key(DBUG_FILE,info->s->keyinfo[keynr].seg,start,
  157.      (uint) (key-start)););
  158.   DBUG_RETURN((uint) (key-start)); /* Return keylength */
  159. } /* _mi_make_key */
  160. /*
  161.   Pack a key to intern format from given format (c_rkey)
  162.   SYNOPSIS
  163.     _mi_pack_key()
  164.     info MyISAM handler
  165.     uint keynr key number
  166.     key Store packed key here
  167.     old Not packed key
  168.     k_length Length of 'old' to use
  169.     last_used_keyseg out parameter.  May be NULL
  170.    RETURN
  171.      length of packed key
  172.      last_use_keyseg    Store pointer to the keyseg after the last used one
  173. */
  174. uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
  175.   uint k_length, HA_KEYSEG **last_used_keyseg)
  176. {
  177.   uchar *start_key=key;
  178.   HA_KEYSEG *keyseg;
  179.   my_bool is_ft= info->s->keyinfo[keynr].flag & HA_FULLTEXT;
  180.   DBUG_ENTER("_mi_pack_key");
  181.   for (keyseg=info->s->keyinfo[keynr].seg ;
  182.        keyseg->type && (int) k_length > 0;
  183.        old+=keyseg->length, keyseg++)
  184.   {
  185.     enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
  186.     uint length=min((uint) keyseg->length,(uint) k_length);
  187.     uint char_length;
  188.     uchar *pos;
  189.     CHARSET_INFO *cs=keyseg->charset;
  190.     if (keyseg->null_bit)
  191.     {
  192.       k_length--;
  193.       if (!(*key++= (char) 1-*old++)) /* Copy null marker */
  194.       {
  195. k_length-=length;
  196.         if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
  197.         {
  198.           old+= 2;
  199.           k_length-=2;                                  /* Skip length */
  200.         }
  201. continue; /* Found NULL */
  202.       }
  203.     }
  204.     char_length= (!is_ft && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen : length;
  205.     pos=old;
  206.     if (keyseg->flag & HA_SPACE_PACK)
  207.     {
  208.       uchar *end=pos+length;
  209.       if (type != HA_KEYTYPE_NUM)
  210.       {
  211. while (end > pos && end[-1] == ' ')
  212.   end--;
  213.       }
  214.       else
  215.       {
  216. while (pos < end && pos[0] == ' ')
  217.   pos++;
  218.       }
  219.       k_length-=length;
  220.       length=(uint) (end-pos);
  221.       FIX_LENGTH(cs, pos, length, char_length);
  222.       store_key_length_inc(key,char_length);
  223.       memcpy((byte*) key,pos,(size_t) char_length);
  224.       key+= char_length;
  225.       continue;
  226.     }
  227.     else if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
  228.     {
  229.       /* Length of key-part used with mi_rkey() always 2 */
  230.       uint tmp_length=uint2korr(pos);
  231.       k_length-= 2+length;
  232.       pos+=2;
  233.       set_if_smaller(length,tmp_length); /* Safety */
  234.       FIX_LENGTH(cs, pos, length, char_length);
  235.       store_key_length_inc(key,char_length);
  236.       old+=2; /* Skip length */
  237.       memcpy((byte*) key, pos,(size_t) char_length);
  238.       key+= char_length;
  239.       continue;
  240.     }
  241.     else if (keyseg->flag & HA_SWAP_KEY)
  242.     { /* Numerical column */
  243.       pos+=length;
  244.       k_length-=length;
  245.       while (length--)
  246.       {
  247. *key++ = *--pos;
  248.       }
  249.       continue;
  250.     }
  251.     FIX_LENGTH(cs, pos, length, char_length);
  252.     memcpy((byte*) key, pos, char_length);
  253.     if (length > char_length)
  254.       cs->cset->fill(cs,key+char_length, length-char_length, ' ');
  255.     key+= length;
  256.     k_length-=length;
  257.   }
  258.   if (last_used_keyseg)
  259.     *last_used_keyseg= keyseg;
  260. #ifdef NOT_USED
  261.   if (keyseg->type)
  262.   {
  263.     /* Part-key ; fill with ASCII 0 for easier searching */
  264.     length= (uint) -k_length; /* unused part of last key */
  265.     do
  266.     {
  267.       if (keyseg->flag & HA_NULL_PART)
  268. length++;
  269.       if (keyseg->flag & HA_SPACE_PACK)
  270. length+=2;
  271.       else
  272. length+= keyseg->length;
  273.       keyseg++;
  274.     } while (keyseg->type);
  275.     bzero((byte*) key,length);
  276.     key+=length;
  277.   }
  278. #endif
  279.   DBUG_RETURN((uint) (key-start_key));
  280. } /* _mi_pack_key */
  281. /*
  282.   Store found key in record
  283.   SYNOPSIS
  284.     _mi_put_key_in_record()
  285.     info MyISAM handler
  286.     keynr Key number that was used
  287.     record  Store key here
  288.     Last read key is in info->lastkey
  289.  NOTES
  290.    Used when only-keyread is wanted
  291.  RETURN
  292.    0   ok
  293.    1   error
  294. */
  295. static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
  296.  byte *record)
  297. {
  298.   reg2 byte *key;
  299.   byte *pos,*key_end;
  300.   reg1 HA_KEYSEG *keyseg;
  301.   byte *blob_ptr;
  302.   DBUG_ENTER("_mi_put_key_in_record");
  303.   blob_ptr= info->lastkey2;                     /* Place to put blob parts */
  304.   key=(byte*) info->lastkey;                    /* KEy that was read */
  305.   key_end=key+info->lastkey_length;
  306.   for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++)
  307.   {
  308.     if (keyseg->null_bit)
  309.     {
  310.       if (!*key++)
  311.       {
  312. record[keyseg->null_pos]|= keyseg->null_bit;
  313. continue;
  314.       }
  315.       record[keyseg->null_pos]&= ~keyseg->null_bit;
  316.     }
  317.     if (keyseg->flag & HA_SPACE_PACK)
  318.     {
  319.       uint length;
  320.       get_key_length(length,key);
  321. #ifdef CHECK_KEYS
  322.       if (length > keyseg->length || key+length > key_end)
  323. goto err;
  324. #endif
  325.       pos= record+keyseg->start;
  326.       if (keyseg->type != (int) HA_KEYTYPE_NUM)
  327.       {
  328. memcpy(pos,key,(size_t) length);
  329. bfill(pos+length,keyseg->length-length,' ');
  330.       }
  331.       else
  332.       {
  333. bfill(pos,keyseg->length-length,' ');
  334. memcpy(pos+keyseg->length-length,key,(size_t) length);
  335.       }
  336.       key+=length;
  337.       continue;
  338.     }
  339.     if (keyseg->flag & HA_VAR_LENGTH)
  340.     {
  341.       uint length;
  342.       get_key_length(length,key);
  343. #ifdef CHECK_KEYS
  344.       if (length > keyseg->length || key+length > key_end)
  345. goto err;
  346. #endif
  347.       memcpy(record+keyseg->start,(byte*) key, length);
  348.       key+= length;
  349.     }
  350.     else if (keyseg->flag & HA_BLOB_PART)
  351.     {
  352.       uint length;
  353.       get_key_length(length,key);
  354. #ifdef CHECK_KEYS
  355.       if (length > keyseg->length || key+length > key_end)
  356. goto err;
  357. #endif
  358.       memcpy(record+keyseg->start+keyseg->bit_start,
  359.      (char*) &blob_ptr,sizeof(char*));
  360.       memcpy(blob_ptr,key,length);
  361.       blob_ptr+=length;
  362.       _my_store_blob_length(record+keyseg->start,
  363.     (uint) keyseg->bit_start,length);
  364.       key+=length;
  365.     }
  366.     else if (keyseg->flag & HA_SWAP_KEY)
  367.     {
  368.       byte *to=  record+keyseg->start+keyseg->length;
  369.       byte *end= key+keyseg->length;
  370. #ifdef CHECK_KEYS
  371.       if (end > key_end)
  372. goto err;
  373. #endif
  374.       do
  375.       {
  376.  *--to= *key++;
  377.       } while (key != end);
  378.       continue;
  379.     }
  380.     else
  381.     {
  382. #ifdef CHECK_KEYS
  383.       if (key+keyseg->length > key_end)
  384. goto err;
  385. #endif
  386.       memcpy(record+keyseg->start,(byte*) key,
  387.      (size_t) keyseg->length);
  388.       key+= keyseg->length;
  389.     }
  390.   }
  391.   DBUG_RETURN(0);
  392. err:
  393.   DBUG_RETURN(1); /* Crashed row */
  394. } /* _mi_put_key_in_record */
  395. /* Here when key reads are used */
  396. int _mi_read_key_record(MI_INFO *info, my_off_t filepos, byte *buf)
  397. {
  398.   fast_mi_writeinfo(info);
  399.   if (filepos != HA_OFFSET_ERROR)
  400.   {
  401.     if (info->lastinx >= 0)
  402.     { /* Read only key */
  403.       if (_mi_put_key_in_record(info,(uint) info->lastinx,buf))
  404.       {
  405. my_errno=HA_ERR_CRASHED;
  406. return -1;
  407.       }
  408.       info->update|= HA_STATE_AKTIV; /* We should find a record */
  409.       return 0;
  410.     }
  411.     my_errno=HA_ERR_WRONG_INDEX;
  412.   }
  413.   return(-1); /* Wrong data to read */
  414. }
  415.   
  416. /*
  417.   Update auto_increment info
  418.   SYNOPSIS
  419.     update_auto_increment()
  420.     info MyISAM handler
  421.     record Row to update
  422.   IMPLEMENTATION
  423.     Only replace the auto_increment value if it is higher than the previous
  424.     one. For signed columns we don't update the auto increment value if it's
  425.     less than zero.
  426. */
  427. void update_auto_increment(MI_INFO *info,const byte *record)
  428. {
  429.   ulonglong value= 0; /* Store unsigned values here */
  430.   longlong s_value= 0; /* Store signed values here */
  431.   HA_KEYSEG *keyseg= info->s->keyinfo[info->s->base.auto_key-1].seg;
  432.   const uchar *key= (uchar*) record + keyseg->start;
  433.   switch (keyseg->type) {
  434.   case HA_KEYTYPE_INT8:
  435.     s_value= (longlong) *(char*)key;
  436.     break;
  437.   case HA_KEYTYPE_BINARY:
  438.     value=(ulonglong)  *(uchar*) key;
  439.     break;
  440.   case HA_KEYTYPE_SHORT_INT:
  441.     s_value= (longlong) sint2korr(key);
  442.     break;
  443.   case HA_KEYTYPE_USHORT_INT:
  444.     value=(ulonglong) uint2korr(key);
  445.     break;
  446.   case HA_KEYTYPE_LONG_INT:
  447.     s_value= (longlong) sint4korr(key);
  448.     break;
  449.   case HA_KEYTYPE_ULONG_INT:
  450.     value=(ulonglong) uint4korr(key);
  451.     break;
  452.   case HA_KEYTYPE_INT24:
  453.     s_value= (longlong) sint3korr(key);
  454.     break;
  455.   case HA_KEYTYPE_UINT24:
  456.     value=(ulonglong) uint3korr(key);
  457.     break;
  458.   case HA_KEYTYPE_FLOAT:                        /* This shouldn't be used */
  459.   {
  460.     float f_1;
  461.     float4get(f_1,key);
  462.     /* Ignore negative values */
  463.     value = (f_1 < (float) 0.0) ? 0 : (ulonglong) f_1;
  464.     break;
  465.   }
  466.   case HA_KEYTYPE_DOUBLE:                       /* This shouldn't be used */
  467.   {
  468.     double f_1;
  469.     float8get(f_1,key);
  470.     /* Ignore negative values */
  471.     value = (f_1 < 0.0) ? 0 : (ulonglong) f_1;
  472.     break;
  473.   }
  474.   case HA_KEYTYPE_LONGLONG:
  475.     s_value= sint8korr(key);
  476.     break;
  477.   case HA_KEYTYPE_ULONGLONG:
  478.     value= uint8korr(key);
  479.     break;
  480.   default:
  481.     DBUG_ASSERT(0);
  482.     value=0;                                    /* Error */
  483.     break;
  484.   }
  485.   /*
  486.     The following code works becasue if s_value < 0 then value is 0
  487.     and if s_value == 0 then value will contain either s_value or the
  488.     correct value.
  489.   */
  490.   set_if_bigger(info->s->state.auto_increment,
  491.                 (s_value > 0) ? (ulonglong) s_value : value);
  492. }