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

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 check if a row is unique */
  17. #include "myisamdef.h"
  18. #include <m_ctype.h>
  19. my_bool mi_check_unique(MI_INFO *info, MI_UNIQUEDEF *def, byte *record,
  20. ha_checksum unique_hash, my_off_t disk_pos)
  21. {
  22.   my_off_t lastpos=info->lastpos;
  23.   MI_KEYDEF *key= &info->s->keyinfo[def->key];
  24.   uchar *key_buff=info->lastkey+info->s->base.max_key_length;
  25.   DBUG_ENTER("mi_check_unique");
  26.   mi_unique_store(record+key->seg->start, unique_hash);
  27.   _mi_make_key(info,def->key,key_buff,record,0);
  28.   if (_mi_search(info,info->s->keyinfo+def->key,key_buff,MI_UNIQUE_HASH_LENGTH,
  29.  SEARCH_FIND,info->s->state.key_root[def->key]))
  30.   {
  31.     info->page_changed=1; /* Can't optimize read next */
  32.     info->lastpos= lastpos;
  33.     DBUG_RETURN(0); /* No matching rows */
  34.   }
  35.   for (;;)
  36.   {
  37.     if (info->lastpos != disk_pos &&
  38. !(*info->s->compare_unique)(info,def,record,info->lastpos))
  39.     {
  40.       my_errno=HA_ERR_FOUND_DUPP_UNIQUE;
  41.       info->errkey= (int) def->key;
  42.       info->dupp_key_pos= info->lastpos;
  43.       info->page_changed=1; /* Can't optimize read next */
  44.       info->lastpos=lastpos;
  45.       DBUG_PRINT("info",("Found duplicate"));
  46.       DBUG_RETURN(1); /* Found identical  */
  47.     }
  48.     if (_mi_search_next(info,info->s->keyinfo+def->key, info->lastkey,
  49. MI_UNIQUE_HASH_LENGTH, SEARCH_BIGGER,
  50. info->s->state.key_root[def->key]) ||
  51. bcmp(info->lastkey, key_buff, MI_UNIQUE_HASH_LENGTH))
  52.     {
  53.       info->page_changed=1; /* Can't optimize read next */
  54.       info->lastpos=lastpos;
  55.       DBUG_RETURN(0); /* end of tree */
  56.     }
  57.   }
  58. }
  59. /* Calculate a hash for a row */
  60. ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
  61. {
  62.   const byte *pos, *end;
  63.   ha_checksum crc=0;
  64.   MI_KEYSEG *keyseg;
  65.   for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
  66.   {
  67.     enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
  68.     uint length=keyseg->length;
  69.     if (keyseg->null_bit)
  70.     {
  71.       if (record[keyseg->null_pos] & keyseg->null_bit)
  72. continue;
  73.     }
  74.     pos= record+keyseg->start;
  75.     if (keyseg->flag & HA_VAR_LENGTH)
  76.     {
  77.       uint tmp_length=uint2korr(pos);
  78.       pos+=2; /* Skip VARCHAR length */
  79.       set_if_smaller(length,tmp_length);
  80.     }
  81.     else if (keyseg->flag & HA_BLOB_PART)
  82.     {
  83.       uint tmp_length=_mi_calc_blob_length(keyseg->bit_start,pos);
  84.       memcpy_fixed((byte*) &pos,pos+keyseg->bit_start,sizeof(char*));
  85.       if (!length || length > tmp_length)
  86. length=tmp_length; /* The whole blob */
  87.     }
  88.     end= pos+length;
  89.     if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
  90.     {
  91.       uchar *sort_order=keyseg->charset->sort_order;
  92.       while (pos != end)
  93. crc=((crc << 8) +
  94.      (((uchar)  sort_order[*(uchar*) pos++]))) +
  95.   (crc >> (8*sizeof(ha_checksum)-8));
  96.     }
  97.     else
  98.       while (pos != end)
  99. crc=((crc << 8) +
  100.      (((uchar)  *(uchar*) pos++))) +
  101.   (crc >> (8*sizeof(ha_checksum)-8));
  102.   }
  103.   return crc;
  104. }
  105. /*
  106.   Returns 0 if both rows have equal unique value
  107.  */
  108. int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
  109.    my_bool null_are_equal)
  110. {
  111.   const byte *pos_a, *pos_b, *end;
  112.   MI_KEYSEG *keyseg;
  113.   for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
  114.   {
  115.     enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
  116.     uint length=keyseg->length;
  117.     /* If part is NULL it's regarded as different */
  118.     if (keyseg->null_bit)
  119.     {
  120.       uint tmp;
  121.       if ((tmp=(a[keyseg->null_pos] & keyseg->null_bit)) !=
  122.   (uint) (b[keyseg->null_pos] & keyseg->null_bit))
  123. return 1;
  124.       if (tmp)
  125.       {
  126. if (!null_are_equal)
  127.   return 1;
  128. continue;
  129.       }
  130.     }
  131.     pos_a= a+keyseg->start;
  132.     pos_b= b+keyseg->start;
  133.     if (keyseg->flag & HA_VAR_LENGTH)
  134.     {
  135.       uint tmp_length=uint2korr(pos_a);
  136.       if (tmp_length != uint2korr(pos_b))
  137. return 1;
  138.       pos_a+=2; /* Skip VARCHAR length */
  139.       pos_b+=2;
  140.       set_if_smaller(length,tmp_length);
  141.     }
  142.     else if (keyseg->flag & HA_BLOB_PART)
  143.     {
  144.       /* Only compare 'length' characters if length<> 0 */
  145.       uint a_length= _mi_calc_blob_length(keyseg->bit_start,pos_a);
  146.       uint b_length= _mi_calc_blob_length(keyseg->bit_start,pos_b);
  147.       /* Check that a and b are of equal length */
  148.       if (length && a_length > length)
  149. a_length=length;
  150.       if (!length || length > b_length)
  151. length=b_length;
  152.       if (length != a_length)
  153. return 1;
  154.       /* Both strings are at least 'length' long */
  155.       memcpy_fixed((byte*) &pos_a,pos_a+keyseg->bit_start,sizeof(char*));
  156.       memcpy_fixed((byte*) &pos_b,pos_b+keyseg->bit_start,sizeof(char*));
  157.     }
  158.     end= pos_a+length;
  159.     if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
  160.     {
  161.       uchar *sort_order=keyseg->charset->sort_order;
  162.       while (pos_a != end)
  163. if (sort_order[*(uchar*) pos_a++] !=
  164.     sort_order[*(uchar*) pos_b++])
  165.   return 1;
  166.     }
  167.     else
  168.       while (pos_a != end)
  169. if (*pos_a++ != *pos_b++)
  170.   return 1;
  171.   }
  172.   return 0;
  173. }