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

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. /* Functions to handle keys */
  17. #include "myisamdef.h"
  18. #include "m_ctype.h"
  19. #define CHECK_KEYS
  20. static int _mi_put_key_in_record(MI_INFO *info,uint keynr,byte *record);
  21. /*
  22. ** Make a intern key from a record
  23. ** Ret: Length of key
  24. */
  25. uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
  26.   const byte *record, my_off_t filepos)
  27. {
  28.   byte *pos,*end;
  29.   uchar *start;
  30.   reg1 MI_KEYSEG *keyseg;
  31.   DBUG_ENTER("_mi_make_key");
  32.   start=key;
  33.   for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++)
  34.   {
  35.     enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
  36.     uint length=keyseg->length;
  37.     if (keyseg->null_bit)
  38.     {
  39.       if (record[keyseg->null_pos] & keyseg->null_bit)
  40.       {
  41. *key++= 0; /* NULL in key */
  42. continue;
  43.       }
  44.       *key++=1; /* Not NULL */
  45.     }
  46.     pos= (byte*) record+keyseg->start;
  47.     if (keyseg->flag & HA_SPACE_PACK)
  48.     {
  49.       end=pos+length;
  50.       if (type != HA_KEYTYPE_NUM)
  51.       {
  52. while (end > pos && end[-1] == ' ')
  53.   end--;
  54.       }
  55.       else
  56.       {
  57. while (pos < end && pos[0] == ' ')
  58.   pos++;
  59.       }
  60.       length=(uint) (end-pos);
  61.       store_key_length_inc(key,length);
  62.       memcpy((byte*) key,(byte*) pos,(size_t) length);
  63.       key+=length;
  64.       continue;
  65.     }
  66.     if (keyseg->flag & HA_VAR_LENGTH)
  67.     {
  68.       uint tmp_length=uint2korr(pos);
  69.       pos+=2; /* Skip VARCHAR length */
  70.       set_if_smaller(length,tmp_length);
  71.       store_key_length_inc(key,length);
  72.     }
  73.     else if (keyseg->flag & HA_BLOB_PART)
  74.     {
  75.       uint tmp_length=_mi_calc_blob_length(keyseg->bit_start,pos);
  76.       memcpy_fixed((byte*) &pos,pos+keyseg->bit_start,sizeof(char*));
  77.       set_if_smaller(length,tmp_length);
  78.       store_key_length_inc(key,length);
  79.     }
  80.     else if (keyseg->flag & HA_SWAP_KEY)
  81.     { /* Numerical column */
  82. #ifdef NAN_TEST
  83.       float float_nr;
  84.       double dbl_nr;
  85.       if (type == HA_KEYTYPE_FLOAT)
  86.       {
  87. float_nr=float4get(pos);
  88. if (float_nr == (float) FLT_MAX)
  89. {
  90.   float_nr= (float) FLT_MAX;
  91.   pos= (byte*) &float_nr;
  92. }
  93.       }
  94.       else if (type == HA_KEYTYPE_DOUBLE)
  95.       {
  96. dbl_nr=float8get(key);
  97. if (dbl_nr == DBL_MAX)
  98. {
  99.   dbl_nr=DBL_MAX;
  100.   pos=(byte*) &dbl_nr;
  101. }
  102.       }
  103. #endif
  104.       pos+=length;
  105.       while (length--)
  106.       {
  107. *key++ = *--pos;
  108.       }
  109.       continue;
  110.     }
  111.     memcpy((byte*) key, pos, length);
  112.     key+= length;
  113.   }
  114.   _mi_dpointer(info,key,filepos);
  115.   DBUG_PRINT("exit",("keynr: %d",keynr));
  116.   DBUG_DUMP("key",(byte*) start,(uint) (key-start)+keyseg->length);
  117.   DBUG_EXECUTE("key",
  118.        _mi_print_key(DBUG_FILE,info->s->keyinfo[keynr].seg,start,
  119.      (uint) (key-start)););
  120.   DBUG_RETURN((uint) (key-start)); /* Return keylength */
  121. } /* _mi_make_key */
  122. /* Pack a key to intern format from given format (c_rkey) */
  123. /* returns length of packed key */
  124. uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
  125.   uint k_length)
  126. {
  127.   uint length;
  128.   uchar *pos,*end,*start_key=key;
  129.   reg1 MI_KEYSEG *keyseg;
  130.   enum ha_base_keytype type;
  131.   DBUG_ENTER("_mi_pack_key");
  132.   start_key=key;
  133.   for (keyseg=info->s->keyinfo[keynr].seg ;
  134.        keyseg->type && (int) k_length > 0;
  135.        old+=keyseg->length, keyseg++)
  136.   {
  137.     length=min((uint) keyseg->length,(uint) k_length);
  138.     type=(enum ha_base_keytype) keyseg->type;
  139.     if (keyseg->null_bit)
  140.     {
  141.       k_length--;
  142.       if (!(*key++= (char) 1-*old++)) /* Copy null marker */
  143.       {
  144. k_length-=length;
  145. continue; /* Found NULL */
  146.       }
  147.     }
  148.     pos=old;
  149.     if (keyseg->flag & HA_SPACE_PACK)
  150.     {
  151.       end=pos+length;
  152.       if (type != HA_KEYTYPE_NUM)
  153.       {
  154. while (end > pos && end[-1] == ' ')
  155.   end--;
  156.       }
  157.       else
  158.       {
  159. while (pos < end && pos[0] == ' ')
  160.   pos++;
  161.       }
  162.       k_length-=length;
  163.       length=(uint) (end-pos);
  164.       store_key_length_inc(key,length);
  165.       memcpy((byte*) key,pos,(size_t) length);
  166.       key+= length;
  167.       continue;
  168.     }
  169.     else if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
  170.     {
  171.       /* Length of key-part used with mi_rkey() always 2 */
  172.       uint tmp_length=uint2korr(pos);
  173.       k_length-= 2+length;
  174.       set_if_smaller(length,tmp_length); /* Safety */
  175.       store_key_length_inc(key,length);
  176.       old+=2; /* Skipp length */
  177.       memcpy((byte*) key, pos+2,(size_t) length);
  178.       key+= length;
  179.       continue;
  180.     }
  181.     else if (keyseg->flag & HA_SWAP_KEY)
  182.     { /* Numerical column */
  183.       pos+=length;
  184.       k_length-=length;
  185.       while (length--)
  186.       {
  187. *key++ = *--pos;
  188.       }
  189.       continue;
  190.     }
  191.     memcpy((byte*) key,pos,(size_t) length);
  192.     key+= length;
  193.     k_length-=length;
  194.   }
  195. #ifdef NOT_USED
  196.   if (keyseg->type)
  197.   {
  198.     /* Part-key ; fill with ASCII 0 for easier searching */
  199.     length= (uint) -k_length; /* unused part of last key */
  200.     do
  201.     {
  202.       if (keyseg->flag & HA_NULL_PART)
  203. length++;
  204.       if (keyseg->flag & HA_SPACE_PACK)
  205. length+=2;
  206.       else
  207. length+= keyseg->length;
  208.       keyseg++;
  209.     } while (keyseg->type);
  210.     bzero((byte*) key,length);
  211.     key+=length;
  212.   }
  213. #endif
  214.   DBUG_RETURN((uint) (key-start_key));
  215. } /* _mi_pack_key */
  216. /* Put a key in record */
  217. /* Used when only-keyread is wanted */
  218. static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
  219.  byte *record)
  220. {
  221.   reg2 byte *key;
  222.   byte *pos,*key_end;
  223.   reg1 MI_KEYSEG *keyseg;
  224.   byte *blob_ptr;
  225.   DBUG_ENTER("_mi_put_key_in_record");
  226.   if (info->blobs && info->s->keyinfo[keynr].flag & HA_VAR_LENGTH_KEY)
  227.   {
  228.     if (!(blob_ptr=
  229.   mi_fix_rec_buff_for_blob(info, info->s->keyinfo[keynr].keylength)))
  230.       goto err;
  231.   }
  232.   key=(byte*) info->lastkey;
  233.   key_end=key+info->lastkey_length;
  234.   for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++)
  235.   {
  236.     if (keyseg->null_bit)
  237.     {
  238.       if (!*key++)
  239.       {
  240. record[keyseg->null_pos]|= keyseg->null_bit;
  241. continue;
  242.       }
  243.       record[keyseg->null_pos]&= ~keyseg->null_bit;
  244.     }
  245.     if (keyseg->flag & HA_SPACE_PACK)
  246.     {
  247.       uint length;
  248.       get_key_length(length,key);
  249. #ifdef CHECK_KEYS
  250.       if (length > keyseg->length || key+length > key_end)
  251. goto err;
  252. #endif
  253.       pos= record+keyseg->start;
  254.       if (keyseg->type != (int) HA_KEYTYPE_NUM)
  255.       {
  256. memcpy(pos,key,(size_t) length);
  257. bfill(pos+length,keyseg->length-length,' ');
  258.       }
  259.       else
  260.       {
  261. bfill(pos,keyseg->length-length,' ');
  262. memcpy(pos+keyseg->length-length,key,(size_t) length);
  263.       }
  264.       key+=length;
  265.       continue;
  266.     }
  267.     if (keyseg->flag & HA_VAR_LENGTH)
  268.     {
  269.       uint length;
  270.       get_key_length(length,key);
  271. #ifdef CHECK_KEYS
  272.       if (length > keyseg->length || key+length > key_end)
  273. goto err;
  274. #endif
  275.       memcpy(record+keyseg->start,(byte*) key, length);
  276.       key+= length;
  277.     }
  278.     else if (keyseg->flag & HA_BLOB_PART)
  279.     {
  280.       uint length;
  281.       get_key_length(length,key);
  282. #ifdef CHECK_KEYS
  283.       if (length > keyseg->length || key+length > key_end)
  284. goto err;
  285. #endif
  286.       memcpy(record+keyseg->start+keyseg->bit_start,
  287.      (char*) &blob_ptr,sizeof(char*));
  288.       memcpy(blob_ptr,key,length);
  289.       blob_ptr+=length;
  290.       _my_store_blob_length(record+keyseg->start,
  291.     (uint) keyseg->bit_start,length);
  292.       key+=length;
  293.     }
  294.     else if (keyseg->flag & HA_SWAP_KEY)
  295.     {
  296.       byte *to=  record+keyseg->start+keyseg->length;
  297.       byte *end= key+keyseg->length;
  298. #ifdef CHECK_KEYS
  299.       if (end > key_end)
  300. goto err;
  301. #endif
  302.       do
  303.       {
  304.  *--to= *key++;
  305.       } while (key != end);
  306.       continue;
  307.     }
  308.     else
  309.     {
  310. #ifdef CHECK_KEYS
  311.       if (key+keyseg->length > key_end)
  312. goto err;
  313. #endif
  314.       memcpy(record+keyseg->start,(byte*) key,
  315.      (size_t) keyseg->length);
  316.       key+= keyseg->length;
  317.     }
  318.   }
  319.   DBUG_RETURN(0);
  320. err:
  321.   DBUG_RETURN(1); /* Crashed row */
  322. } /* _mi_put_key_in_record */
  323. /* Here when key reads are used */
  324. int _mi_read_key_record(MI_INFO *info, my_off_t filepos, byte *buf)
  325. {
  326.   VOID(_mi_writeinfo(info,0));
  327.   if (filepos != HA_OFFSET_ERROR)
  328.   {
  329.     if (info->lastinx >= 0)
  330.     { /* Read only key */
  331.       if (_mi_put_key_in_record(info,(uint) info->lastinx,buf))
  332.       {
  333. my_errno=HA_ERR_CRASHED;
  334. return -1;
  335.       }
  336.       info->update|= HA_STATE_AKTIV; /* We should find a record */
  337.       return 0;
  338.     }
  339.     my_errno=HA_ERR_WRONG_INDEX;
  340.   }
  341.   return(-1); /* Wrong data to read */
  342. }
  343. /* Update auto_increment info */
  344. void update_auto_increment(MI_INFO *info,const byte *record)
  345. {
  346.   ulonglong value;
  347.   MI_KEYSEG *keyseg=info->s->keyinfo[info->s->base.auto_key-1].seg;
  348.   const uchar *key=(uchar*) record+keyseg->start;
  349.   switch (keyseg->type) {
  350.   case HA_KEYTYPE_INT8:
  351.   case HA_KEYTYPE_BINARY:
  352.     value=(ulonglong)  *(uchar*) key;
  353.     break;
  354.   case HA_KEYTYPE_SHORT_INT:
  355.   case HA_KEYTYPE_USHORT_INT:
  356.     value=(ulonglong) uint2korr(key);
  357.     break;
  358.   case HA_KEYTYPE_LONG_INT:
  359.   case HA_KEYTYPE_ULONG_INT:
  360.     value=(ulonglong) uint4korr(key);
  361.     break;
  362.   case HA_KEYTYPE_INT24:
  363.   case HA_KEYTYPE_UINT24:
  364.     value=(ulonglong) uint3korr(key);
  365.     break;
  366.   case HA_KEYTYPE_FLOAT: /* This shouldn't be used */
  367.   {
  368.     float f_1;
  369.     float4get(f_1,key);
  370.     value = (ulonglong) f_1;
  371.     break;
  372.   }
  373.   case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */
  374.   {
  375.     double f_1;
  376.     float8get(f_1,key);
  377.     value = (ulonglong) f_1;
  378.     break;
  379.   }
  380.   case HA_KEYTYPE_LONGLONG:
  381.   case HA_KEYTYPE_ULONGLONG:
  382.     value= uint8korr(key);
  383.     break;
  384.   default:
  385.     value=0; /* Error */
  386.     break;
  387.   }
  388.   set_if_bigger(info->s->state.auto_increment,value);
  389. }